@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.
- package/README.md +297 -4
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,7 +1,300 @@
|
|
|
1
|
-
# block-search
|
|
1
|
+
# @23blocks/block-search
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Search block for the 23blocks SDK - full-text search, suggestions, and favorites.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
[](https://www.npmjs.com/package/@23blocks/block-search)
|
|
6
|
+
[](https://opensource.org/licenses/MIT)
|
|
6
7
|
|
|
7
|
-
|
|
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
|