@avleon/core 0.0.27 → 0.0.29

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 (77) hide show
  1. package/README.md +601 -561
  2. package/dist/application.js +1 -1
  3. package/dist/cache.d.ts +1 -1
  4. package/dist/cache.js +2 -2
  5. package/dist/collection.d.ts +25 -32
  6. package/dist/collection.js +50 -6
  7. package/dist/collection.test.d.ts +1 -0
  8. package/dist/collection.test.js +59 -0
  9. package/dist/config.d.ts +2 -0
  10. package/dist/config.js +30 -5
  11. package/dist/config.test.d.ts +1 -0
  12. package/dist/config.test.js +40 -0
  13. package/dist/controller.js +2 -2
  14. package/dist/environment-variables.js +42 -5
  15. package/dist/event-dispatcher.d.ts +23 -0
  16. package/dist/event-dispatcher.js +102 -0
  17. package/dist/event-subscriber.d.ts +15 -0
  18. package/dist/event-subscriber.js +96 -0
  19. package/dist/exceptions/http-exceptions.js +1 -1
  20. package/dist/exceptions/index.d.ts +1 -1
  21. package/dist/exceptions/system-exception.js +3 -1
  22. package/dist/file-storage.js +1 -1
  23. package/dist/helpers.js +1 -1
  24. package/dist/icore.d.ts +5 -0
  25. package/dist/icore.js +53 -18
  26. package/dist/index.d.ts +2 -0
  27. package/dist/index.js +6 -1
  28. package/dist/utils/index.d.ts +2 -2
  29. package/dist/utils/optional-require.js +2 -2
  30. package/dist/validation.d.ts +1 -1
  31. package/dist/websocket.d.ts +7 -0
  32. package/dist/websocket.js +20 -0
  33. package/dist/websocket.test.d.ts +0 -0
  34. package/dist/websocket.test.js +1 -0
  35. package/package.json +37 -6
  36. package/src/application.ts +104 -125
  37. package/src/authentication.ts +16 -16
  38. package/src/cache.ts +91 -91
  39. package/src/collection.test.ts +71 -0
  40. package/src/collection.ts +344 -254
  41. package/src/config.test.ts +35 -0
  42. package/src/config.ts +85 -42
  43. package/src/constants.ts +1 -1
  44. package/src/container.ts +54 -54
  45. package/src/controller.ts +125 -127
  46. package/src/decorators.ts +27 -27
  47. package/src/environment-variables.ts +53 -46
  48. package/src/event-dispatcher.ts +100 -0
  49. package/src/event-subscriber.ts +79 -0
  50. package/src/exceptions/http-exceptions.ts +86 -86
  51. package/src/exceptions/index.ts +1 -1
  52. package/src/exceptions/system-exception.ts +35 -34
  53. package/src/file-storage.ts +206 -206
  54. package/src/helpers.ts +324 -328
  55. package/src/icore.ts +1106 -1084
  56. package/src/index.ts +32 -30
  57. package/src/interfaces/avleon-application.ts +32 -40
  58. package/src/logger.ts +72 -72
  59. package/src/map-types.ts +159 -159
  60. package/src/middleware.ts +121 -98
  61. package/src/multipart.ts +116 -116
  62. package/src/openapi.ts +372 -372
  63. package/src/params.ts +111 -111
  64. package/src/queue.ts +126 -126
  65. package/src/response.ts +74 -74
  66. package/src/results.ts +30 -30
  67. package/src/route-methods.ts +186 -186
  68. package/src/swagger-schema.ts +213 -213
  69. package/src/testing.ts +220 -220
  70. package/src/types/app-builder.interface.ts +18 -19
  71. package/src/types/application.interface.ts +7 -9
  72. package/src/utils/hash.ts +8 -5
  73. package/src/utils/index.ts +2 -2
  74. package/src/utils/optional-require.ts +50 -50
  75. package/src/validation.ts +160 -156
  76. package/src/validator-extend.ts +25 -25
  77. package/src/websocket.ts +47 -0
@@ -1,125 +1,104 @@
1
- import Container from "typedi";
2
- import { Constructor } from "./helpers";
3
- import fastify, { FastifyInstance, RouteShorthandMethod } from "fastify";
4
-
5
- export interface AvleonApplication{
6
- // all public
7
- useCors: () => void
8
- useOpenApi:() => void
9
- useView:()=> void;
10
- useAuth:() => void
11
- useMultipart:()=> void
12
- useDataSource: () => void
13
- useMiddlewares: () => void
14
- useControllers: () => void
15
- useAutoControllers:() => void
16
- useStaticFiles: () => void
17
- useCustomErrorHandler: () => void
18
-
19
-
20
-
21
-
22
- // all mapping
23
- mapGroup:() => any;
24
- mapGet:()=> any;
25
- mapPost:()=> any;
26
- mapPut: () => any;
27
- mapPatch: () => any;
28
- mapDelete: () => any;
29
- mapView: () => any;
30
-
31
- // run
32
- run:(port:number) => void
33
-
34
- }
35
-
36
-
37
- export interface InlineRoutes{
38
- get: RouteShorthandMethod;
39
- post: RouteShorthandMethod;
40
- put: RouteShorthandMethod;
41
- patch: RouteShorthandMethod;
42
- delete: RouteShorthandMethod;
43
- }
44
-
45
-
46
- export interface Application{
47
-
48
- inlineRoutes:() => InlineRoutes;
49
- mapGroup:(path?: string | RegExp) => InlineRoutes;
50
-
51
- /**
52
- * Start the application
53
- * @param port
54
- * @returns void
55
- */
56
- start:(port?: number)=> void
57
- }
58
-
59
- export interface TestApplication{
60
- getController: <T>(controller: Constructor<T>)=>T;
61
- }
62
-
63
-
64
- class IqraTestApplication implements TestApplication{
65
-
66
- getController<T>(controller: Constructor<T>){
67
- const con = Container.get(controller);
68
- return con;
69
- }
70
- }
71
- class IqraApplication implements Application{
72
-
73
- private app!: FastifyInstance;
74
-
75
- constructor(){
76
- if(!this.app){
77
- this.app = fastify.prototype;
78
- }
79
-
80
- }
81
-
82
-
83
- inlineRoutes() {
84
- return {
85
- get: this.app.get,
86
- post: this.app.post,
87
- put: this.app.put,
88
- patch: this.app.patch,
89
- delete: this.app.delete
90
- }
91
- }
92
-
93
-
94
- mapGroup(path?:string|RegExp){
95
- return this.inlineRoutes();
96
- }
97
-
98
-
99
- start(port?:number){
100
- const p = port ? port : 4000
101
- this.app.listen({port:p});
102
- }
103
- }
104
-
105
-
106
-
107
- export class Builder{
108
-
109
- static createApplication(): Application{
110
- const app = new IqraApplication();
111
- return app;
112
- }
113
-
114
- static createTestApplication(app?: Application): TestApplication {
115
- const testApp = new IqraTestApplication();
116
- return testApp;
117
- }
118
- }
119
-
120
-
121
- const app = Builder.createApplication();
122
- const route = app.inlineRoutes();
123
-
124
-
125
-
1
+ import Container from "typedi";
2
+ import { Constructor } from "./helpers";
3
+ import fastify, { FastifyInstance, RouteShorthandMethod } from "fastify";
4
+
5
+ export interface AvleonApplication {
6
+ // all public
7
+ useCors: () => void;
8
+ useOpenApi: () => void;
9
+ useView: () => void;
10
+ useAuth: () => void;
11
+ useMultipart: () => void;
12
+ useDataSource: () => void;
13
+ useMiddlewares: () => void;
14
+ useControllers: () => void;
15
+ useAutoControllers: () => void;
16
+ useStaticFiles: () => void;
17
+ useCustomErrorHandler: () => void;
18
+
19
+ // all mapping
20
+ mapGroup: () => any;
21
+ mapGet: () => any;
22
+ mapPost: () => any;
23
+ mapPut: () => any;
24
+ mapPatch: () => any;
25
+ mapDelete: () => any;
26
+ mapView: () => any;
27
+
28
+ // run
29
+ run: (port: number) => void;
30
+ }
31
+
32
+ export interface InlineRoutes {
33
+ get: RouteShorthandMethod;
34
+ post: RouteShorthandMethod;
35
+ put: RouteShorthandMethod;
36
+ patch: RouteShorthandMethod;
37
+ delete: RouteShorthandMethod;
38
+ }
39
+
40
+ export interface Application {
41
+ inlineRoutes: () => InlineRoutes;
42
+ mapGroup: (path?: string | RegExp) => InlineRoutes;
43
+
44
+ /**
45
+ * Start the application
46
+ * @param port
47
+ * @returns void
48
+ */
49
+ start: (port?: number) => void;
50
+ }
51
+
52
+ export interface TestApplication {
53
+ getController: <T>(controller: Constructor<T>) => T;
54
+ }
55
+
56
+ class IqraTestApplication implements TestApplication {
57
+ getController<T>(controller: Constructor<T>) {
58
+ const con = Container.get(controller);
59
+ return con;
60
+ }
61
+ }
62
+ class IqraApplication implements Application {
63
+ private app!: FastifyInstance;
64
+
65
+ constructor() {
66
+ if (!this.app) {
67
+ this.app = fastify.prototype;
68
+ }
69
+ }
70
+
71
+ inlineRoutes() {
72
+ return {
73
+ get: this.app.get,
74
+ post: this.app.post,
75
+ put: this.app.put,
76
+ patch: this.app.patch,
77
+ delete: this.app.delete,
78
+ };
79
+ }
80
+
81
+ mapGroup(path?: string | RegExp) {
82
+ return this.inlineRoutes();
83
+ }
84
+
85
+ start(port?: number) {
86
+ const p = port ? port : 4000;
87
+ this.app.listen({ port: p });
88
+ }
89
+ }
90
+
91
+ export class Builder {
92
+ static createApplication(): Application {
93
+ const app = new IqraApplication();
94
+ return app;
95
+ }
96
+
97
+ static createTestApplication(app?: Application): TestApplication {
98
+ const testApp = new IqraTestApplication();
99
+ return testApp;
100
+ }
101
+ }
102
+
103
+ const app = Builder.createApplication();
104
+ const route = app.inlineRoutes();
@@ -1,16 +1,16 @@
1
- /**
2
- * @copyright 2024
3
- * @author Tareq Hossain
4
- * @email xtrinsic96@gmail.com
5
- * @url https://github.com/xtareq
6
- */
7
-
8
- export type CurrentUser = {};
9
-
10
- export abstract class BaseAuthetication {
11
- abstract authenticate(): Promise<Boolean>;
12
- abstract authorize(): Promise<Boolean>;
13
- }
14
-
15
- export function Authorized() {}
16
- export function CurrentUser() {}
1
+ /**
2
+ * @copyright 2024
3
+ * @author Tareq Hossain
4
+ * @email xtrinsic96@gmail.com
5
+ * @url https://github.com/xtareq
6
+ */
7
+
8
+ export type CurrentUser = {};
9
+
10
+ export abstract class BaseAuthetication {
11
+ abstract authenticate(): Promise<Boolean>;
12
+ abstract authorize(): Promise<Boolean>;
13
+ }
14
+
15
+ export function Authorized() {}
16
+ export function CurrentUser() {}
package/src/cache.ts CHANGED
@@ -1,91 +1,91 @@
1
- import type { Redis } from 'ioredis';
2
-
3
- type CacheEntry<T = any> = {
4
- data: T;
5
- timestamp: number;
6
- };
7
-
8
- export class CacheManager {
9
- private store = new Map<string, CacheEntry>();
10
- private tagsMap = new Map<string, Set<string>>();
11
- private redis: Redis | null = null;
12
-
13
- constructor(redisInstance?: Redis) {
14
- this.redis = redisInstance || null;
15
- }
16
-
17
- private redisTagKey(tag: string) {
18
- return `cache-tags:${tag}`;
19
- }
20
-
21
- async get<T>(key: string): Promise<T | null> {
22
- if (this.redis) {
23
- const val = await this.redis.get(key);
24
- return val ? JSON.parse(val) : null;
25
- }
26
-
27
- const cached = this.store.get(key);
28
- return cached ? cached.data : null;
29
- }
30
-
31
- async set<T>(
32
- key: string,
33
- value: T,
34
- tags: string[] = [],
35
- ttl: number = 3600
36
- ): Promise<void> {
37
- const entry: CacheEntry<T> = {
38
- data: value,
39
- timestamp: Date.now(),
40
- };
41
-
42
- if (this.redis) {
43
- await this.redis.set(key, JSON.stringify(entry.data), 'EX', ttl);
44
- for (const tag of tags) {
45
- await this.redis.sadd(this.redisTagKey(tag), key);
46
- }
47
- } else {
48
- this.store.set(key, entry);
49
- for (const tag of tags) {
50
- if (!this.tagsMap.has(tag)) this.tagsMap.set(tag, new Set());
51
- this.tagsMap.get(tag)!.add(key);
52
- }
53
- }
54
- }
55
-
56
- async delete(key: string): Promise<void> {
57
- if (this.redis) {
58
- await this.redis.del(key);
59
-
60
- // Also clean up from any tag sets
61
- const tagKeys = await this.redis.keys('cache-tags:*');
62
- for (const tagKey of tagKeys) {
63
- await this.redis.srem(tagKey, key);
64
- }
65
- } else {
66
- this.store.delete(key);
67
- for (const keys of this.tagsMap.values()) {
68
- keys.delete(key);
69
- }
70
- }
71
- }
72
-
73
- async invalidateTag(tag: string): Promise<void> {
74
- if (this.redis) {
75
- const tagKey = this.redisTagKey(tag);
76
- const keys = await this.redis.smembers(tagKey);
77
- if (keys.length) {
78
- await this.redis.del(...keys); // delete all cached keys
79
- await this.redis.del(tagKey); // delete the tag set
80
- }
81
- } else {
82
- const keys = this.tagsMap.get(tag);
83
- if (keys) {
84
- for (const key of keys) {
85
- this.store.delete(key);
86
- }
87
- this.tagsMap.delete(tag);
88
- }
89
- }
90
- }
91
- }
1
+ import type { Redis } from "ioredis";
2
+
3
+ type CacheEntry<T = any> = {
4
+ data: T;
5
+ timestamp: number;
6
+ };
7
+
8
+ export class CacheManager {
9
+ private store = new Map<string, CacheEntry>();
10
+ private tagsMap = new Map<string, Set<string>>();
11
+ private redis: Redis | null = null;
12
+
13
+ constructor(redisInstance?: Redis) {
14
+ this.redis = redisInstance || null;
15
+ }
16
+
17
+ private redisTagKey(tag: string) {
18
+ return `cache-tags:${tag}`;
19
+ }
20
+
21
+ async get<T>(key: string): Promise<T | null> {
22
+ if (this.redis) {
23
+ const val = await this.redis.get(key);
24
+ return val ? JSON.parse(val) : null;
25
+ }
26
+
27
+ const cached = this.store.get(key);
28
+ return cached ? cached.data : null;
29
+ }
30
+
31
+ async set<T>(
32
+ key: string,
33
+ value: T,
34
+ tags: string[] = [],
35
+ ttl: number = 3600,
36
+ ): Promise<void> {
37
+ const entry: CacheEntry<T> = {
38
+ data: value,
39
+ timestamp: Date.now(),
40
+ };
41
+
42
+ if (this.redis) {
43
+ await this.redis.set(key, JSON.stringify(entry.data), "EX", ttl);
44
+ for (const tag of tags) {
45
+ await this.redis.sadd(this.redisTagKey(tag), key);
46
+ }
47
+ } else {
48
+ this.store.set(key, entry);
49
+ for (const tag of tags) {
50
+ if (!this.tagsMap.has(tag)) this.tagsMap.set(tag, new Set());
51
+ this.tagsMap.get(tag)!.add(key);
52
+ }
53
+ }
54
+ }
55
+
56
+ async delete(key: string): Promise<void> {
57
+ if (this.redis) {
58
+ await this.redis.del(key);
59
+
60
+ // Also clean up from any tag sets
61
+ const tagKeys = await this.redis.keys("cache-tags:*");
62
+ for (const tagKey of tagKeys) {
63
+ await this.redis.srem(tagKey, key);
64
+ }
65
+ } else {
66
+ this.store.delete(key);
67
+ for (const keys of this.tagsMap.values()) {
68
+ keys.delete(key);
69
+ }
70
+ }
71
+ }
72
+
73
+ async invalidateTag(tag: string): Promise<void> {
74
+ if (this.redis) {
75
+ const tagKey = this.redisTagKey(tag);
76
+ const keys = await this.redis.smembers(tagKey);
77
+ if (keys.length) {
78
+ await this.redis.del(...keys); // delete all cached keys
79
+ await this.redis.del(tagKey); // delete the tag set
80
+ }
81
+ } else {
82
+ const keys = this.tagsMap.get(tag);
83
+ if (keys) {
84
+ for (const key of keys) {
85
+ this.store.delete(key);
86
+ }
87
+ this.tagsMap.delete(tag);
88
+ }
89
+ }
90
+ }
91
+ }
@@ -0,0 +1,71 @@
1
+ import Container from "typedi";
2
+ import { CreateConfig, GetConfig } from "./config";
3
+ import { BasicCollection, Collection } from "./collection";
4
+
5
+ type Todo = {
6
+ id: number;
7
+ body: string;
8
+ completed: boolean;
9
+ };
10
+
11
+ describe("Collection", () => {
12
+ let collection!: BasicCollection<Todo>;
13
+ beforeEach(() => {
14
+ collection = Collection.from<Todo>([
15
+ {
16
+ id: 1,
17
+ body: "test 1",
18
+ completed: false,
19
+ },
20
+ {
21
+ id: 2,
22
+ body: "test 2",
23
+ completed: true,
24
+ },
25
+ {
26
+ id: 3,
27
+ body: "test 2",
28
+ completed: true,
29
+ },
30
+ ]);
31
+ });
32
+
33
+ afterEach(() => {
34
+ collection.clear();
35
+ });
36
+
37
+ describe("find()", () => {
38
+ it("should be return collection", () => {
39
+ const result = collection.find();
40
+ expect(result).toHaveProperty("length");
41
+ expect(result.length).toBe(3);
42
+ });
43
+
44
+ it("should return only completed task", () => {
45
+ const result = collection.find((todo) => todo.completed);
46
+ expect(result).toHaveProperty("length");
47
+ expect(result.length).toBe(2);
48
+ expect(result[0].id).toBe(2);
49
+ });
50
+ });
51
+
52
+ describe("findOne()", () => {
53
+ it("should be return todo", () => {
54
+ const result = collection.findOne({ where: { id: 1 } });
55
+ expect(result).toHaveProperty("id");
56
+ expect(result?.id).toBe(1);
57
+ });
58
+
59
+ it("should return only completed task", () => {
60
+ const result = collection.findOne({
61
+ where: {
62
+ id: {
63
+ $in: [3],
64
+ },
65
+ },
66
+ });
67
+ expect(result).toHaveProperty("id");
68
+ expect(result?.completed).toBe(true);
69
+ });
70
+ });
71
+ });