@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 +40 -0
- package/package.json +29 -0
- package/src/index.ts +32 -0
- package/src/router.test.ts +84 -0
- package/src/router.ts +71 -0
- package/tsconfig.json +6 -0
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
|
+
};
|