@checkstack/command-common 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,23 @@
1
+ # @checkstack/command-common
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/common@0.0.2
10
+
11
+ ## 0.0.3
12
+
13
+ ### Patch Changes
14
+
15
+ - Updated dependencies [a65e002]
16
+ - @checkstack/common@0.2.0
17
+
18
+ ## 0.0.2
19
+
20
+ ### Patch Changes
21
+
22
+ - Updated dependencies [ffc28f6]
23
+ - @checkstack/common@0.1.0
package/package.json ADDED
@@ -0,0 +1,25 @@
1
+ {
2
+ "name": "@checkstack/command-common",
3
+ "version": "0.0.2",
4
+ "type": "module",
5
+ "exports": {
6
+ ".": {
7
+ "import": "./src/index.ts"
8
+ }
9
+ },
10
+ "dependencies": {
11
+ "@orpc/contract": "^0.48.0",
12
+ "zod": "^4.2.1",
13
+ "@checkstack/common": "workspace:*"
14
+ },
15
+ "devDependencies": {
16
+ "typescript": "^5.7.2",
17
+ "@checkstack/tsconfig": "workspace:*",
18
+ "@checkstack/scripts": "workspace:*"
19
+ },
20
+ "scripts": {
21
+ "typecheck": "tsc --noEmit",
22
+ "lint": "bun run lint:code",
23
+ "lint:code": "eslint . --max-warnings 0"
24
+ }
25
+ }
package/src/index.ts ADDED
@@ -0,0 +1,132 @@
1
+ import { oc } from "@orpc/contract";
2
+ import { z } from "zod";
3
+ import {
4
+ createClientDefinition,
5
+ definePluginMetadata,
6
+ type ProcedureMetadata,
7
+ } from "@checkstack/common";
8
+
9
+ // =============================================================================
10
+ // PLUGIN METADATA
11
+ // =============================================================================
12
+
13
+ export const pluginMetadata = definePluginMetadata({
14
+ pluginId: "command",
15
+ });
16
+
17
+ // =============================================================================
18
+ // SCHEMAS
19
+ // =============================================================================
20
+
21
+ /**
22
+ * Schema for a search result displayed in the command palette.
23
+ */
24
+ export const SearchResultSchema = z.object({
25
+ id: z.string(),
26
+ type: z.enum(["entity", "command"]),
27
+ title: z.string(),
28
+ subtitle: z.string().optional(),
29
+ /** Icon name (resolved by frontend) */
30
+ iconName: z.string().optional(),
31
+ category: z.string(),
32
+ /** Route to navigate to when the result is selected */
33
+ route: z.string().optional(),
34
+ /** For commands: keyboard shortcuts */
35
+ shortcuts: z.array(z.string()).optional(),
36
+ /** Permission IDs required to see this result */
37
+ requiredPermissions: z.array(z.string()).optional(),
38
+ });
39
+
40
+ export type SearchResult = z.infer<typeof SearchResultSchema>;
41
+
42
+ /**
43
+ * Schema for a registered command.
44
+ * Commands are searchable and can have global keyboard shortcuts.
45
+ */
46
+ export const CommandSchema = z.object({
47
+ id: z.string(),
48
+ title: z.string(),
49
+ subtitle: z.string().optional(),
50
+ /** Cross-platform keyboard shortcuts, e.g. ["meta+shift+i", "ctrl+shift+i"] */
51
+ shortcuts: z.array(z.string()).optional(),
52
+ category: z.string(),
53
+ /** Icon name (resolved by frontend) */
54
+ iconName: z.string().optional(),
55
+ /** Route to navigate to when the command is executed */
56
+ route: z.string(),
57
+ /** Permission IDs required to see/execute this command */
58
+ requiredPermissions: z.array(z.string()).optional(),
59
+ });
60
+
61
+ export type Command = z.infer<typeof CommandSchema>;
62
+
63
+ // =============================================================================
64
+ // RPC CONTRACT
65
+ // =============================================================================
66
+
67
+ const _base = oc.$meta<ProcedureMetadata>({});
68
+
69
+ /**
70
+ * Command palette RPC contract.
71
+ * Provides search functionality across all registered providers.
72
+ */
73
+ export const commandContract = {
74
+ /**
75
+ * Search across all registered search providers.
76
+ * Returns results filtered by user permissions.
77
+ */
78
+ search: _base
79
+ .meta({ userType: "public" })
80
+ .input(z.object({ query: z.string() }))
81
+ .output(z.array(SearchResultSchema)),
82
+
83
+ /**
84
+ * Get all registered commands (for browsing without a query).
85
+ * Returns commands filtered by user permissions.
86
+ */
87
+ getCommands: _base
88
+ .meta({ userType: "public" })
89
+ .output(z.array(SearchResultSchema)),
90
+ };
91
+
92
+ export type CommandContract = typeof commandContract;
93
+
94
+ /**
95
+ * Client definition for type-safe forPlugin usage.
96
+ * Use: `const client = rpcApi.forPlugin(CommandApi);`
97
+ */
98
+ export const CommandApi = createClientDefinition(
99
+ commandContract,
100
+ pluginMetadata
101
+ );
102
+
103
+ // =============================================================================
104
+ // PERMISSION UTILITIES (shared between frontend and backend)
105
+ // =============================================================================
106
+
107
+ /**
108
+ * Filter items by user permissions.
109
+ * Items without requiredPermissions are always included.
110
+ * Users with the wildcard "*" permission can see all items.
111
+ */
112
+ export function filterByPermissions<
113
+ T extends { requiredPermissions?: string[] }
114
+ >(items: T[], userPermissions: string[]): T[] {
115
+ // Wildcard permission means access to everything
116
+ const hasWildcard = userPermissions.includes("*");
117
+
118
+ return items.filter((item) => {
119
+ // No permissions required - always visible
120
+ if (!item.requiredPermissions || item.requiredPermissions.length === 0) {
121
+ return true;
122
+ }
123
+ // Wildcard user can see everything
124
+ if (hasWildcard) {
125
+ return true;
126
+ }
127
+ // Check if user has all required permissions
128
+ return item.requiredPermissions.every((perm) =>
129
+ userPermissions.includes(perm)
130
+ );
131
+ });
132
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,6 @@
1
+ {
2
+ "extends": "@checkstack/tsconfig/common.json",
3
+ "include": [
4
+ "src"
5
+ ]
6
+ }