redis-smq-web-server 9.0.0-next.9 → 9.0.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 (105) hide show
  1. package/CHANGELOG.md +97 -0
  2. package/README.md +20 -190
  3. package/dist/cjs/bin/cli.js +1 -5
  4. package/dist/cjs/bin/cli.js.map +1 -1
  5. package/dist/cjs/src/config/parse-config.d.ts.map +1 -1
  6. package/dist/cjs/src/config/parse-config.js +14 -2
  7. package/dist/cjs/src/config/parse-config.js.map +1 -1
  8. package/dist/cjs/src/config/types/index.d.ts +1 -1
  9. package/dist/cjs/src/config/types/index.d.ts.map +1 -1
  10. package/dist/cjs/src/index.d.ts +1 -0
  11. package/dist/cjs/src/index.d.ts.map +1 -1
  12. package/dist/cjs/src/index.js +54 -21
  13. package/dist/cjs/src/index.js.map +1 -1
  14. package/dist/cjs/tests/common/config.d.ts +3 -0
  15. package/dist/cjs/tests/common/config.d.ts.map +1 -0
  16. package/dist/cjs/tests/common/config.js +24 -0
  17. package/dist/cjs/tests/common/config.js.map +1 -0
  18. package/dist/cjs/tests/common/redis-client.d.ts +94 -0
  19. package/dist/cjs/tests/common/redis-client.d.ts.map +1 -0
  20. package/dist/cjs/tests/common/redis-client.js +40 -0
  21. package/dist/cjs/tests/common/redis-client.js.map +1 -0
  22. package/dist/cjs/tests/common/start-api-server.d.ts +3 -0
  23. package/dist/cjs/tests/common/start-api-server.d.ts.map +1 -0
  24. package/dist/cjs/tests/common/start-api-server.js +39 -0
  25. package/dist/cjs/tests/common/start-api-server.js.map +1 -0
  26. package/dist/cjs/tests/common/start-cli.d.ts +10 -0
  27. package/dist/cjs/tests/common/start-cli.d.ts.map +1 -0
  28. package/dist/cjs/tests/common/start-cli.js +70 -0
  29. package/dist/cjs/tests/common/start-cli.js.map +1 -0
  30. package/dist/cjs/tests/common/start-redis-server.d.ts +3 -0
  31. package/dist/cjs/tests/common/start-redis-server.d.ts.map +1 -0
  32. package/dist/cjs/tests/common/start-redis-server.js +37 -0
  33. package/dist/cjs/tests/common/start-redis-server.js.map +1 -0
  34. package/dist/cjs/tests/common/start-web-server.d.ts +3 -0
  35. package/dist/cjs/tests/common/start-web-server.d.ts.map +1 -0
  36. package/dist/cjs/tests/common/start-web-server.js +33 -0
  37. package/dist/cjs/tests/common/start-web-server.js.map +1 -0
  38. package/dist/cjs/tests/setup.d.ts +2 -0
  39. package/dist/cjs/tests/setup.d.ts.map +1 -0
  40. package/dist/cjs/tests/setup.js +27 -0
  41. package/dist/cjs/tests/setup.js.map +1 -0
  42. package/dist/cjs/tests/tests/test00001.test.d.ts +2 -0
  43. package/dist/cjs/tests/tests/test00001.test.d.ts.map +1 -0
  44. package/dist/cjs/tests/tests/test00001.test.js +114 -0
  45. package/dist/cjs/tests/tests/test00001.test.js.map +1 -0
  46. package/dist/cjs/tests/tests/test00002.test.d.ts +2 -0
  47. package/dist/cjs/tests/tests/test00002.test.d.ts.map +1 -0
  48. package/dist/cjs/tests/tests/test00002.test.js +70 -0
  49. package/dist/cjs/tests/tests/test00002.test.js.map +1 -0
  50. package/dist/cjs/tests/tests/test00003.test.d.ts +2 -0
  51. package/dist/cjs/tests/tests/test00003.test.d.ts.map +1 -0
  52. package/dist/cjs/tests/tests/test00003.test.js +119 -0
  53. package/dist/cjs/tests/tests/test00003.test.js.map +1 -0
  54. package/dist/esm/bin/cli.js +1 -5
  55. package/dist/esm/bin/cli.js.map +1 -1
  56. package/dist/esm/src/config/parse-config.d.ts.map +1 -1
  57. package/dist/esm/src/config/parse-config.js +16 -1
  58. package/dist/esm/src/config/parse-config.js.map +1 -1
  59. package/dist/esm/src/config/types/index.d.ts +1 -1
  60. package/dist/esm/src/config/types/index.d.ts.map +1 -1
  61. package/dist/esm/src/index.d.ts +1 -0
  62. package/dist/esm/src/index.d.ts.map +1 -1
  63. package/dist/esm/src/index.js +54 -21
  64. package/dist/esm/src/index.js.map +1 -1
  65. package/dist/esm/tests/common/config.d.ts +3 -0
  66. package/dist/esm/tests/common/config.d.ts.map +1 -0
  67. package/dist/esm/tests/common/config.js +21 -0
  68. package/dist/esm/tests/common/config.js.map +1 -0
  69. package/dist/esm/tests/common/redis-client.d.ts +94 -0
  70. package/dist/esm/tests/common/redis-client.d.ts.map +1 -0
  71. package/dist/esm/tests/common/redis-client.js +20 -0
  72. package/dist/esm/tests/common/redis-client.js.map +1 -0
  73. package/dist/esm/tests/common/start-api-server.d.ts +3 -0
  74. package/dist/esm/tests/common/start-api-server.d.ts.map +1 -0
  75. package/dist/esm/tests/common/start-api-server.js +22 -0
  76. package/dist/esm/tests/common/start-api-server.js.map +1 -0
  77. package/dist/esm/tests/common/start-cli.d.ts +10 -0
  78. package/dist/esm/tests/common/start-cli.d.ts.map +1 -0
  79. package/dist/esm/tests/common/start-cli.js +54 -0
  80. package/dist/esm/tests/common/start-cli.js.map +1 -0
  81. package/dist/esm/tests/common/start-redis-server.d.ts +3 -0
  82. package/dist/esm/tests/common/start-redis-server.d.ts.map +1 -0
  83. package/dist/esm/tests/common/start-redis-server.js +22 -0
  84. package/dist/esm/tests/common/start-redis-server.js.map +1 -0
  85. package/dist/esm/tests/common/start-web-server.d.ts +3 -0
  86. package/dist/esm/tests/common/start-web-server.d.ts.map +1 -0
  87. package/dist/esm/tests/common/start-web-server.js +16 -0
  88. package/dist/esm/tests/common/start-web-server.js.map +1 -0
  89. package/dist/esm/tests/setup.d.ts +2 -0
  90. package/dist/esm/tests/setup.d.ts.map +1 -0
  91. package/dist/esm/tests/setup.js +16 -0
  92. package/dist/esm/tests/setup.js.map +1 -0
  93. package/dist/esm/tests/tests/test00001.test.d.ts +2 -0
  94. package/dist/esm/tests/tests/test00001.test.d.ts.map +1 -0
  95. package/dist/esm/tests/tests/test00001.test.js +99 -0
  96. package/dist/esm/tests/tests/test00001.test.js.map +1 -0
  97. package/dist/esm/tests/tests/test00002.test.d.ts +2 -0
  98. package/dist/esm/tests/tests/test00002.test.d.ts.map +1 -0
  99. package/dist/esm/tests/tests/test00002.test.js +59 -0
  100. package/dist/esm/tests/tests/test00002.test.js.map +1 -0
  101. package/dist/esm/tests/tests/test00003.test.d.ts +2 -0
  102. package/dist/esm/tests/tests/test00003.test.d.ts.map +1 -0
  103. package/dist/esm/tests/tests/test00003.test.js +104 -0
  104. package/dist/esm/tests/tests/test00003.test.js.map +1 -0
  105. package/package.json +7 -6
@@ -0,0 +1,20 @@
1
+ import bluebird from 'bluebird';
2
+ import { RedisClientFactory } from 'redis-smq-common';
3
+ import { config } from './config.js';
4
+ const { promisifyAll } = bluebird;
5
+ let redisClient = null;
6
+ export async function getRedisClientInstance() {
7
+ if (!redisClient) {
8
+ if (!config.redis)
9
+ throw new Error(`Redis configuration is required`);
10
+ redisClient = promisifyAll(new RedisClientFactory(config.redis));
11
+ await redisClient.initAsync();
12
+ }
13
+ return promisifyAll(redisClient.getInstance());
14
+ }
15
+ export async function shutdownRedisClient() {
16
+ if (redisClient) {
17
+ await redisClient.shutdownAsync();
18
+ }
19
+ }
20
+ //# sourceMappingURL=redis-client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-client.js","sourceRoot":"","sources":["../../../../tests/common/redis-client.ts"],"names":[],"mappings":"AASA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,MAAM,EAAE,YAAY,EAAE,GAAG,QAAQ,CAAC;AAElC,IAAI,WAAW,GAEJ,IAAI,CAAC;AAEhB,MAAM,CAAC,KAAK,UAAU,sBAAsB;IAC1C,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,IAAI,CAAC,MAAM,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,iCAAiC,CAAC,CAAC;QACtE,WAAW,GAAG,YAAY,CAAC,IAAI,kBAAkB,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QACjE,MAAM,WAAW,CAAC,SAAS,EAAE,CAAC;IAChC,CAAC;IACD,OAAO,YAAY,CAAC,WAAW,CAAC,WAAW,EAAE,CAAC,CAAC;AACjD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,WAAW,EAAE,CAAC;QAChB,MAAM,WAAW,CAAC,aAAa,EAAE,CAAC;IACpC,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function startApiServer(): Promise<number | undefined>;
2
+ export declare function stopApiServer(): Promise<void>;
3
+ //# sourceMappingURL=start-api-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-api-server.d.ts","sourceRoot":"","sources":["../../../../tests/common/start-api-server.ts"],"names":[],"mappings":"AAeA,wBAAsB,cAAc,gCAUnC;AAED,wBAAsB,aAAa,kBAKlC"}
@@ -0,0 +1,22 @@
1
+ import { net } from 'redis-smq-common';
2
+ import { config } from './config.js';
3
+ import { RedisSMQRestApi } from 'redis-smq-rest-api';
4
+ let server = null;
5
+ export async function startApiServer() {
6
+ if (!server) {
7
+ const port = await net.getRandomPort();
8
+ const cfg = config;
9
+ cfg.apiServer = cfg.apiServer || {};
10
+ cfg.apiServer.port = port;
11
+ server = new RedisSMQRestApi(cfg);
12
+ await server.run();
13
+ return port;
14
+ }
15
+ }
16
+ export async function stopApiServer() {
17
+ if (server) {
18
+ await server.shutdown();
19
+ server = null;
20
+ }
21
+ }
22
+ //# sourceMappingURL=start-api-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-api-server.js","sourceRoot":"","sources":["../../../../tests/common/start-api-server.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,GAAG,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAA0B,eAAe,EAAE,MAAM,oBAAoB,CAAC;AAE7E,IAAI,MAAM,GAA2B,IAAI,CAAC;AAE1C,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,MAAM,EAAE,CAAC;QACZ,MAAM,IAAI,GAAG,MAAM,GAAG,CAAC,aAAa,EAAE,CAAC;QACvC,MAAM,GAAG,GAA2B,MAAM,CAAC;QAC3C,GAAG,CAAC,SAAS,GAAG,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC;QACpC,GAAG,CAAC,SAAS,CAAC,IAAI,GAAG,IAAI,CAAC;QAC1B,MAAM,GAAG,IAAI,eAAe,CAAC,GAAG,CAAC,CAAC;QAClC,MAAM,MAAM,CAAC,GAAG,EAAE,CAAC;QACnB,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa;IACjC,IAAI,MAAM,EAAE,CAAC;QACX,MAAM,MAAM,CAAC,QAAQ,EAAE,CAAC;QACxB,MAAM,GAAG,IAAI,CAAC;IAChB,CAAC;AACH,CAAC"}
@@ -0,0 +1,10 @@
1
+ import { spawn } from 'child_process';
2
+ export type StartedProcess = {
3
+ proc: ReturnType<typeof spawn>;
4
+ url: string;
5
+ stop: () => Promise<void>;
6
+ stdout: string[];
7
+ stderr: string[];
8
+ };
9
+ export declare function startCliWithArgs(args: string[]): Promise<StartedProcess>;
10
+ //# sourceMappingURL=start-cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-cli.d.ts","sourceRoot":"","sources":["../../../../tests/common/start-cli.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,KAAK,EAAE,MAAM,eAAe,CAAC;AAMtC,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,UAAU,CAAC,OAAO,KAAK,CAAC,CAAC;IAC/B,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB,CAAC;AAEF,wBAAsB,gBAAgB,CACpC,IAAI,EAAE,MAAM,EAAE,GACb,OAAO,CAAC,cAAc,CAAC,CAyDzB"}
@@ -0,0 +1,54 @@
1
+ import { spawn } from 'child_process';
2
+ import { env, net } from 'redis-smq-common';
3
+ import path from 'path';
4
+ import { config } from './config.js';
5
+ import request from 'supertest';
6
+ export async function startCliWithArgs(args) {
7
+ const node = process.execPath;
8
+ const currentDir = env.getCurrentDir();
9
+ const cliPath = path.resolve(currentDir, '../../bin/cli.js');
10
+ const port = await net.getRandomPort();
11
+ const finalArgs = [
12
+ cliPath,
13
+ '--port',
14
+ String(port),
15
+ '--redis-port',
16
+ String(config.redis?.options?.port),
17
+ ...args,
18
+ ];
19
+ const proc = spawn(node, finalArgs, {
20
+ env: {
21
+ ...process.env,
22
+ },
23
+ stdio: ['ignore', 'pipe', 'pipe'],
24
+ });
25
+ const stdout = [];
26
+ const stderr = [];
27
+ proc.stdout.on('data', (d) => stdout.push(String(d)));
28
+ proc.stderr.on('data', (d) => stderr.push(String(d)));
29
+ const url = `http://127.0.0.1:${port}`;
30
+ const deadline = Date.now() + 10000;
31
+ let lastErr;
32
+ while (Date.now() < deadline) {
33
+ try {
34
+ await request(url).get('/').timeout({ deadline: 2000 });
35
+ break;
36
+ }
37
+ catch (e) {
38
+ lastErr = e;
39
+ await new Promise((r) => setTimeout(r, 150));
40
+ }
41
+ }
42
+ if (Date.now() >= deadline) {
43
+ proc.kill('SIGKILL');
44
+ throw new Error(`CLI server did not start in time. stderr:\n${stderr.join('')}\nLastErr: ${String(lastErr)}`);
45
+ }
46
+ const stop = async () => {
47
+ proc.kill('SIGINT');
48
+ await new Promise((r) => setTimeout(r, 200));
49
+ if (!proc.killed)
50
+ proc.kill('SIGKILL');
51
+ };
52
+ return { proc, url, stop, stdout, stderr };
53
+ }
54
+ //# sourceMappingURL=start-cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-cli.js","sourceRoot":"","sources":["../../../../tests/common/start-cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function initializeRedis(): Promise<void>;
2
+ export declare function shutDownRedisServer(): Promise<void>;
3
+ //# sourceMappingURL=start-redis-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-redis-server.d.ts","sourceRoot":"","sources":["../../../../tests/common/start-redis-server.ts"],"names":[],"mappings":"AAeA,wBAAsB,eAAe,kBAYpC;AAED,wBAAsB,mBAAmB,kBAExC"}
@@ -0,0 +1,22 @@
1
+ import { ERedisConfigClient } from 'redis-smq-common';
2
+ import { RedisServer } from 'redis-smq-common';
3
+ import { config } from './config.js';
4
+ let redisServer = null;
5
+ export async function initializeRedis() {
6
+ if (!redisServer) {
7
+ redisServer = new RedisServer();
8
+ const port = await redisServer.start();
9
+ config.redis = config.redis ?? {
10
+ client: ERedisConfigClient.IOREDIS,
11
+ };
12
+ config.redis.options = {
13
+ ...config.redis.options,
14
+ port,
15
+ };
16
+ }
17
+ }
18
+ export async function shutDownRedisServer() {
19
+ if (redisServer)
20
+ await redisServer.shutdown();
21
+ }
22
+ //# sourceMappingURL=start-redis-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-redis-server.js","sourceRoot":"","sources":["../../../../tests/common/start-redis-server.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,IAAI,WAAW,GAAuB,IAAI,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,eAAe;IACnC,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,WAAW,GAAG,IAAI,WAAW,EAAE,CAAC;QAChC,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,KAAK,EAAE,CAAC;QACvC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,IAAI;YAC7B,MAAM,EAAE,kBAAkB,CAAC,OAAO;SACnC,CAAC;QACF,MAAM,CAAC,KAAK,CAAC,OAAO,GAAG;YACrB,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO;YACvB,IAAI;SACL,CAAC;IACJ,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB;IACvC,IAAI,WAAW;QAAE,MAAM,WAAW,CAAC,QAAQ,EAAE,CAAC;AAChD,CAAC"}
@@ -0,0 +1,3 @@
1
+ export declare function startWebServer(): Promise<void>;
2
+ export declare function shutdownWebServer(): Promise<void>;
3
+ //# sourceMappingURL=start-web-server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-web-server.d.ts","sourceRoot":"","sources":["../../../../tests/common/start-web-server.ts"],"names":[],"mappings":"AAcA,wBAAsB,cAAc,kBAKnC;AAED,wBAAsB,iBAAiB,kBAKtC"}
@@ -0,0 +1,16 @@
1
+ import { RedisSMQWebServer } from '../../src/index.js';
2
+ import { config } from './config.js';
3
+ let webServer = null;
4
+ export async function startWebServer() {
5
+ if (!webServer) {
6
+ webServer = new RedisSMQWebServer(config);
7
+ await webServer.run();
8
+ }
9
+ }
10
+ export async function shutdownWebServer() {
11
+ if (webServer) {
12
+ await webServer.shutdown();
13
+ webServer = null;
14
+ }
15
+ }
16
+ //# sourceMappingURL=start-web-server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"start-web-server.js","sourceRoot":"","sources":["../../../../tests/common/start-web-server.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,IAAI,SAAS,GAA6B,IAAI,CAAC;AAE/C,MAAM,CAAC,KAAK,UAAU,cAAc;IAClC,IAAI,CAAC,SAAS,EAAE,CAAC;QACf,SAAS,GAAG,IAAI,iBAAiB,CAAC,MAAM,CAAC,CAAC;QAC1C,MAAM,SAAS,CAAC,GAAG,EAAE,CAAC;IACxB,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB;IACrC,IAAI,SAAS,EAAE,CAAC;QACd,MAAM,SAAS,CAAC,QAAQ,EAAE,CAAC;QAC3B,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=setup.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.d.ts","sourceRoot":"","sources":["../../../tests/setup.ts"],"names":[],"mappings":""}
@@ -0,0 +1,16 @@
1
+ import { afterAll, afterEach, beforeAll, beforeEach } from 'vitest';
2
+ import { initializeRedis, shutDownRedisServer, } from './common/start-redis-server.js';
3
+ import { getRedisClientInstance, shutdownRedisClient, } from './common/redis-client.js';
4
+ beforeAll(async () => {
5
+ await initializeRedis();
6
+ });
7
+ afterAll(async () => {
8
+ await shutdownRedisClient();
9
+ await shutDownRedisServer();
10
+ });
11
+ beforeEach(async () => {
12
+ const redis = await getRedisClientInstance();
13
+ await redis.flushallAsync();
14
+ });
15
+ afterEach(async () => void 0);
16
+ //# sourceMappingURL=setup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"setup.js","sourceRoot":"","sources":["../../../tests/setup.ts"],"names":[],"mappings":"AASA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAEpE,OAAO,EACL,eAAe,EACf,mBAAmB,GACpB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EACL,sBAAsB,EACtB,mBAAmB,GACpB,MAAM,0BAA0B,CAAC;AAElC,SAAS,CAAC,KAAK,IAAI,EAAE;IACnB,MAAM,eAAe,EAAE,CAAC;AAC1B,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;IAClB,MAAM,mBAAmB,EAAE,CAAC;IAC5B,MAAM,mBAAmB,EAAE,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,UAAU,CAAC,KAAK,IAAI,EAAE;IACpB,MAAM,KAAK,GAAG,MAAM,sBAAsB,EAAE,CAAC;IAC7C,MAAM,KAAK,CAAC,aAAa,EAAE,CAAC;AAC9B,CAAC,CAAC,CAAC;AAEH,SAAS,CAAC,KAAK,IAAI,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test00001.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00001.test.d.ts","sourceRoot":"","sources":["../../../../tests/tests/test00001.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,99 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import request from 'supertest';
3
+ import { config } from '../common/config.js';
4
+ import { shutdownWebServer, startWebServer, } from '../common/start-web-server.js';
5
+ import path from 'path';
6
+ describe('RedisSMQWebServer E2E Tests', () => {
7
+ const serverUrl = `http://localhost:${config.webServer?.port}`;
8
+ it('should serve index.html for root path', async () => {
9
+ await startWebServer();
10
+ const response = await request(serverUrl)
11
+ .get('/')
12
+ .expect(200)
13
+ .expect('Content-Type', /text\/html/);
14
+ expect(response.text).toContain('<!doctype html>');
15
+ });
16
+ it('should inject web UI config into index.html', async () => {
17
+ await startWebServer();
18
+ const response = await request(serverUrl).get('/').expect(200);
19
+ expect(response.text).toContain('window.configs');
20
+ expect(response.text).toContain('"BASE_PATH":"/"');
21
+ expect(response.text).toContain('"API_URL":"/"');
22
+ });
23
+ it('should set cache headers for asset files', async () => {
24
+ await startWebServer();
25
+ const response = await request(serverUrl).get('/index.html').expect(200);
26
+ expect(response.headers['cache-control']).toContain('no-cache');
27
+ const match = response.text.match(/<script[^>]+src=["']([^"']+)["']/i);
28
+ expect(match, 'index.html should include at least one script tag with src').toBeTruthy();
29
+ const scriptSrc = match?.[1] || '';
30
+ expect(scriptSrc.length).toBeGreaterThan(0);
31
+ const assetPath = scriptSrc.startsWith('http')
32
+ ? scriptSrc.replace(serverUrl, '')
33
+ : scriptSrc;
34
+ const absolutePath = path.resolve('/', assetPath);
35
+ const assetRes = await request(serverUrl).get(absolutePath).expect(200);
36
+ expect(assetRes.headers['cache-control']).toBeDefined();
37
+ });
38
+ it('should return 404 for non-existent static files', async () => {
39
+ await startWebServer();
40
+ await request(serverUrl)
41
+ .get('/assets/non-existent-file-12345.js')
42
+ .expect(404);
43
+ });
44
+ it('should set ETag header for static files', async () => {
45
+ await startWebServer();
46
+ const response = await request(serverUrl).get('/').expect(200);
47
+ expect(response.headers['etag']).toBeDefined();
48
+ });
49
+ it('should route /api requests to embedded REST API', async () => {
50
+ await startWebServer();
51
+ await request(serverUrl)
52
+ .get('/api/v1/queues')
53
+ .expect(200)
54
+ .expect('Content-Type', /application\/json/);
55
+ });
56
+ it('should serve index.html for non-API routes', async () => {
57
+ await startWebServer();
58
+ const response = await request(serverUrl)
59
+ .get('/queues/my-queue/messages/123/details')
60
+ .expect(200)
61
+ .expect('Content-Type', /text\/html/);
62
+ expect(response.text).toContain('<!doctype html>');
63
+ });
64
+ it('should not serve index.html for /api routes', async () => {
65
+ await startWebServer();
66
+ const response = await request(serverUrl).get('/api/v1/queues');
67
+ expect(response.headers['content-type']).not.toContain('text/html');
68
+ });
69
+ it('should not serve index.html for /swagger routes', async () => {
70
+ await startWebServer();
71
+ const response = await request(serverUrl).get('/swagger');
72
+ expect(response.text).toContain('Swagger UI');
73
+ });
74
+ it('should handle concurrent requests', async () => {
75
+ await startWebServer();
76
+ const requests = Array(50)
77
+ .fill(null)
78
+ .map(() => request(serverUrl).get('/'));
79
+ const responses = await Promise.all(requests);
80
+ const successfulResponses = responses.filter((r) => r.status === 200);
81
+ expect(successfulResponses.length).toBe(50);
82
+ });
83
+ it('should shutdown gracefully', async () => {
84
+ await startWebServer();
85
+ await new Promise((resolve) => setTimeout(resolve, 500));
86
+ let response = await request(serverUrl).get('/');
87
+ expect(response.status).toBe(200);
88
+ await shutdownWebServer();
89
+ await new Promise((resolve) => setTimeout(resolve, 500));
90
+ try {
91
+ response = await request(serverUrl).get('/');
92
+ expect(response.status).not.toBe(200);
93
+ }
94
+ catch (err) {
95
+ expect(err).toBeDefined();
96
+ }
97
+ });
98
+ });
99
+ //# sourceMappingURL=test00001.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00001.test.js","sourceRoot":"","sources":["../../../../tests/tests/test00001.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test00002.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00002.test.d.ts","sourceRoot":"","sources":["../../../../tests/tests/test00002.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,59 @@
1
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
2
+ import request from 'supertest';
3
+ import { startApiServer, stopApiServer } from '../common/start-api-server.js';
4
+ import { RedisSMQWebServer } from '../../index.js';
5
+ import { config } from '../common/config.js';
6
+ import { net } from 'redis-smq-common';
7
+ import path from 'path';
8
+ describe('RedisSMQWebServer with apiProxyTarget', () => {
9
+ let webServerUrl;
10
+ let webServer;
11
+ beforeEach(async () => {
12
+ const apiPort = await startApiServer();
13
+ const apiProxyTarget = `http://127.0.0.1:${apiPort}`;
14
+ const webServerPort = await net.getRandomPort();
15
+ webServer = new RedisSMQWebServer({
16
+ ...config,
17
+ webServer: {
18
+ port: webServerPort,
19
+ apiProxyTarget,
20
+ },
21
+ });
22
+ await webServer.run();
23
+ webServerUrl = `http://127.0.0.1:${webServerPort}`;
24
+ });
25
+ afterEach(async () => {
26
+ await webServer.shutdown();
27
+ await stopApiServer();
28
+ });
29
+ it('proxies /api/v1 endpoints', async () => {
30
+ await request(webServerUrl)
31
+ .get('/api/v1/queues')
32
+ .expect(200)
33
+ .expect('Content-Type', /application\/json/);
34
+ });
35
+ it('proxies /swagger', async () => {
36
+ const res = await request(webServerUrl).get('/swagger').expect(200);
37
+ expect(res.text).toContain('Swagger UI');
38
+ });
39
+ it('serves SPA index.html for non-API routes', async () => {
40
+ const res = await request(webServerUrl)
41
+ .get('/queues/my-queue')
42
+ .expect(200)
43
+ .expect('Content-Type', /text\/html/);
44
+ expect(res.text).toContain('<!doctype html>');
45
+ });
46
+ it('serves assets as static files', async () => {
47
+ const res = await request(webServerUrl).get('/').expect(200);
48
+ const match = res.text.match(/<script[^>]+src=["']([^"']+)["']/i);
49
+ expect(match).toBeTruthy();
50
+ const scriptSrc = match?.[1] || '';
51
+ const assetPath = scriptSrc.startsWith('http')
52
+ ? scriptSrc.replace(webServerUrl, '')
53
+ : scriptSrc;
54
+ const absolutePath = path.resolve('/', assetPath);
55
+ const assetRes = await request(webServerUrl).get(absolutePath).expect(200);
56
+ expect(assetRes.headers['cache-control']).toBeDefined();
57
+ });
58
+ });
59
+ //# sourceMappingURL=test00002.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00002.test.js","sourceRoot":"","sources":["../../../../tests/tests/test00002.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=test00003.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00003.test.d.ts","sourceRoot":"","sources":["../../../../tests/tests/test00003.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,104 @@
1
+ import { afterAll, beforeAll, describe, expect, it } from 'vitest';
2
+ import request from 'supertest';
3
+ import { startApiServer, stopApiServer } from '../common/start-api-server.js';
4
+ import { startCliWithArgs } from '../common/start-cli.js';
5
+ import path from 'path';
6
+ describe('RedisSMQ Web Server CLI e2e tests', () => {
7
+ describe('serves SPA with default basePath "/"', () => {
8
+ let started;
9
+ beforeAll(async () => {
10
+ started = await startCliWithArgs([
11
+ '--base-path',
12
+ '/',
13
+ '--enable-log',
14
+ '0',
15
+ ]);
16
+ });
17
+ afterAll(async () => {
18
+ await started.stop();
19
+ });
20
+ it('returns index.html for / and caches assets', async () => {
21
+ const res = await request(started.url).get('/index.html').expect(200);
22
+ expect(res.headers['content-type']).toMatch(/text\/html/);
23
+ expect(res.headers['cache-control']).toMatch(/no-cache/);
24
+ const match = res.text.match(/<script[^>]+src=["']([^"']+)["']/i);
25
+ expect(match).toBeTruthy();
26
+ const scriptSrc = match?.[1] ?? '';
27
+ const assetPath = scriptSrc.startsWith('http')
28
+ ? scriptSrc.replace(started.url, '')
29
+ : scriptSrc;
30
+ const absolutePath = path.resolve('/', assetPath);
31
+ const assetRes = await request(started.url).get(absolutePath).expect(200);
32
+ expect(assetRes.headers['cache-control']).toBeDefined();
33
+ expect(assetRes.headers['cache-control']).toMatch(/max-age=\d+/);
34
+ });
35
+ it('SPA fallback works on non-API route', async () => {
36
+ const res = await request(started.url).get('/queues/demo').expect(200);
37
+ expect(res.headers['content-type']).toMatch(/text\/html/);
38
+ });
39
+ });
40
+ describe('respects custom basePath "/ui"', () => {
41
+ let started;
42
+ beforeAll(async () => {
43
+ started = await startCliWithArgs([
44
+ '--base-path',
45
+ '/ui',
46
+ '--enable-log',
47
+ '0',
48
+ ]);
49
+ });
50
+ afterAll(async () => {
51
+ await started.stop();
52
+ });
53
+ it('redirects "/" to "/ui"', async () => {
54
+ const res = await request(started.url).get('/').expect(302);
55
+ expect(res.headers.location).toBe('/ui');
56
+ });
57
+ it('serves index.html at "/ui" and SPA fallback under it', async () => {
58
+ const res = await request(started.url).get('/ui/').expect(200);
59
+ expect(res.headers['content-type']).toMatch(/text\/html/);
60
+ const sub = await request(started.url).get('/ui/queues').expect(200);
61
+ expect(sub.headers['content-type']).toMatch(/text\/html/);
62
+ });
63
+ it('serves api requests under custom basePath', async () => {
64
+ await request(started.url)
65
+ .get('/ui/api/v1/queues')
66
+ .expect((r) => {
67
+ expect(r.headers['content-type']).not.toMatch(/text\/html/);
68
+ });
69
+ });
70
+ });
71
+ describe('proxies API when apiProxyTarget is set', () => {
72
+ let started;
73
+ beforeAll(async () => {
74
+ const port = await startApiServer();
75
+ started = await startCliWithArgs([
76
+ '--base-path',
77
+ '/',
78
+ '--api-proxy-target',
79
+ `http://127.0.0.1:${port}`,
80
+ '--enable-log',
81
+ '0',
82
+ ]);
83
+ });
84
+ afterAll(async () => {
85
+ await started.stop();
86
+ await stopApiServer();
87
+ });
88
+ it('proxies /api/v1 endpoints', async () => {
89
+ await request(started.url)
90
+ .get('/api/v1/queues')
91
+ .expect(200)
92
+ .expect('Content-Type', /application\/json/);
93
+ });
94
+ it('proxies /swagger', async () => {
95
+ const res = await request(started.url).get('/swagger').expect(200);
96
+ expect(res.text).toMatch(/<html|<!doctype/i);
97
+ });
98
+ it('keeps SPA behavior for non-API routes', async () => {
99
+ const res = await request(started.url).get('/about').expect(200);
100
+ expect(res.headers['content-type']).toMatch(/text\/html/);
101
+ });
102
+ });
103
+ });
104
+ //# sourceMappingURL=test00003.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test00003.test.js","sourceRoot":"","sources":["../../../../tests/tests/test00003.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "redis-smq-web-server",
3
- "version": "9.0.0-next.9",
3
+ "version": "9.0.1",
4
4
  "description": "Web server for RedisSMQ Web UI: serves the SPA and hosts or proxies the RedisSMQ REST API.",
5
5
  "author": "Weyoss <weyoss@protonmail.com>",
6
6
  "license": "MIT",
@@ -37,6 +37,7 @@
37
37
  "dependencies": {
38
38
  "commander": "14.0.1",
39
39
  "express": "4.21.2",
40
+ "express-rate-limit": "8.1.0",
40
41
  "http-proxy-middleware": "3.0.5"
41
42
  },
42
43
  "devDependencies": {
@@ -45,10 +46,10 @@
45
46
  "peerDependencies": {
46
47
  "@redis/client": "^5",
47
48
  "ioredis": "^5",
48
- "redis-smq-common": "^9.0.0-next.9",
49
- "redis-smq": "^9.0.0-next.9",
50
- "redis-smq-web-ui": "^9.0.0-next.9",
51
- "redis-smq-rest-api": "^9.0.0-next.9"
49
+ "redis-smq": "^9.0.1",
50
+ "redis-smq-common": "^9.0.1",
51
+ "redis-smq-web-ui": "^9.0.1",
52
+ "redis-smq-rest-api": "^9.0.1"
52
53
  },
53
54
  "peerDependenciesMeta": {
54
55
  "@redis/client": {
@@ -65,6 +66,6 @@
65
66
  "scripts": {
66
67
  "build": "scripts/build.sh",
67
68
  "dev": "tsc -w & node --watch dist/index.js",
68
- "test": "vitest run --passWithNoTests"
69
+ "test": "../../scripts/test_workspace_esm.sh"
69
70
  }
70
71
  }