@23blocks/block-search 4.0.0 → 4.1.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.
Files changed (2) hide show
  1. package/README.md +297 -4
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -1,7 +1,300 @@
1
- # block-search
1
+ # @23blocks/block-search
2
2
 
3
- This library was generated with [Nx](https://nx.dev).
3
+ Search block for the 23blocks SDK - full-text search, suggestions, and favorites.
4
4
 
5
- ## Building
5
+ [![npm version](https://img.shields.io/npm/v/@23blocks/block-search.svg)](https://www.npmjs.com/package/@23blocks/block-search)
6
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
7
 
7
- Run `nx build block-search` to build the library.
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install @23blocks/block-search @23blocks/transport-http
12
+ ```
13
+
14
+ ## Overview
15
+
16
+ This package provides comprehensive search functionality including:
17
+
18
+ - **Search** - Full-text search with filtering and pagination
19
+ - **Suggestions** - Autocomplete and typeahead
20
+ - **Search History** - Recent searches and query management
21
+ - **Favorites** - Save and manage favorite entities
22
+
23
+ ## Quick Start
24
+
25
+ ```typescript
26
+ import { createHttpTransport } from '@23blocks/transport-http';
27
+ import { createSearchBlock } from '@23blocks/block-search';
28
+
29
+ // Create transport
30
+ const transport = createHttpTransport({
31
+ baseUrl: 'https://api.yourapp.com',
32
+ headers: () => {
33
+ const token = localStorage.getItem('access_token');
34
+ return token ? { Authorization: `Bearer ${token}` } : {};
35
+ },
36
+ });
37
+
38
+ // Create block
39
+ const search = createSearchBlock(transport, {
40
+ apiKey: 'your-api-key',
41
+ });
42
+
43
+ // Execute search
44
+ const { results, totalRecords } = await search.search.search({
45
+ query: 'hello world',
46
+ limit: 20,
47
+ });
48
+
49
+ results.forEach((result) => {
50
+ console.log(result.title, result.score);
51
+ });
52
+ ```
53
+
54
+ ## Services
55
+
56
+ ### search - Full-text Search
57
+
58
+ ```typescript
59
+ // Basic search
60
+ const { results, query, totalRecords, elapsedTime } = await search.search.search({
61
+ query: 'laptop',
62
+ limit: 20,
63
+ offset: 0,
64
+ });
65
+
66
+ // Search with entity type filtering
67
+ const { results } = await search.search.search({
68
+ query: 'john',
69
+ entityTypes: ['users', 'contacts'],
70
+ limit: 10,
71
+ });
72
+
73
+ // Search with include/exclude terms
74
+ const { results } = await search.search.search({
75
+ query: 'programming',
76
+ include: ['javascript', 'typescript'],
77
+ exclude: ['java'],
78
+ });
79
+
80
+ // Get search suggestions (autocomplete)
81
+ const suggestions = await search.search.suggest('lap', 5);
82
+ suggestions.forEach((s) => console.log(s.title));
83
+
84
+ // Get available entity types
85
+ const entityTypes = await search.search.entityTypes();
86
+ entityTypes.forEach((type) => {
87
+ console.log(type.name, type.count);
88
+ });
89
+ ```
90
+
91
+ ### history - Search History
92
+
93
+ ```typescript
94
+ // Get recent searches
95
+ const recentSearches = await search.history.recent(20);
96
+ recentSearches.forEach((q) => {
97
+ console.log(q.query, q.totalRecords);
98
+ });
99
+
100
+ // Get specific query details
101
+ const queryDetails = await search.history.get('query-id');
102
+
103
+ // Clear all search history
104
+ await search.history.clear();
105
+
106
+ // Delete specific query from history
107
+ await search.history.delete('query-id');
108
+ ```
109
+
110
+ ### favorites - Favorites Management
111
+
112
+ ```typescript
113
+ // List favorites with pagination
114
+ const { data: favorites, meta } = await search.favorites.list({
115
+ page: 1,
116
+ perPage: 20,
117
+ });
118
+
119
+ favorites.forEach((fav) => {
120
+ console.log(fav.entityAlias, fav.entityType);
121
+ });
122
+
123
+ // Get a specific favorite
124
+ const favorite = await search.favorites.get('favorite-id');
125
+
126
+ // Add to favorites
127
+ const newFavorite = await search.favorites.add({
128
+ entityUniqueId: 'product-123',
129
+ entityType: 'Product',
130
+ entityAlias: 'MacBook Pro',
131
+ entityUrl: '/products/product-123',
132
+ entityAvatarUrl: 'https://example.com/image.jpg',
133
+ });
134
+
135
+ // Remove from favorites
136
+ await search.favorites.remove('favorite-id');
137
+
138
+ // Check if entity is favorited
139
+ const isFavorited = await search.favorites.isFavorite('product-123');
140
+ if (isFavorited) {
141
+ console.log('This item is in your favorites');
142
+ }
143
+ ```
144
+
145
+ ## Types
146
+
147
+ ```typescript
148
+ import type {
149
+ // Search types
150
+ SearchResult,
151
+ SearchQuery,
152
+ SearchRequest,
153
+ SearchResponse,
154
+
155
+ // History types
156
+ LastQuery,
157
+
158
+ // Favorites types
159
+ FavoriteEntity,
160
+ AddFavoriteRequest,
161
+
162
+ // Entity types
163
+ EntityType,
164
+ } from '@23blocks/block-search';
165
+ ```
166
+
167
+ ### SearchRequest
168
+
169
+ | Property | Type | Description |
170
+ |----------|------|-------------|
171
+ | `query` | `string` | Search query text |
172
+ | `entityTypes` | `string[]` | Filter by entity types |
173
+ | `include` | `string[]` | Terms to include |
174
+ | `exclude` | `string[]` | Terms to exclude |
175
+ | `limit` | `number` | Max results to return |
176
+ | `offset` | `number` | Pagination offset |
177
+
178
+ ### SearchResponse
179
+
180
+ | Property | Type | Description |
181
+ |----------|------|-------------|
182
+ | `results` | `SearchResult[]` | Search results |
183
+ | `query` | `SearchQuery` | Query details |
184
+ | `totalRecords` | `number` | Total matching records |
185
+ | `elapsedTime` | `number` | Search duration (ms) |
186
+
187
+ ### SearchResult
188
+
189
+ | Property | Type | Description |
190
+ |----------|------|-------------|
191
+ | `id` | `string` | Result ID |
192
+ | `uniqueId` | `string` | Unique identifier |
193
+ | `title` | `string` | Display title |
194
+ | `description` | `string` | Description text |
195
+ | `entityType` | `string` | Type of entity |
196
+ | `entityUniqueId` | `string` | Entity unique ID |
197
+ | `score` | `number` | Relevance score |
198
+ | `url` | `string` | Entity URL |
199
+ | `avatarUrl` | `string` | Avatar/image URL |
200
+
201
+ ### FavoriteEntity
202
+
203
+ | Property | Type | Description |
204
+ |----------|------|-------------|
205
+ | `id` | `string` | Favorite ID |
206
+ | `uniqueId` | `string` | Unique identifier |
207
+ | `entityUniqueId` | `string` | Favorited entity ID |
208
+ | `entityType` | `string` | Type of favorited entity |
209
+ | `entityAlias` | `string` | Display name |
210
+ | `entityUrl` | `string` | Entity URL |
211
+ | `entityAvatarUrl` | `string` | Entity image URL |
212
+ | `createdAt` | `Date` | When favorited |
213
+
214
+ ## Error Handling
215
+
216
+ ```typescript
217
+ import { isBlockErrorException, ErrorCodes } from '@23blocks/contracts';
218
+
219
+ try {
220
+ const results = await search.search.search({ query: '' });
221
+ } catch (error) {
222
+ if (isBlockErrorException(error)) {
223
+ switch (error.code) {
224
+ case ErrorCodes.VALIDATION_ERROR:
225
+ console.log('Invalid search query');
226
+ break;
227
+ case ErrorCodes.UNAUTHORIZED:
228
+ console.log('Please sign in to search');
229
+ break;
230
+ }
231
+ }
232
+ }
233
+ ```
234
+
235
+ ## Advanced Usage
236
+
237
+ ### Building a Search Component
238
+
239
+ ```typescript
240
+ import { createSearchBlock } from '@23blocks/block-search';
241
+
242
+ // Debounced search with suggestions
243
+ let debounceTimer: NodeJS.Timeout;
244
+
245
+ async function handleSearchInput(query: string) {
246
+ clearTimeout(debounceTimer);
247
+
248
+ debounceTimer = setTimeout(async () => {
249
+ if (query.length < 2) return;
250
+
251
+ // Get suggestions for autocomplete
252
+ const suggestions = await search.search.suggest(query, 5);
253
+ updateSuggestions(suggestions);
254
+ }, 300);
255
+ }
256
+
257
+ async function executeSearch(query: string) {
258
+ const { results, totalRecords } = await search.search.search({
259
+ query,
260
+ limit: 20,
261
+ });
262
+
263
+ updateResults(results);
264
+ updateResultCount(totalRecords);
265
+ }
266
+ ```
267
+
268
+ ### Favorites Toggle
269
+
270
+ ```typescript
271
+ async function toggleFavorite(entityId: string, entityType: string, entityName: string) {
272
+ const isFavorited = await search.favorites.isFavorite(entityId);
273
+
274
+ if (isFavorited) {
275
+ // Find and remove the favorite
276
+ const { data: favorites } = await search.favorites.list({
277
+ filter: { entity_unique_id: entityId },
278
+ });
279
+ if (favorites.length > 0) {
280
+ await search.favorites.remove(favorites[0].id);
281
+ }
282
+ } else {
283
+ await search.favorites.add({
284
+ entityUniqueId: entityId,
285
+ entityType,
286
+ entityAlias: entityName,
287
+ });
288
+ }
289
+ }
290
+ ```
291
+
292
+ ## Related Packages
293
+
294
+ - [`@23blocks/angular`](https://www.npmjs.com/package/@23blocks/angular) - Angular integration
295
+ - [`@23blocks/react`](https://www.npmjs.com/package/@23blocks/react) - React integration
296
+ - [`@23blocks/sdk`](https://www.npmjs.com/package/@23blocks/sdk) - Full SDK package
297
+
298
+ ## License
299
+
300
+ MIT - Copyright (c) 2024 23blocks
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@23blocks/block-search",
3
- "version": "4.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Search block for 23blocks SDK - full-text search, history, favorites",
5
5
  "license": "MIT",
6
6
  "author": "23blocks <hello@23blocks.com>",