@enactprotocol/api 2.0.0

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/src/search.ts ADDED
@@ -0,0 +1,147 @@
1
+ /**
2
+ * Tool search functionality
3
+ * Implements semantic search via registry API
4
+ */
5
+
6
+ import type { EnactApiClient } from "./client";
7
+ import type { ToolSearchResult } from "./types";
8
+
9
+ /**
10
+ * Search options
11
+ */
12
+ export interface SearchOptions {
13
+ /** Search query (semantic) */
14
+ query: string;
15
+ /** Filter by tags (comma-separated or array) */
16
+ tags?: string | string[] | undefined;
17
+ /** Maximum results (default: 20, max: 100) */
18
+ limit?: number | undefined;
19
+ /** Pagination offset */
20
+ offset?: number | undefined;
21
+ }
22
+
23
+ /**
24
+ * Single search result with parsed data (v2)
25
+ */
26
+ export interface SearchResult {
27
+ /** Tool name */
28
+ name: string;
29
+ /** Tool description */
30
+ description: string;
31
+ /** Tool tags */
32
+ tags: string[];
33
+ /** Latest version */
34
+ version: string;
35
+ /** Author */
36
+ author: {
37
+ username: string;
38
+ avatarUrl?: string | undefined;
39
+ };
40
+ /** Download count */
41
+ downloads: number;
42
+ /** Trust status */
43
+ trustStatus?:
44
+ | {
45
+ auditorCount: number;
46
+ }
47
+ | undefined;
48
+ }
49
+
50
+ /**
51
+ * Search response with pagination info
52
+ */
53
+ export interface SearchResponse {
54
+ /** Search results */
55
+ results: SearchResult[];
56
+ /** Total matching tools */
57
+ total: number;
58
+ /** Results limit used */
59
+ limit: number;
60
+ /** Results offset used */
61
+ offset: number;
62
+ /** Whether more results are available */
63
+ hasMore: boolean;
64
+ }
65
+
66
+ /**
67
+ * Raw API search response v2
68
+ */
69
+ interface RawSearchResponse {
70
+ tools: ToolSearchResult[];
71
+ total: number;
72
+ limit: number;
73
+ offset: number;
74
+ }
75
+
76
+ /**
77
+ * Convert raw API result to clean SearchResult
78
+ */
79
+ function toSearchResult(raw: ToolSearchResult): SearchResult {
80
+ return {
81
+ name: raw.name,
82
+ description: raw.description,
83
+ tags: raw.tags,
84
+ version: raw.version,
85
+ author: {
86
+ username: raw.author.username,
87
+ avatarUrl: raw.author.avatar_url,
88
+ },
89
+ downloads: raw.downloads,
90
+ trustStatus: raw.trust_status
91
+ ? {
92
+ auditorCount: raw.trust_status.auditor_count,
93
+ }
94
+ : undefined,
95
+ };
96
+ }
97
+
98
+ /**
99
+ * Search for tools in the registry
100
+ *
101
+ * @param client - API client instance
102
+ * @param options - Search options
103
+ * @returns Search results with pagination
104
+ *
105
+ * @example
106
+ * ```ts
107
+ * const client = createApiClient();
108
+ * const results = await searchTools(client, {
109
+ * query: "pdf extraction",
110
+ * tags: ["ai", "document"],
111
+ * limit: 10
112
+ * });
113
+ * ```
114
+ */
115
+ export async function searchTools(
116
+ client: EnactApiClient,
117
+ options: SearchOptions
118
+ ): Promise<SearchResponse> {
119
+ const params = new URLSearchParams();
120
+
121
+ params.set("q", options.query);
122
+
123
+ if (options.tags) {
124
+ const tagsStr = Array.isArray(options.tags) ? options.tags.join(",") : options.tags;
125
+ params.set("tags", tagsStr);
126
+ }
127
+
128
+ if (options.limit !== undefined) {
129
+ params.set("limit", String(Math.min(options.limit, 100)));
130
+ }
131
+
132
+ if (options.offset !== undefined) {
133
+ params.set("offset", String(options.offset));
134
+ }
135
+
136
+ const response = await client.get<RawSearchResponse>(`/tools/search?${params.toString()}`);
137
+
138
+ const results = response.data.tools.map(toSearchResult);
139
+
140
+ return {
141
+ results,
142
+ total: response.data.total,
143
+ limit: response.data.limit,
144
+ offset: response.data.offset,
145
+ hasMore: response.data.offset + results.length < response.data.total,
146
+ };
147
+ }
package/src/trust.ts ADDED
@@ -0,0 +1,203 @@
1
+ /**
2
+ * Trust configuration management (v2)
3
+ * Functions for managing user trust settings
4
+ */
5
+
6
+ import type { EnactApiClient } from "./client";
7
+ import type { UpdateTrustConfigRequest, UpdateTrustConfigResponse, UserTrustConfig } from "./types";
8
+
9
+ /**
10
+ * Get a user's trust configuration (v2)
11
+ *
12
+ * This is public information - anyone can see which auditors a user trusts.
13
+ *
14
+ * @param client - API client instance
15
+ * @param username - Username to look up
16
+ * @returns User's trust configuration
17
+ *
18
+ * @example
19
+ * ```ts
20
+ * const trustConfig = await getUserTrust(client, "alice");
21
+ * console.log(`Alice trusts ${trustConfig.trusted_auditors.length} auditors`);
22
+ * ```
23
+ */
24
+ export async function getUserTrust(
25
+ client: EnactApiClient,
26
+ username: string
27
+ ): Promise<UserTrustConfig> {
28
+ const response = await client.get<UserTrustConfig>(`/users/${username}/trust`);
29
+ return response.data;
30
+ }
31
+
32
+ /**
33
+ * Update current user's trust configuration (v2)
34
+ *
35
+ * Replace the entire list of trusted auditors.
36
+ *
37
+ * @param client - API client instance (must be authenticated)
38
+ * @param trustedAuditors - Array of auditor emails to trust
39
+ * @returns Updated trust configuration
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * const updated = await updateMyTrust(client, [
44
+ * "security@example.com",
45
+ * "bob@github.com",
46
+ * "audit-team@company.com"
47
+ * ]);
48
+ * console.log(`Now trusting ${updated.trusted_auditors.length} auditors`);
49
+ * ```
50
+ */
51
+ export async function updateMyTrust(
52
+ client: EnactApiClient,
53
+ trustedAuditors: string[]
54
+ ): Promise<{
55
+ trustedAuditors: Array<{
56
+ identity: string;
57
+ addedAt: Date;
58
+ }>;
59
+ updatedAt: Date;
60
+ }> {
61
+ const response = await client.put<UpdateTrustConfigResponse>("/users/me/trust", {
62
+ trusted_auditors: trustedAuditors,
63
+ } as UpdateTrustConfigRequest);
64
+
65
+ return {
66
+ trustedAuditors: response.data.trusted_auditors.map((ta) => ({
67
+ identity: ta.identity,
68
+ addedAt: new Date(ta.added_at),
69
+ })),
70
+ updatedAt: new Date(response.data.updated_at),
71
+ };
72
+ }
73
+
74
+ /**
75
+ * Add an auditor to the current user's trust list
76
+ *
77
+ * This is a convenience wrapper that fetches current trust config,
78
+ * adds the auditor if not already present, and updates.
79
+ *
80
+ * @param client - API client instance (must be authenticated)
81
+ * @param auditorEmail - Auditor email to trust
82
+ * @returns Updated trust configuration
83
+ *
84
+ * @example
85
+ * ```ts
86
+ * await addTrustedAuditor(client, "new-auditor@example.com");
87
+ * ```
88
+ */
89
+ export async function addTrustedAuditor(
90
+ client: EnactApiClient,
91
+ auditorEmail: string
92
+ ): Promise<{
93
+ trustedAuditors: Array<{
94
+ identity: string;
95
+ addedAt: Date;
96
+ }>;
97
+ updatedAt: Date;
98
+ }> {
99
+ // First get current user to know their username
100
+ const currentUser = await client.get<{ username: string }>("/auth/me");
101
+ const username = currentUser.data.username;
102
+
103
+ // Get current trust config
104
+ const currentTrust = await getUserTrust(client, username);
105
+
106
+ // Add new auditor if not already present
107
+ const currentAuditors = currentTrust.trusted_auditors.map((ta) => ta.identity);
108
+ if (!currentAuditors.includes(auditorEmail)) {
109
+ currentAuditors.push(auditorEmail);
110
+ }
111
+
112
+ // Update trust config
113
+ return updateMyTrust(client, currentAuditors);
114
+ }
115
+
116
+ /**
117
+ * Remove an auditor from the current user's trust list
118
+ *
119
+ * This is a convenience wrapper that fetches current trust config,
120
+ * removes the auditor if present, and updates.
121
+ *
122
+ * @param client - API client instance (must be authenticated)
123
+ * @param auditorEmail - Auditor email to remove
124
+ * @returns Updated trust configuration
125
+ *
126
+ * @example
127
+ * ```ts
128
+ * await removeTrustedAuditor(client, "old-auditor@example.com");
129
+ * ```
130
+ */
131
+ export async function removeTrustedAuditor(
132
+ client: EnactApiClient,
133
+ auditorEmail: string
134
+ ): Promise<{
135
+ trustedAuditors: Array<{
136
+ identity: string;
137
+ addedAt: Date;
138
+ }>;
139
+ updatedAt: Date;
140
+ }> {
141
+ // First get current user to know their username
142
+ const currentUser = await client.get<{ username: string }>("/auth/me");
143
+ const username = currentUser.data.username;
144
+
145
+ // Get current trust config
146
+ const currentTrust = await getUserTrust(client, username);
147
+
148
+ // Remove auditor
149
+ const updatedAuditors = currentTrust.trusted_auditors
150
+ .map((ta) => ta.identity)
151
+ .filter((email) => email !== auditorEmail);
152
+
153
+ // Update trust config
154
+ return updateMyTrust(client, updatedAuditors);
155
+ }
156
+
157
+ /**
158
+ * Check if a user trusts a specific auditor
159
+ *
160
+ * @param client - API client instance
161
+ * @param username - Username to check
162
+ * @param auditorEmail - Auditor email to check
163
+ * @returns True if the user trusts this auditor
164
+ *
165
+ * @example
166
+ * ```ts
167
+ * const trusts = await userTrustsAuditor(client, "alice", "security@example.com");
168
+ * if (trusts) {
169
+ * console.log("Alice trusts this auditor");
170
+ * }
171
+ * ```
172
+ */
173
+ export async function userTrustsAuditor(
174
+ client: EnactApiClient,
175
+ username: string,
176
+ auditorEmail: string
177
+ ): Promise<boolean> {
178
+ const trustConfig = await getUserTrust(client, username);
179
+ return trustConfig.trusted_auditors.some((ta) => ta.identity === auditorEmail);
180
+ }
181
+
182
+ /**
183
+ * Get list of auditors trusted by the current user
184
+ *
185
+ * @param client - API client instance (must be authenticated)
186
+ * @returns Array of trusted auditor emails
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * const auditors = await getMyTrustedAuditors(client);
191
+ * console.log(`You trust: ${auditors.join(", ")}`);
192
+ * ```
193
+ */
194
+ export async function getMyTrustedAuditors(client: EnactApiClient): Promise<string[]> {
195
+ // First get current user to know their username
196
+ const currentUser = await client.get<{ username: string }>("/auth/me");
197
+ const username = currentUser.data.username;
198
+
199
+ // Get trust config
200
+ const trustConfig = await getUserTrust(client, username);
201
+
202
+ return trustConfig.trusted_auditors.map((ta) => ta.identity);
203
+ }