@hyperfixi/patterns-reference 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/README.md +311 -0
- package/data/hyperfixi-extensions.json +106 -0
- package/dist/api/index.d.mts +59 -0
- package/dist/api/index.d.ts +59 -0
- package/dist/api/index.js +769 -0
- package/dist/api/index.mjs +731 -0
- package/dist/index-CBoczxz7.d.mts +296 -0
- package/dist/index-CBoczxz7.d.ts +296 -0
- package/dist/index.d.mts +403 -0
- package/dist/index.d.ts +403 -0
- package/dist/index.js +1312 -0
- package/dist/index.mjs +1240 -0
- package/dist/llm-DMR6tmkM.d.ts +123 -0
- package/dist/llm-UOOBXwj3.d.mts +123 -0
- package/dist/sync/index.d.mts +42 -0
- package/dist/sync/index.d.ts +42 -0
- package/dist/sync/index.js +28 -0
- package/dist/sync/index.mjs +23 -0
- package/package.json +92 -0
- package/src/adapters/index.ts +7 -0
- package/src/adapters/llm-adapter.ts +394 -0
- package/src/api/index.ts +52 -0
- package/src/api/language-docs.ts +529 -0
- package/src/api/llm.ts +357 -0
- package/src/api/patterns.ts +276 -0
- package/src/api/roles.ts +401 -0
- package/src/api/translations.ts +283 -0
- package/src/database/connection.ts +85 -0
- package/src/index.ts +266 -0
- package/src/registry/index.ts +7 -0
- package/src/registry/patterns-provider.ts +250 -0
- package/src/semantic-bridge.ts +204 -0
- package/src/sync/index.ts +70 -0
- package/src/types/better-sqlite3.d.ts +44 -0
- package/src/types/index.ts +434 -0
|
@@ -0,0 +1,529 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Language Documentation API
|
|
3
|
+
*
|
|
4
|
+
* Provides functions to query hyperscript language documentation:
|
|
5
|
+
* commands, expressions, keywords, features, and special symbols.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getDatabase } from '../database/connection';
|
|
9
|
+
import type {
|
|
10
|
+
Command,
|
|
11
|
+
Expression,
|
|
12
|
+
ExpressionOperator,
|
|
13
|
+
Keyword,
|
|
14
|
+
Feature,
|
|
15
|
+
SpecialSymbol,
|
|
16
|
+
LanguageElement,
|
|
17
|
+
LanguageElementType,
|
|
18
|
+
LanguageDocsStats,
|
|
19
|
+
ConnectionOptions,
|
|
20
|
+
} from '../types';
|
|
21
|
+
|
|
22
|
+
// =============================================================================
|
|
23
|
+
// Database Row Types
|
|
24
|
+
// =============================================================================
|
|
25
|
+
|
|
26
|
+
interface CommandRow {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string | null;
|
|
30
|
+
syntax: string | null;
|
|
31
|
+
purpose: string | null;
|
|
32
|
+
implicit_target: string | null;
|
|
33
|
+
implicit_result_target: string | null;
|
|
34
|
+
is_blocking: number;
|
|
35
|
+
has_body: number;
|
|
36
|
+
created_at: string;
|
|
37
|
+
updated_at: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
interface ExpressionRow {
|
|
41
|
+
id: string;
|
|
42
|
+
name: string;
|
|
43
|
+
description: string | null;
|
|
44
|
+
category: string;
|
|
45
|
+
evaluates_to_type: string | null;
|
|
46
|
+
precedence: number | null;
|
|
47
|
+
associativity: string | null;
|
|
48
|
+
created_at: string;
|
|
49
|
+
updated_at: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
interface KeywordRow {
|
|
53
|
+
id: string;
|
|
54
|
+
name: string;
|
|
55
|
+
description: string | null;
|
|
56
|
+
context_of_use: string | null;
|
|
57
|
+
is_optional: number;
|
|
58
|
+
created_at: string;
|
|
59
|
+
updated_at: string;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface FeatureRow {
|
|
63
|
+
id: string;
|
|
64
|
+
name: string;
|
|
65
|
+
description: string | null;
|
|
66
|
+
syntax: string | null;
|
|
67
|
+
trigger: string | null;
|
|
68
|
+
structure_description: string | null;
|
|
69
|
+
scope_impact: string | null;
|
|
70
|
+
created_at: string;
|
|
71
|
+
updated_at: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface SpecialSymbolRow {
|
|
75
|
+
id: string;
|
|
76
|
+
name: string;
|
|
77
|
+
symbol: string;
|
|
78
|
+
symbol_type: string;
|
|
79
|
+
description: string | null;
|
|
80
|
+
typical_value: string | null;
|
|
81
|
+
scope_implications: string | null;
|
|
82
|
+
created_at: string;
|
|
83
|
+
updated_at: string;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// =============================================================================
|
|
87
|
+
// Row Mappers
|
|
88
|
+
// =============================================================================
|
|
89
|
+
|
|
90
|
+
function mapCommand(row: CommandRow): Command {
|
|
91
|
+
return {
|
|
92
|
+
id: row.id,
|
|
93
|
+
name: row.name,
|
|
94
|
+
description: row.description,
|
|
95
|
+
syntax: row.syntax,
|
|
96
|
+
purpose: row.purpose,
|
|
97
|
+
implicitTarget: row.implicit_target,
|
|
98
|
+
implicitResultTarget: row.implicit_result_target,
|
|
99
|
+
isBlocking: row.is_blocking === 1,
|
|
100
|
+
hasBody: row.has_body === 1,
|
|
101
|
+
createdAt: new Date(row.created_at),
|
|
102
|
+
updatedAt: new Date(row.updated_at),
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
function mapExpression(row: ExpressionRow, operators: string[] = []): Expression {
|
|
107
|
+
return {
|
|
108
|
+
id: row.id,
|
|
109
|
+
name: row.name,
|
|
110
|
+
description: row.description,
|
|
111
|
+
category: row.category,
|
|
112
|
+
evaluatesToType: row.evaluates_to_type,
|
|
113
|
+
precedence: row.precedence,
|
|
114
|
+
associativity: row.associativity,
|
|
115
|
+
operators,
|
|
116
|
+
createdAt: new Date(row.created_at),
|
|
117
|
+
updatedAt: new Date(row.updated_at),
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function mapKeyword(row: KeywordRow): Keyword {
|
|
122
|
+
return {
|
|
123
|
+
id: row.id,
|
|
124
|
+
name: row.name,
|
|
125
|
+
description: row.description,
|
|
126
|
+
contextOfUse: row.context_of_use,
|
|
127
|
+
isOptional: row.is_optional === 1,
|
|
128
|
+
createdAt: new Date(row.created_at),
|
|
129
|
+
updatedAt: new Date(row.updated_at),
|
|
130
|
+
};
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function mapFeature(row: FeatureRow): Feature {
|
|
134
|
+
return {
|
|
135
|
+
id: row.id,
|
|
136
|
+
name: row.name,
|
|
137
|
+
description: row.description,
|
|
138
|
+
syntax: row.syntax,
|
|
139
|
+
trigger: row.trigger,
|
|
140
|
+
structureDescription: row.structure_description,
|
|
141
|
+
scopeImpact: row.scope_impact,
|
|
142
|
+
createdAt: new Date(row.created_at),
|
|
143
|
+
updatedAt: new Date(row.updated_at),
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
function mapSpecialSymbol(row: SpecialSymbolRow): SpecialSymbol {
|
|
148
|
+
return {
|
|
149
|
+
id: row.id,
|
|
150
|
+
name: row.name,
|
|
151
|
+
symbol: row.symbol,
|
|
152
|
+
symbolType: row.symbol_type,
|
|
153
|
+
description: row.description,
|
|
154
|
+
typicalValue: row.typical_value,
|
|
155
|
+
scopeImplications: row.scope_implications,
|
|
156
|
+
createdAt: new Date(row.created_at),
|
|
157
|
+
updatedAt: new Date(row.updated_at),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// =============================================================================
|
|
162
|
+
// Command Functions
|
|
163
|
+
// =============================================================================
|
|
164
|
+
|
|
165
|
+
/**
|
|
166
|
+
* Get a command by name.
|
|
167
|
+
*/
|
|
168
|
+
export async function getCommandByName(
|
|
169
|
+
name: string,
|
|
170
|
+
options?: ConnectionOptions
|
|
171
|
+
): Promise<Command | null> {
|
|
172
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
173
|
+
|
|
174
|
+
const row = db.prepare('SELECT * FROM commands WHERE LOWER(name) = LOWER(?)').get(name) as
|
|
175
|
+
| CommandRow
|
|
176
|
+
| undefined;
|
|
177
|
+
|
|
178
|
+
return row ? mapCommand(row) : null;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get all commands.
|
|
183
|
+
*/
|
|
184
|
+
export async function getAllCommands(options?: ConnectionOptions): Promise<Command[]> {
|
|
185
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
186
|
+
|
|
187
|
+
const rows = db.prepare('SELECT * FROM commands ORDER BY name').all() as CommandRow[];
|
|
188
|
+
|
|
189
|
+
return rows.map(mapCommand);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Search commands by name or description.
|
|
194
|
+
*/
|
|
195
|
+
export async function searchCommands(
|
|
196
|
+
query: string,
|
|
197
|
+
options?: ConnectionOptions
|
|
198
|
+
): Promise<Command[]> {
|
|
199
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
200
|
+
|
|
201
|
+
const pattern = `%${query}%`;
|
|
202
|
+
const rows = db
|
|
203
|
+
.prepare(
|
|
204
|
+
`SELECT * FROM commands
|
|
205
|
+
WHERE LOWER(name) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?)
|
|
206
|
+
ORDER BY name`
|
|
207
|
+
)
|
|
208
|
+
.all(pattern, pattern) as CommandRow[];
|
|
209
|
+
|
|
210
|
+
return rows.map(mapCommand);
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// =============================================================================
|
|
214
|
+
// Expression Functions
|
|
215
|
+
// =============================================================================
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get an expression by name.
|
|
219
|
+
*/
|
|
220
|
+
export async function getExpressionByName(
|
|
221
|
+
name: string,
|
|
222
|
+
options?: ConnectionOptions
|
|
223
|
+
): Promise<Expression | null> {
|
|
224
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
225
|
+
|
|
226
|
+
const row = db.prepare('SELECT * FROM expressions WHERE LOWER(name) = LOWER(?)').get(name) as
|
|
227
|
+
| ExpressionRow
|
|
228
|
+
| undefined;
|
|
229
|
+
|
|
230
|
+
if (!row) return null;
|
|
231
|
+
|
|
232
|
+
// Get operators for this expression
|
|
233
|
+
const operators = db
|
|
234
|
+
.prepare('SELECT operator FROM expression_operators WHERE expression_id = ?')
|
|
235
|
+
.all(row.id) as { operator: string }[];
|
|
236
|
+
|
|
237
|
+
return mapExpression(
|
|
238
|
+
row,
|
|
239
|
+
operators.map(o => o.operator)
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
/**
|
|
244
|
+
* Get all expressions.
|
|
245
|
+
*/
|
|
246
|
+
export async function getAllExpressions(options?: ConnectionOptions): Promise<Expression[]> {
|
|
247
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
248
|
+
|
|
249
|
+
const rows = db.prepare('SELECT * FROM expressions ORDER BY name').all() as ExpressionRow[];
|
|
250
|
+
|
|
251
|
+
// Get all operators in one query
|
|
252
|
+
const allOperators = db
|
|
253
|
+
.prepare('SELECT expression_id, operator FROM expression_operators')
|
|
254
|
+
.all() as { expression_id: string; operator: string }[];
|
|
255
|
+
|
|
256
|
+
// Group by expression_id
|
|
257
|
+
const operatorMap = new Map<string, string[]>();
|
|
258
|
+
for (const op of allOperators) {
|
|
259
|
+
const ops = operatorMap.get(op.expression_id) || [];
|
|
260
|
+
ops.push(op.operator);
|
|
261
|
+
operatorMap.set(op.expression_id, ops);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
return rows.map(row => mapExpression(row, operatorMap.get(row.id) || []));
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Get expressions by category.
|
|
269
|
+
*/
|
|
270
|
+
export async function getExpressionsByCategory(
|
|
271
|
+
category: string,
|
|
272
|
+
options?: ConnectionOptions
|
|
273
|
+
): Promise<Expression[]> {
|
|
274
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
275
|
+
|
|
276
|
+
const rows = db
|
|
277
|
+
.prepare('SELECT * FROM expressions WHERE LOWER(category) = LOWER(?) ORDER BY name')
|
|
278
|
+
.all(category) as ExpressionRow[];
|
|
279
|
+
|
|
280
|
+
// Get operators
|
|
281
|
+
const ids = rows.map(r => r.id);
|
|
282
|
+
if (ids.length === 0) return [];
|
|
283
|
+
|
|
284
|
+
const placeholders = ids.map(() => '?').join(',');
|
|
285
|
+
const allOperators = db
|
|
286
|
+
.prepare(
|
|
287
|
+
`SELECT expression_id, operator FROM expression_operators WHERE expression_id IN (${placeholders})`
|
|
288
|
+
)
|
|
289
|
+
.all(...ids) as { expression_id: string; operator: string }[];
|
|
290
|
+
|
|
291
|
+
const operatorMap = new Map<string, string[]>();
|
|
292
|
+
for (const op of allOperators) {
|
|
293
|
+
const ops = operatorMap.get(op.expression_id) || [];
|
|
294
|
+
ops.push(op.operator);
|
|
295
|
+
operatorMap.set(op.expression_id, ops);
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
return rows.map(row => mapExpression(row, operatorMap.get(row.id) || []));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// =============================================================================
|
|
302
|
+
// Keyword Functions
|
|
303
|
+
// =============================================================================
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Get a keyword by name.
|
|
307
|
+
*/
|
|
308
|
+
export async function getKeywordByName(
|
|
309
|
+
name: string,
|
|
310
|
+
options?: ConnectionOptions
|
|
311
|
+
): Promise<Keyword | null> {
|
|
312
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
313
|
+
|
|
314
|
+
const row = db.prepare('SELECT * FROM keywords WHERE LOWER(name) = LOWER(?)').get(name) as
|
|
315
|
+
| KeywordRow
|
|
316
|
+
| undefined;
|
|
317
|
+
|
|
318
|
+
return row ? mapKeyword(row) : null;
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
/**
|
|
322
|
+
* Get all keywords.
|
|
323
|
+
*/
|
|
324
|
+
export async function getAllKeywords(options?: ConnectionOptions): Promise<Keyword[]> {
|
|
325
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
326
|
+
|
|
327
|
+
const rows = db.prepare('SELECT * FROM keywords ORDER BY name').all() as KeywordRow[];
|
|
328
|
+
|
|
329
|
+
return rows.map(mapKeyword);
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// =============================================================================
|
|
333
|
+
// Feature Functions
|
|
334
|
+
// =============================================================================
|
|
335
|
+
|
|
336
|
+
/**
|
|
337
|
+
* Get a feature by name.
|
|
338
|
+
*/
|
|
339
|
+
export async function getFeatureByName(
|
|
340
|
+
name: string,
|
|
341
|
+
options?: ConnectionOptions
|
|
342
|
+
): Promise<Feature | null> {
|
|
343
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
344
|
+
|
|
345
|
+
const row = db.prepare('SELECT * FROM features WHERE LOWER(name) = LOWER(?)').get(name) as
|
|
346
|
+
| FeatureRow
|
|
347
|
+
| undefined;
|
|
348
|
+
|
|
349
|
+
return row ? mapFeature(row) : null;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
/**
|
|
353
|
+
* Get all features.
|
|
354
|
+
*/
|
|
355
|
+
export async function getAllFeatures(options?: ConnectionOptions): Promise<Feature[]> {
|
|
356
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
357
|
+
|
|
358
|
+
const rows = db.prepare('SELECT * FROM features ORDER BY name').all() as FeatureRow[];
|
|
359
|
+
|
|
360
|
+
return rows.map(mapFeature);
|
|
361
|
+
}
|
|
362
|
+
|
|
363
|
+
// =============================================================================
|
|
364
|
+
// Special Symbol Functions
|
|
365
|
+
// =============================================================================
|
|
366
|
+
|
|
367
|
+
/**
|
|
368
|
+
* Get a special symbol by name.
|
|
369
|
+
*/
|
|
370
|
+
export async function getSpecialSymbolByName(
|
|
371
|
+
name: string,
|
|
372
|
+
options?: ConnectionOptions
|
|
373
|
+
): Promise<SpecialSymbol | null> {
|
|
374
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
375
|
+
|
|
376
|
+
const row = db
|
|
377
|
+
.prepare(
|
|
378
|
+
'SELECT * FROM special_symbols WHERE LOWER(name) = LOWER(?) OR LOWER(symbol) = LOWER(?)'
|
|
379
|
+
)
|
|
380
|
+
.get(name, name) as SpecialSymbolRow | undefined;
|
|
381
|
+
|
|
382
|
+
return row ? mapSpecialSymbol(row) : null;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
/**
|
|
386
|
+
* Get all special symbols.
|
|
387
|
+
*/
|
|
388
|
+
export async function getAllSpecialSymbols(options?: ConnectionOptions): Promise<SpecialSymbol[]> {
|
|
389
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
390
|
+
|
|
391
|
+
const rows = db
|
|
392
|
+
.prepare('SELECT * FROM special_symbols ORDER BY name')
|
|
393
|
+
.all() as SpecialSymbolRow[];
|
|
394
|
+
|
|
395
|
+
return rows.map(mapSpecialSymbol);
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// =============================================================================
|
|
399
|
+
// Unified Search
|
|
400
|
+
// =============================================================================
|
|
401
|
+
|
|
402
|
+
/**
|
|
403
|
+
* Search across all language elements.
|
|
404
|
+
*/
|
|
405
|
+
export async function searchLanguageElements(
|
|
406
|
+
query: string,
|
|
407
|
+
types?: LanguageElementType[],
|
|
408
|
+
options?: ConnectionOptions
|
|
409
|
+
): Promise<LanguageElement[]> {
|
|
410
|
+
const results: LanguageElement[] = [];
|
|
411
|
+
const searchTypes = types || ['command', 'expression', 'keyword', 'feature', 'special_symbol'];
|
|
412
|
+
|
|
413
|
+
if (searchTypes.includes('command')) {
|
|
414
|
+
const commands = await searchCommands(query, options);
|
|
415
|
+
results.push(...commands.map(c => ({ type: 'command' as const, element: c })));
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
if (searchTypes.includes('expression')) {
|
|
419
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
420
|
+
const pattern = `%${query}%`;
|
|
421
|
+
const rows = db
|
|
422
|
+
.prepare(
|
|
423
|
+
`SELECT * FROM expressions
|
|
424
|
+
WHERE LOWER(name) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?) OR LOWER(category) LIKE LOWER(?)
|
|
425
|
+
ORDER BY name`
|
|
426
|
+
)
|
|
427
|
+
.all(pattern, pattern, pattern) as ExpressionRow[];
|
|
428
|
+
|
|
429
|
+
// Get operators
|
|
430
|
+
const ids = rows.map(r => r.id);
|
|
431
|
+
const operatorMap = new Map<string, string[]>();
|
|
432
|
+
if (ids.length > 0) {
|
|
433
|
+
const placeholders = ids.map(() => '?').join(',');
|
|
434
|
+
const ops = db
|
|
435
|
+
.prepare(
|
|
436
|
+
`SELECT expression_id, operator FROM expression_operators WHERE expression_id IN (${placeholders})`
|
|
437
|
+
)
|
|
438
|
+
.all(...ids) as { expression_id: string; operator: string }[];
|
|
439
|
+
for (const op of ops) {
|
|
440
|
+
const arr = operatorMap.get(op.expression_id) || [];
|
|
441
|
+
arr.push(op.operator);
|
|
442
|
+
operatorMap.set(op.expression_id, arr);
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
results.push(
|
|
447
|
+
...rows.map(row => ({
|
|
448
|
+
type: 'expression' as const,
|
|
449
|
+
element: mapExpression(row, operatorMap.get(row.id) || []),
|
|
450
|
+
}))
|
|
451
|
+
);
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
if (searchTypes.includes('keyword')) {
|
|
455
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
456
|
+
const pattern = `%${query}%`;
|
|
457
|
+
const rows = db
|
|
458
|
+
.prepare(
|
|
459
|
+
`SELECT * FROM keywords
|
|
460
|
+
WHERE LOWER(name) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?)
|
|
461
|
+
ORDER BY name`
|
|
462
|
+
)
|
|
463
|
+
.all(pattern, pattern) as KeywordRow[];
|
|
464
|
+
results.push(...rows.map(row => ({ type: 'keyword' as const, element: mapKeyword(row) })));
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
if (searchTypes.includes('feature')) {
|
|
468
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
469
|
+
const pattern = `%${query}%`;
|
|
470
|
+
const rows = db
|
|
471
|
+
.prepare(
|
|
472
|
+
`SELECT * FROM features
|
|
473
|
+
WHERE LOWER(name) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?)
|
|
474
|
+
ORDER BY name`
|
|
475
|
+
)
|
|
476
|
+
.all(pattern, pattern) as FeatureRow[];
|
|
477
|
+
results.push(...rows.map(row => ({ type: 'feature' as const, element: mapFeature(row) })));
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
if (searchTypes.includes('special_symbol')) {
|
|
481
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
482
|
+
const pattern = `%${query}%`;
|
|
483
|
+
const rows = db
|
|
484
|
+
.prepare(
|
|
485
|
+
`SELECT * FROM special_symbols
|
|
486
|
+
WHERE LOWER(name) LIKE LOWER(?) OR LOWER(symbol) LIKE LOWER(?) OR LOWER(description) LIKE LOWER(?)
|
|
487
|
+
ORDER BY name`
|
|
488
|
+
)
|
|
489
|
+
.all(pattern, pattern, pattern) as SpecialSymbolRow[];
|
|
490
|
+
results.push(
|
|
491
|
+
...rows.map(row => ({ type: 'special_symbol' as const, element: mapSpecialSymbol(row) }))
|
|
492
|
+
);
|
|
493
|
+
}
|
|
494
|
+
|
|
495
|
+
return results;
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
// =============================================================================
|
|
499
|
+
// Statistics
|
|
500
|
+
// =============================================================================
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Get language documentation statistics.
|
|
504
|
+
*/
|
|
505
|
+
export async function getLanguageDocsStats(
|
|
506
|
+
options?: ConnectionOptions
|
|
507
|
+
): Promise<LanguageDocsStats> {
|
|
508
|
+
const db = getDatabase({ ...options, readonly: true });
|
|
509
|
+
|
|
510
|
+
const getCount = (table: string): number => {
|
|
511
|
+
try {
|
|
512
|
+
const result = db.prepare(`SELECT COUNT(*) as count FROM ${table}`).get() as {
|
|
513
|
+
count: number;
|
|
514
|
+
};
|
|
515
|
+
return result.count;
|
|
516
|
+
} catch {
|
|
517
|
+
return 0;
|
|
518
|
+
}
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
return {
|
|
522
|
+
commands: getCount('commands'),
|
|
523
|
+
expressions: getCount('expressions'),
|
|
524
|
+
keywords: getCount('keywords'),
|
|
525
|
+
features: getCount('features'),
|
|
526
|
+
specialSymbols: getCount('special_symbols'),
|
|
527
|
+
expressionOperators: getCount('expression_operators'),
|
|
528
|
+
};
|
|
529
|
+
}
|