@twasik4/pocket-service 1.0.3 → 1.1.0

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.
@@ -1,25 +0,0 @@
1
- export type RedisStreamHandlerContext = {
2
- service: string;
3
- emit: (ev: {
4
- type: string;
5
- data: Record<string, string | number | boolean | null>;
6
- }) => Promise<void>;
7
- log: {
8
- info: (msg: string) => void;
9
- warn: (msg: string) => void;
10
- error: (msg: string) => void;
11
- };
12
- };
13
- export type RedisStreamEventHandler = {
14
- type: string;
15
- execute: (
16
- ev: Record<string, any>,
17
- ctx: RedisStreamHandlerContext,
18
- ) => Promise<void>;
19
- };
20
- export function redisStreamHandler(
21
- type: string,
22
- fn: RedisStreamEventHandler["execute"],
23
- ): RedisStreamEventHandler {
24
- return { type, execute: fn };
25
- }
@@ -1,59 +0,0 @@
1
- import { NextFunction, Request, Response } from "express";
2
- import { Logger } from "winston";
3
-
4
- export type Message = {
5
- type: string;
6
- userId: string;
7
- teamId: string;
8
- timestamp: number;
9
- payload: Record<string, string | number | boolean | null>;
10
- };
11
- export type ExpressMiddleware = (
12
- req: Request,
13
- res: Response,
14
- next: NextFunction,
15
- ) => void;
16
- export type BaseExpressOptions = {
17
- /**
18
- * Don't include the default health check and metrics routes.
19
- */
20
- omitDefaultRoutes?: boolean;
21
- /**
22
- * Whether to parse incoming request bodies as JSON.
23
- */
24
- asJson: boolean;
25
- /**
26
- * An array of custom Express middleware functions to apply to the Express app globally (before all routes).
27
- */
28
- customMiddleware?: ExpressMiddleware[];
29
- /**
30
- * Whether to allow CORS requests with credentials (cookies, authorization headers, etc.). This option is only relevant if CORS is enabled via either `corsFn` or `corsWhitelist`.
31
- */
32
- credentials?: boolean;
33
- };
34
- export type ExpressOptionsWithCorsFn = BaseExpressOptions & {
35
- /**
36
- * A function to determine whether to allow CORS requests from a given origin.
37
- * @param origin The origin of the request.
38
- * @param callback A callback function to indicate whether the origin is allowed.
39
- */
40
- corsFn: (
41
- origin: string | undefined,
42
- callback: (err: Error | null, allow?: boolean) => void,
43
- ) => void;
44
- };
45
- export type ExpressOptionsWithCorsWhitelist = BaseExpressOptions & {
46
- /**
47
- * An array of allowed origins for CORS requests. If the origin of an incoming request is in this whitelist, the request will be allowed.
48
- */
49
- corsWhitelist: string[];
50
- };
51
- export type ExpressOptions =
52
- | ExpressOptionsWithCorsFn
53
- | ExpressOptionsWithCorsWhitelist;
54
- export type CustomModuleFactory = (log: Logger) => boolean | Promise<boolean>;
55
- export type CustomModules = {
56
- init: CustomModuleFactory;
57
- shutdown?: CustomModuleFactory;
58
- name: string;
59
- }[];
@@ -1,19 +0,0 @@
1
- import * as crypto from "crypto";
2
-
3
- export function generateRandomHexString(length: number): string {
4
- if (length % 2 !== 0) {
5
- throw new Error("Length must be an even number");
6
- }
7
-
8
- const numBytes = length / 2;
9
- const randomBytes = crypto.randomBytes(numBytes);
10
- return randomBytes.toString("hex");
11
- }
12
-
13
- export function getUseableDatesFromMs(ms: number) {
14
- const seconds = Math.floor((ms / 1000) % 60);
15
- const minutes = Math.floor((ms / (1000 * 60)) % 60);
16
- const hours = Math.floor((ms / (1000 * 60 * 60)) % 24);
17
- const days = Math.floor(ms / (1000 * 60 * 60 * 24));
18
- return { days, hours, minutes, seconds };
19
- }
@@ -1,92 +0,0 @@
1
- /// <reference types="vitest/globals" />
2
- import z from "zod";
3
- import {
4
- defineMongoCollection,
5
- MongoCollectionDefinition,
6
- } from "../src/workers/db/mongo/mongo";
7
- import { MongoMemoryServer } from "mongodb-memory-server";
8
- import { Service } from "../src/workers/service";
9
-
10
- describe("MongoDB Dependency", () => {
11
- let service: Service<{
12
- testCollection: MongoCollectionDefinition<
13
- {
14
- name: string;
15
- },
16
- {}
17
- >;
18
- }>;
19
- let mongoServer: MongoMemoryServer;
20
-
21
- beforeAll(async () => {
22
- mongoServer = await MongoMemoryServer.create();
23
- const uri = mongoServer.getUri();
24
- service = new Service()
25
- .withName("admin-service")
26
- .withPort(4120)
27
- .withRedis("redis://localhost:6379")
28
- .withMongo({
29
- dbName: "test",
30
- uri,
31
- collections: {
32
- testCollection: defineMongoCollection({
33
- schema: z.object({
34
- name: z.string(),
35
- }),
36
- }),
37
- },
38
- })
39
- .build();
40
- });
41
-
42
- afterEach(async () => {
43
- await service.db.testCollection.delete({});
44
- });
45
-
46
- afterAll(async () => {
47
- await mongoServer.stop();
48
- });
49
-
50
- it("Should contain the custom collection", () => {
51
- expect(service.db).toHaveProperty("testCollection");
52
- });
53
-
54
- it("Should not contain undefined collection", () => {
55
- expect(() => service.db).not.toHaveProperty("undefinedCollection");
56
- });
57
-
58
- it("Should be initialized", () => {
59
- expect(() => service.mongo).not.toThrow();
60
- });
61
-
62
- it("Should return an empty array when getting from an empty collection", async () => {
63
- const res = await service.db.testCollection.get();
64
- expect(res).toEqual([]);
65
- });
66
-
67
- it("Should insert and retrieve documents correctly", async () => {
68
- await service.db.testCollection.insert({ name: "test" });
69
- const res = await service.db.testCollection.get({});
70
- expect(res.length).toBe(1);
71
- expect(res[0].name).toEqual("test");
72
- });
73
-
74
- it("Should delete documents correctly", async () => {
75
- await service.db.testCollection.insert({ name: "toDelete" });
76
- await service.db.testCollection.delete({ name: "toDelete" });
77
- const res = await service.db.testCollection.get({ name: "toDelete" });
78
- expect(res).toEqual([]);
79
- });
80
-
81
- it("Should update documents correctly", async () => {
82
- await service.db.testCollection.insert({ name: "toUpdate" });
83
- await service.db.testCollection.updateOne(
84
- { name: "toUpdate" },
85
- { name: "updated" },
86
- );
87
- const res = await service.db.testCollection.get({ name: "updated" });
88
- expect(res.length).toBe(1);
89
- expect(res[0].name).toEqual("updated");
90
- console.log("Updated document:", res[0]);
91
- });
92
- });
@@ -1,36 +0,0 @@
1
- /// <reference types="vitest/globals" />
2
- import { Service } from "../src/workers/service";
3
-
4
- describe.only("Redis Dependency", () => {
5
- let service: Service<{}>;
6
-
7
- beforeAll(async () => {
8
- service = new Service()
9
- .withName("admin-service")
10
- .withPort(3103)
11
- .withRedis("redis://localhost:6379")
12
- .build();
13
- });
14
-
15
- it("Should not throw an error when accessing redis", () => {
16
- expect(() => service.redis).not.toThrow();
17
- });
18
-
19
- it.skip("Should automatically register the service to redis", async () => {
20
- const value = await service.redis.get("services:registry:admin-service");
21
- expect(value).toBeDefined();
22
- const parsedValue = JSON.parse(value!);
23
- expect(parsedValue.name).equal("admin-service");
24
- expect(parsedValue.streamKey).equal("admin:events");
25
- expect(parsedValue.url).equal("http://admin-service:3103");
26
- expect(parsedValue.dependencies).toEqual([]);
27
- expect(parsedValue.routes).toBeInstanceOf(Array);
28
- expect(
29
- parsedValue.routes.some(
30
- (s: any) => s.method === "GET" && s.path === "/health",
31
- ),
32
- ).toBeTruthy();
33
- expect(parsedValue.routes.length).toBeGreaterThan(0);
34
- expect(parsedValue.lastHeartbeat).toBeDefined();
35
- });
36
- });
@@ -1,82 +0,0 @@
1
- /// <reference types="vitest/globals" />
2
- import z from "zod";
3
- import { defineMongoCollection } from "../src/workers/db/mongo/mongo";
4
- import { MongoMemoryServer } from "mongodb-memory-server";
5
- import { Service } from "../src/workers/service";
6
- import { CustomDependencies } from "../src/workers/types";
7
-
8
- describe("Service Class", () => {
9
- it("Should be able to be initialized", async () => {
10
- const service = new Service()
11
- .withName("admin-service")
12
- .withPort(3000)
13
- .build();
14
- expect(service.simpleName).toBe("admin");
15
- expect(() => service.log.info("Service initialized")).not.toThrow();
16
- });
17
-
18
- it("Should throw error if accessing uninitialized dependencies", async () => {
19
- const service = new Service().withName("admin-service").build();
20
- expect(() => service.redis).toThrow("Redis module has not been added.");
21
- expect(() => service.clickhouse).toThrow(
22
- "Clickhouse module has not been added.",
23
- );
24
- });
25
-
26
- it("Should initialize Redis dependency", async () => {
27
- const service = new Service()
28
- .withName("admin-service")
29
- .withRedis("redis://localhost:6379")
30
- .build();
31
- expect(() => service.redis).not.toThrow();
32
- });
33
-
34
- it("Should initialize MongoDB dependency", async () => {
35
- const mongoServer = await MongoMemoryServer.create();
36
- const uri = mongoServer.getUri();
37
- const service = new Service()
38
- .withName("admin-service")
39
- .withPort(4120)
40
- .withRedis("redis://localhost:6379")
41
- .withMongo({
42
- dbName: "test",
43
- uri,
44
- collections: {
45
- testCollection: defineMongoCollection({
46
- schema: z.object({
47
- name: z.string(),
48
- }),
49
- }),
50
- },
51
- })
52
- .build();
53
-
54
- expect(() => service.mongo).not.toThrow();
55
- await mongoServer.stop();
56
- });
57
-
58
- it("Should allow custom dependencies", async () => {
59
- const service = new Service()
60
- .withName("admin-service")
61
- .withPort(4120)
62
- .withModules([
63
- {
64
- name: "doSomething",
65
- init: async (log) => {
66
- log.info("Initializing custom dependency");
67
- return true;
68
- },
69
- },
70
- ])
71
- .withRedis("redis://localhost:6379")
72
- .build();
73
- expect(service["dependencies"].has("customDependencies")).toBe(true);
74
- const customDeps = service["dependencies"].get(
75
- "customDependencies",
76
- ) as CustomDependencies;
77
- expect(customDeps).toBeDefined();
78
- expect(customDeps[0].name).toBe("doSomething");
79
- expect(await customDeps[0].init(service.log)).toBe(true);
80
- expect(customDeps[0].shutdown).toBeUndefined();
81
- });
82
- });
package/tsconfig.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "extends": "../../tsconfig.base.json",
3
- "compilerOptions": {
4
- "rootDir": "src",
5
- "outDir": "dist",
6
- "declaration": true,
7
- "declarationMap": true,
8
- "emitDeclarationOnly": false
9
- },
10
- "include": ["src"],
11
- "exclude": ["node_modules", "dist"]
12
- }
package/tsup.config.ts DELETED
@@ -1,11 +0,0 @@
1
- import { defineConfig } from "tsup";
2
-
3
- export default defineConfig({
4
- entry: ["src/index.ts", "src/worker-thread.ts"],
5
- format: ["esm"],
6
- dts: true,
7
- sourcemap: true,
8
- clean: true,
9
- minify: true,
10
- outDir: "dist",
11
- });
package/vitest.config.ts DELETED
@@ -1,8 +0,0 @@
1
- import { defineConfig } from "vitest/config";
2
-
3
- export default defineConfig({
4
- test: {
5
- globals: true,
6
- include: ["tests/**/*.spec.ts"],
7
- },
8
- });