@bgord/bun 0.11.2 → 0.12.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.
Files changed (55) hide show
  1. package/dist/bots.vo.d.ts +2 -0
  2. package/dist/bots.vo.d.ts.map +1 -0
  3. package/dist/bots.vo.js +4 -0
  4. package/dist/bots.vo.js.map +1 -0
  5. package/dist/dispatching-event-store.d.ts +15 -0
  6. package/dist/dispatching-event-store.d.ts.map +1 -0
  7. package/dist/dispatching-event-store.js +13 -0
  8. package/dist/dispatching-event-store.js.map +1 -0
  9. package/dist/event-handler.service.d.ts +5 -2
  10. package/dist/event-handler.service.d.ts.map +1 -1
  11. package/dist/event-handler.service.js.map +1 -1
  12. package/dist/event-publisher.types.d.ts +4 -0
  13. package/dist/event-publisher.types.d.ts.map +1 -0
  14. package/dist/event-publisher.types.js +2 -0
  15. package/dist/event-publisher.types.js.map +1 -0
  16. package/dist/event-store.d.ts +18 -0
  17. package/dist/event-store.d.ts.map +1 -0
  18. package/dist/event-store.js +21 -0
  19. package/dist/event-store.js.map +1 -0
  20. package/dist/event-stream.vo.d.ts +4 -0
  21. package/dist/event-stream.vo.d.ts.map +1 -0
  22. package/dist/event-stream.vo.js +3 -0
  23. package/dist/event-stream.vo.js.map +1 -0
  24. package/dist/event.types.d.ts +13 -0
  25. package/dist/event.types.d.ts.map +1 -0
  26. package/dist/event.types.js +2 -0
  27. package/dist/event.types.js.map +1 -0
  28. package/dist/index.d.ts +5 -1
  29. package/dist/index.d.ts.map +1 -1
  30. package/dist/index.js +5 -1
  31. package/dist/index.js.map +1 -1
  32. package/dist/setup.service.d.ts.map +1 -1
  33. package/dist/setup.service.js +3 -0
  34. package/dist/setup.service.js.map +1 -1
  35. package/dist/to-event-map.types.d.ts +6 -0
  36. package/dist/to-event-map.types.d.ts.map +1 -0
  37. package/dist/to-event-map.types.js +2 -0
  38. package/dist/to-event-map.types.js.map +1 -0
  39. package/dist/tsconfig.tsbuildinfo +1 -1
  40. package/package.json +2 -1
  41. package/src/bots.vo.ts +3 -0
  42. package/src/dispatching-event-store.ts +28 -0
  43. package/src/event-handler.service.ts +3 -2
  44. package/src/event-publisher.types.ts +3 -0
  45. package/src/event-store.ts +44 -0
  46. package/src/event-stream.vo.ts +4 -0
  47. package/src/event.types.ts +16 -0
  48. package/src/index.ts +5 -1
  49. package/src/setup.service.ts +3 -0
  50. package/src/to-event-map.types.ts +3 -0
  51. package/dist/event.vo.d.ts +0 -20
  52. package/dist/event.vo.d.ts.map +0 -1
  53. package/dist/event.vo.js +0 -23
  54. package/dist/event.vo.js.map +0 -1
  55. package/src/event.vo.ts +0 -29
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bgord/bun",
3
- "version": "0.11.2",
3
+ "version": "0.12.1",
4
4
  "license": "MIT",
5
5
  "type": "module",
6
6
  "author": "Bartosz Gordon",
@@ -36,6 +36,7 @@
36
36
  },
37
37
  "dependencies": {
38
38
  "@bgord/tools": "0.9.3",
39
+ "@hono/ua-blocker": "^0.1.2",
39
40
  "check-disk-space": "3.4.0",
40
41
  "croner": "9.1.0",
41
42
  "hcaptcha": "0.2.0",
package/src/bots.vo.ts ADDED
@@ -0,0 +1,3 @@
1
+ export const BOTS_REGEX =
2
+ // cspell:disable-next-line
3
+ /(AI2BOT|AI2BOT-DOLMA|AIHITBOT|AMAZONBOT|ANDIBOT|ANTHROPIC-AI|APPLEBOT|APPLEBOT-EXTENDED|BEDROCKBOT|BRIGHTBOT 1.0|BYTESPIDER|CCBOT|CHATGPT-USER|CLAUDE-SEARCHBOT|CLAUDE-USER|CLAUDE-WEB|CLAUDEBOT|COHERE-AI|COHERE-TRAINING-DATA-CRAWLER|COTOYOGI|CRAWLSPACE|DIFFBOT|DUCKASSISTBOT|ECHOBOXBOT|FACEBOOKBOT|FACEBOOKEXTERNALHIT|FACTSET_SPYDERBOT|FIRECRAWLAGENT|FRIENDLYCRAWLER|GOOGLE-CLOUDVERTEXBOT|GOOGLE-EXTENDED|GOOGLEOTHER|GOOGLEOTHER-IMAGE|GOOGLEOTHER-VIDEO|GPTBOT|IASKSPIDER\/2.0|ICC-CRAWLER|IMAGESIFTBOT|IMG2DATASET|ISSCYBERRISKCRAWLER|KANGAROO BOT|META-EXTERNALAGENT|META-EXTERNALAGENT|META-EXTERNALFETCHER|META-EXTERNALFETCHER|MISTRALAI-USER\/1.0|MYCENTRALAISCRAPERBOT|NOVAACT|OAI-SEARCHBOT|OMGILI|OMGILIBOT|OPERATOR|PANGUBOT|PANSCIENT|PANSCIENT.COM|PERPLEXITY-USER|PERPLEXITYBOT|PETALBOT|PHINDBOT|POSEIDON RESEARCH CRAWLER|QUALIFIEDBOT|QUILLBOT|QUILLBOT.COM|SBINTUITIONSBOT|SCRAPY|SEMRUSHBOT|SEMRUSHBOT-BA|SEMRUSHBOT-CT|SEMRUSHBOT-OCOB|SEMRUSHBOT-SI|SEMRUSHBOT-SWA|SIDETRADE INDEXER BOT|TIKTOKSPIDER|TIMPIBOT|VELENPUBLICWEBCRAWLER|WEBZIO-EXTENDED|WPBOT|YANDEXADDITIONAL|YANDEXADDITIONALBOT|YOUBOT)/;
@@ -0,0 +1,28 @@
1
+ import { z } from "zod/v4";
2
+ import type { GenericEventSchema, GenericParsedEventSchema } from "./event.types";
3
+ import type { EventPublisher } from "./event-publisher.types";
4
+ import { EventStore as BaseStore } from "./event-store";
5
+ import type { EventStreamType } from "./event-stream.vo";
6
+ import { ToEventMap } from "./to-event-map.types";
7
+
8
+ export class DispatchingEventStore<AllEvents extends GenericEventSchema> extends BaseStore<AllEvents> {
9
+ constructor(
10
+ config: {
11
+ finder: (stream: EventStreamType, names: string[]) => Promise<z.infer<GenericEventSchema>[]>;
12
+ inserter: (events: z.infer<GenericParsedEventSchema>[]) => Promise<void>;
13
+ },
14
+ private readonly publisher: EventPublisher<ToEventMap<z.infer<AllEvents>>>,
15
+ ) {
16
+ super(config);
17
+ }
18
+
19
+ async save(events: z.infer<AllEvents>[]) {
20
+ await super.save(events);
21
+
22
+ await Promise.all(
23
+ events.map((event) =>
24
+ this.publisher.emit(event.name as keyof ToEventMap<z.infer<AllEvents>>, event as any),
25
+ ),
26
+ );
27
+ }
28
+ }
@@ -1,10 +1,11 @@
1
- import type { EventType } from "./event.vo";
1
+ import { z } from "zod/v4";
2
+ import type { GenericEventSchema } from "./event.types";
2
3
  import { Logger } from "./logger.service";
3
4
 
4
5
  export class EventHandler {
5
6
  constructor(private readonly logger: Logger) {}
6
7
 
7
- handle<T extends Pick<EventType, "name">>(fn: (event: T) => Promise<void>) {
8
+ handle<T extends { name: z.infer<GenericEventSchema["shape"]["name"]> }>(fn: (event: T) => Promise<void>) {
8
9
  return async (event: T) => {
9
10
  try {
10
11
  await fn(event);
@@ -0,0 +1,3 @@
1
+ export interface EventPublisher<EventMap extends Record<string, any>> {
2
+ emit<Name extends keyof EventMap>(name: Name, payload: EventMap[Name]): Promise<void>;
3
+ }
@@ -0,0 +1,44 @@
1
+ import { z } from "zod/v4";
2
+ import type { GenericEventSchema, GenericParsedEventSchema } from "./event.types";
3
+ import type { EventStreamType } from "./event-stream.vo";
4
+
5
+ export type EventNameType = z.infer<GenericEventSchema["shape"]["name"]>;
6
+
7
+ type FindEventsHandler = (
8
+ stream: EventStreamType,
9
+ acceptedEventsNames: EventNameType[],
10
+ ) => Promise<z.infer<GenericEventSchema>[]>;
11
+
12
+ type InserterEventsHandler = (events: z.infer<GenericParsedEventSchema>[]) => Promise<void>;
13
+
14
+ type EventStoreConfigType = {
15
+ finder: FindEventsHandler;
16
+ inserter: InserterEventsHandler;
17
+ };
18
+
19
+ export class EventStore<AllEvents extends GenericEventSchema> {
20
+ constructor(private readonly config: EventStoreConfigType) {}
21
+
22
+ async find<AcceptedEvents extends readonly AllEvents[]>(
23
+ acceptedEvents: AcceptedEvents,
24
+ stream: EventStreamType,
25
+ ): Promise<z.infer<AcceptedEvents[number]>[]> {
26
+ const acceptedEventsNames = acceptedEvents.map((event) => event.shape.name.value);
27
+
28
+ const rows = await this.config.finder(stream, acceptedEventsNames);
29
+
30
+ return rows
31
+ .map((row) => ({ ...row, payload: JSON.parse(row.payload) }))
32
+ .map((row) => acceptedEvents.find((event) => event.shape.name.value === row.name)?.parse(row))
33
+ .filter((event): event is z.infer<AcceptedEvents[number]> => event !== undefined);
34
+ }
35
+
36
+ async save(events: z.infer<AllEvents>[]) {
37
+ await this.config.inserter(
38
+ events.map((event) => ({
39
+ ...event,
40
+ payload: JSON.stringify(event.payload),
41
+ })),
42
+ );
43
+ }
44
+ }
@@ -0,0 +1,4 @@
1
+ import { z } from "zod/v4";
2
+
3
+ export const EventStream = z.string().min(1).max(256);
4
+ export type EventStreamType = z.infer<typeof EventStream>;
@@ -0,0 +1,16 @@
1
+ import { z } from "zod/v4";
2
+
3
+ export type GenericEventSchema = z.ZodObject<{
4
+ id: z.ZodType<string>;
5
+ createdAt: z.ZodType<number>;
6
+ stream: z.ZodString;
7
+ name: z.ZodLiteral<string>;
8
+ version: z.ZodLiteral<number>;
9
+ payload: z.ZodType<any>;
10
+ }>;
11
+
12
+ export type GenericParsedEventSchema = z.ZodObject<
13
+ Omit<GenericEventSchema["shape"], "payload"> & {
14
+ payload: z.ZodString;
15
+ }
16
+ >;
package/src/index.ts CHANGED
@@ -10,13 +10,16 @@ export * from "./cache-static-files.middleware";
10
10
  export * from "./context.middleware";
11
11
  export * from "./correlation-id.vo";
12
12
  export * from "./decorators.service";
13
+ export * from "./dispatching-event-store";
13
14
  export * from "./download-file.service";
14
15
  export * from "./encryption.service";
15
16
  export * from "./env-validator.service";
16
17
  export * from "./etag-extractor.middleware";
17
- export * from "./event.vo";
18
+ export * from "./event.types";
18
19
  export * from "./event-handler.service";
19
20
  export * from "./event-logger.service";
21
+ export * from "./event-store";
22
+ export * from "./event-stream.vo";
20
23
  export * from "./file-location.service";
21
24
  export * from "./file-uploader.middleware";
22
25
  export * from "./graceful-shutdown.service";
@@ -49,6 +52,7 @@ export * from "./simulated-error.middleware";
49
52
  export * from "./sitemap.service";
50
53
  export * from "./slower.middleware";
51
54
  export * from "./time-zone-offset.middleware";
55
+ export * from "./to-event-map.types";
52
56
  export * from "./uptime.service";
53
57
  export * from "./url-wo-trailing-slash.vo";
54
58
  export * from "./username.vo";
@@ -1,4 +1,5 @@
1
1
  import * as tools from "@bgord/tools";
2
+ import { uaBlocker } from "@hono/ua-blocker";
2
3
  import { bodyLimit } from "hono/body-limit";
3
4
  import { cors } from "hono/cors";
4
5
  import { languageDetector } from "hono/language";
@@ -7,6 +8,7 @@ import { secureHeaders } from "hono/secure-headers";
7
8
  import { timing } from "hono/timing";
8
9
 
9
10
  import { ApiVersion } from "./api-version.middleware";
11
+ import { BOTS_REGEX } from "./bots.vo";
10
12
  import { Context } from "./context.middleware";
11
13
  import { ETagExtractor } from "./etag-extractor.middleware";
12
14
  import { HttpLogger } from "./http-logger.middleware";
@@ -25,6 +27,7 @@ export class Setup {
25
27
  return [
26
28
  secureHeaders(),
27
29
  bodyLimit({ maxSize: BODY_LIMIT_MAX_SIZE }),
30
+ uaBlocker({ blocklist: BOTS_REGEX }),
28
31
  ApiVersion.attach,
29
32
  cors({ origin: "*" }),
30
33
  languageDetector({
@@ -0,0 +1,3 @@
1
+ export type ToEventMap<E extends { name: string }> = {
2
+ [Ev in E as Ev["name"]]: Ev;
3
+ };
@@ -1,20 +0,0 @@
1
- import { z } from "zod/v4";
2
- export declare const Event: z.ZodObject<{
3
- id: z.ZodDefault<z.ZodUUID>;
4
- createdAt: z.ZodDate;
5
- stream: z.ZodString;
6
- name: z.ZodString;
7
- version: z.ZodNumber;
8
- payload: z.ZodPipe<z.ZodRecord<z.ZodString, z.ZodAny>, z.ZodTransform<string, Record<string, any>>>;
9
- }, z.core.$strip>;
10
- export declare const ParsedEvent: z.ZodObject<{
11
- id: z.ZodDefault<z.ZodUUID>;
12
- createdAt: z.ZodDate;
13
- stream: z.ZodString;
14
- name: z.ZodString;
15
- version: z.ZodNumber;
16
- payload: z.ZodRecord<z.ZodString, z.ZodAny>;
17
- }, z.core.$strip>;
18
- export type EventType = z.infer<typeof Event>;
19
- export type ParsedEventType = z.infer<typeof ParsedEvent>;
20
- //# sourceMappingURL=event.vo.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event.vo.d.ts","sourceRoot":"","sources":["../src/event.vo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAI3B,eAAO,MAAM,KAAK;;;;;;;iBAmBhB,CAAC;AAEH,eAAO,MAAM,WAAW;;;;;;;iBAAoE,CAAC;AAE7F,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAC;AAC9C,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,WAAW,CAAC,CAAC"}
package/dist/event.vo.js DELETED
@@ -1,23 +0,0 @@
1
- import { z } from "zod/v4";
2
- import { UUID } from "./uuid.vo";
3
- export const Event = z.object({
4
- id: UUID,
5
- createdAt: z.date(),
6
- stream: z.string().min(1),
7
- name: z.string().min(1),
8
- version: z.number().int().positive(),
9
- payload: z
10
- .record(z.string(), z.any())
11
- .refine((value) => {
12
- try {
13
- JSON.parse(JSON.stringify(value));
14
- return true;
15
- }
16
- catch (_error) {
17
- return false;
18
- }
19
- })
20
- .transform((value) => JSON.stringify(value)),
21
- });
22
- export const ParsedEvent = Event.merge(z.object({ payload: z.record(z.string(), z.any()) }));
23
- //# sourceMappingURL=event.vo.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"event.vo.js","sourceRoot":"","sources":["../src/event.vo.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,QAAQ,CAAC;AAE3B,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAEjC,MAAM,CAAC,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,EAAE,EAAE,IAAI;IACR,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE;IAEnB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAEzB,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACvB,OAAO,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,QAAQ,EAAE;IACpC,OAAO,EAAE,CAAC;SACP,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;SAC3B,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE;QAChB,IAAI,CAAC;YACH,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;YAClC,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,OAAO,MAAM,EAAE,CAAC;YAChB,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC,CAAC;SACD,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;CAC/C,CAAC,CAAC;AAEH,MAAM,CAAC,MAAM,WAAW,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC"}
package/src/event.vo.ts DELETED
@@ -1,29 +0,0 @@
1
- import { z } from "zod/v4";
2
-
3
- import { UUID } from "./uuid.vo";
4
-
5
- export const Event = z.object({
6
- id: UUID,
7
- createdAt: z.date(),
8
-
9
- stream: z.string().min(1),
10
-
11
- name: z.string().min(1),
12
- version: z.number().int().positive(),
13
- payload: z
14
- .record(z.string(), z.any())
15
- .refine((value) => {
16
- try {
17
- JSON.parse(JSON.stringify(value));
18
- return true;
19
- } catch (_error) {
20
- return false;
21
- }
22
- })
23
- .transform((value) => JSON.stringify(value)),
24
- });
25
-
26
- export const ParsedEvent = Event.merge(z.object({ payload: z.record(z.string(), z.any()) }));
27
-
28
- export type EventType = z.infer<typeof Event>;
29
- export type ParsedEventType = z.infer<typeof ParsedEvent>;