@checkstack/queue-backend 0.0.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,40 @@
1
+ # @checkstack/queue-backend
2
+
3
+ ## 0.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - d20d274: Initial release of all @checkstack packages. Rebranded from Checkmate to Checkstack with new npm organization @checkstack and domain checkstack.dev.
8
+ - Updated dependencies [d20d274]
9
+ - @checkstack/backend-api@0.0.2
10
+ - @checkstack/common@0.0.2
11
+ - @checkstack/queue-api@0.0.2
12
+ - @checkstack/queue-common@0.0.2
13
+
14
+ ## 0.0.3
15
+
16
+ ### Patch Changes
17
+
18
+ - Updated dependencies [b4eb432]
19
+ - Updated dependencies [a65e002]
20
+ - @checkstack/backend-api@1.1.0
21
+ - @checkstack/common@0.2.0
22
+ - @checkstack/queue-api@1.0.1
23
+ - @checkstack/queue-common@0.0.3
24
+
25
+ ## 0.0.2
26
+
27
+ ### Patch Changes
28
+
29
+ - Updated dependencies [ffc28f6]
30
+ - Updated dependencies [e4d83fc]
31
+ - Updated dependencies [71275dd]
32
+ - Updated dependencies [ae19ff6]
33
+ - Updated dependencies [b55fae6]
34
+ - Updated dependencies [b354ab3]
35
+ - Updated dependencies [8e889b4]
36
+ - Updated dependencies [81f3f85]
37
+ - @checkstack/common@0.1.0
38
+ - @checkstack/backend-api@1.0.0
39
+ - @checkstack/queue-api@1.0.0
40
+ - @checkstack/queue-common@0.0.2
package/package.json ADDED
@@ -0,0 +1,29 @@
1
+ {
2
+ "name": "@checkstack/queue-backend",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "main": "src/index.ts",
6
+ "types": "./dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "dev": "tsc --watch",
10
+ "typecheck": "tsc --noEmit",
11
+ "lint": "bun run lint:code",
12
+ "lint:code": "eslint . --max-warnings 0"
13
+ },
14
+ "dependencies": {
15
+ "@checkstack/backend-api": "workspace:*",
16
+ "@checkstack/queue-api": "workspace:*",
17
+ "@checkstack/queue-common": "workspace:*",
18
+ "@hono/zod-validator": "^0.4.1",
19
+ "hono": "^4.6.14",
20
+ "zod": "^4.0.0",
21
+ "@checkstack/common": "workspace:*"
22
+ },
23
+ "devDependencies": {
24
+ "@checkstack/scripts": "workspace:*",
25
+ "@checkstack/tsconfig": "workspace:*",
26
+ "@orpc/server": "^1.13.2",
27
+ "typescript": "^5.7.2"
28
+ }
29
+ }
package/src/index.ts ADDED
@@ -0,0 +1,32 @@
1
+ import {
2
+ createBackendPlugin,
3
+ coreServices,
4
+ } from "@checkstack/backend-api";
5
+ import {
6
+ permissionList,
7
+ pluginMetadata,
8
+ queueContract,
9
+ } from "@checkstack/queue-common";
10
+ import { createQueueRouter } from "./router";
11
+
12
+ export default createBackendPlugin({
13
+ metadata: pluginMetadata,
14
+ register(env) {
15
+ env.registerPermissions(permissionList);
16
+
17
+ env.registerInit({
18
+ deps: {
19
+ logger: coreServices.logger,
20
+ rpc: coreServices.rpc,
21
+ config: coreServices.config,
22
+ },
23
+ init: async ({ logger, rpc, config }) => {
24
+ logger.debug("📋 Initializing Queue Settings Backend...");
25
+
26
+ // 4. Register oRPC router
27
+ const queueRouter = createQueueRouter(config);
28
+ rpc.registerRouter(queueRouter, queueContract);
29
+ },
30
+ });
31
+ },
32
+ });
@@ -0,0 +1,84 @@
1
+ import { describe, it, expect, mock } from "bun:test";
2
+ import { createQueueRouter } from "./router";
3
+ import { createMockRpcContext } from "@checkstack/backend-api";
4
+ import { call } from "@orpc/server";
5
+ import { z } from "zod";
6
+
7
+ describe("Queue Router", () => {
8
+ const mockUser = {
9
+ id: "test-user",
10
+ permissions: ["*"],
11
+ roles: ["admin"],
12
+ } as any;
13
+
14
+ const mockPlugins = [
15
+ {
16
+ id: "memory",
17
+ displayName: "In-Memory Queue",
18
+ description: "Simple in-memory queue for testing",
19
+ configVersion: 1,
20
+ configSchema: z.object({}),
21
+ },
22
+ ];
23
+
24
+ const mockRegistry: any = {
25
+ getPlugins: mock(() => mockPlugins),
26
+ getPlugin: mock((id: string) => mockPlugins.find((p) => p.id === id)),
27
+ };
28
+
29
+ const mockManager: any = {
30
+ getActivePlugin: mock(() => "memory"),
31
+ setActiveBackend: mock(() =>
32
+ Promise.resolve({ success: true, migratedRecurringJobs: 0, warnings: [] })
33
+ ),
34
+ };
35
+
36
+ const mockConfigService: any = {
37
+ getRedacted: mock(() => Promise.resolve({ concurrency: 10 })),
38
+ };
39
+
40
+ const router = createQueueRouter(mockConfigService);
41
+
42
+ it("getPlugins returns list of plugins", async () => {
43
+ const context = createMockRpcContext({
44
+ user: mockUser,
45
+ queuePluginRegistry: mockRegistry,
46
+ });
47
+
48
+ const result = await call(router.getPlugins, undefined, { context });
49
+ expect(result).toHaveLength(1);
50
+ expect(result[0].id).toBe("memory");
51
+ });
52
+
53
+ it("getConfiguration returns redacted config", async () => {
54
+ const context = createMockRpcContext({
55
+ user: mockUser,
56
+ queuePluginRegistry: mockRegistry,
57
+ queueManager: mockManager,
58
+ });
59
+
60
+ const result = await call(router.getConfiguration, undefined, { context });
61
+ expect(result.pluginId).toBe("memory");
62
+ expect(result.config).toEqual({ concurrency: 10 });
63
+ expect(mockConfigService.getRedacted).toHaveBeenCalledWith(
64
+ "memory",
65
+ mockPlugins[0].configSchema,
66
+ mockPlugins[0].configVersion
67
+ );
68
+ });
69
+
70
+ it("updateConfiguration updates active plugin", async () => {
71
+ const context = createMockRpcContext({
72
+ user: mockUser,
73
+ queueManager: mockManager,
74
+ });
75
+
76
+ const result = await call(
77
+ router.updateConfiguration,
78
+ { pluginId: "memory", config: {} },
79
+ { context }
80
+ );
81
+ expect(result.pluginId).toBe("memory");
82
+ expect(mockManager.setActiveBackend).toHaveBeenCalled();
83
+ });
84
+ });
package/src/router.ts ADDED
@@ -0,0 +1,71 @@
1
+ import {
2
+ toJsonSchema,
3
+ ConfigService,
4
+ RpcContext,
5
+ autoAuthMiddleware,
6
+ } from "@checkstack/backend-api";
7
+ import { queueContract } from "@checkstack/queue-common";
8
+ import { implement, ORPCError } from "@orpc/server";
9
+
10
+ const os = implement(queueContract)
11
+ .$context<RpcContext>()
12
+ .use(autoAuthMiddleware);
13
+
14
+ export const createQueueRouter = (configService: ConfigService) => {
15
+ return os.router({
16
+ getPlugins: os.getPlugins.handler(async ({ context }) => {
17
+ const plugins = context.queuePluginRegistry.getPlugins().map((p) => ({
18
+ id: p.id,
19
+ displayName: p.displayName,
20
+ description: p.description,
21
+ configVersion: p.configVersion,
22
+ configSchema: toJsonSchema(p.configSchema),
23
+ }));
24
+ return plugins;
25
+ }),
26
+
27
+ getConfiguration: os.getConfiguration.handler(async ({ context }) => {
28
+ const activePluginId = context.queueManager.getActivePlugin();
29
+ const plugin = context.queuePluginRegistry.getPlugin(activePluginId);
30
+
31
+ if (!plugin) {
32
+ throw new Error("Active queue plugin not found");
33
+ }
34
+
35
+ // Get redacted config from ConfigService using plugin's schema
36
+ const config = await configService.getRedacted(
37
+ activePluginId,
38
+ plugin.configSchema,
39
+ plugin.configVersion
40
+ );
41
+
42
+ return {
43
+ pluginId: activePluginId,
44
+ config: config || {},
45
+ };
46
+ }),
47
+
48
+ updateConfiguration: os.updateConfiguration.handler(
49
+ async ({ input, context }) => {
50
+ const { pluginId, config } = input;
51
+ try {
52
+ await context.queueManager.setActiveBackend(pluginId, config);
53
+ } catch (error) {
54
+ if (error instanceof Error) {
55
+ throw new ORPCError("INTERNAL_SERVER_ERROR", {
56
+ message: error.message,
57
+ });
58
+ }
59
+ throw error;
60
+ }
61
+ context.logger.info(
62
+ `Queue configuration updated to plugin: ${pluginId}`
63
+ );
64
+ return {
65
+ pluginId,
66
+ config,
67
+ };
68
+ }
69
+ ),
70
+ });
71
+ };
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@checkstack/tsconfig/backend.json",
3
+ "include": [
4
+ "src"
5
+ ]
6
+ }