@finos/legend-server-showcase-deployment 10.0.0 → 10.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/lib/ShowcaseRegistry.d.ts +3 -1
- package/lib/ShowcaseRegistry.d.ts.map +1 -1
- package/lib/ShowcaseRegistry.js +92 -3
- package/lib/ShowcaseRegistry.js.map +1 -1
- package/lib/ShowcaseRegistryServer.d.ts.map +1 -1
- package/lib/ShowcaseRegistryServer.js +3 -2
- package/lib/ShowcaseRegistryServer.js.map +1 -1
- package/package.json +4 -4
- package/src/ShowcaseRegistry.ts +131 -3
- package/src/ShowcaseRegistryServer.ts +14 -3
@@ -13,7 +13,7 @@
|
|
13
13
|
* See the License for the specific language governing permissions and
|
14
14
|
* limitations under the License.
|
15
15
|
*/
|
16
|
-
import { Showcase, type ShowcaseMetadata } from '@finos/legend-server-showcase';
|
16
|
+
import { Showcase, type ShowcaseMetadata, type ShowcaseTextSearchResult } from '@finos/legend-server-showcase';
|
17
17
|
import { type PlainObject } from '@finos/legend-shared';
|
18
18
|
export type ShowcaseRegistryConfig = {
|
19
19
|
datasources: {
|
@@ -25,9 +25,11 @@ export declare class ShowcaseRegistry {
|
|
25
25
|
private readonly RAW__metadata;
|
26
26
|
private readonly RAW__showcaseIndex;
|
27
27
|
private readonly showcasesIndex;
|
28
|
+
private readonly showcaseSearchEngine;
|
28
29
|
private constructor();
|
29
30
|
static initialize(config: ShowcaseRegistryConfig): Promise<ShowcaseRegistry>;
|
30
31
|
getShowcases(): PlainObject<ShowcaseMetadata>[];
|
31
32
|
getShowcase(path: string): PlainObject<Showcase> | undefined;
|
33
|
+
search(searchText: string): Promise<ShowcaseTextSearchResult>;
|
32
34
|
}
|
33
35
|
//# sourceMappingURL=ShowcaseRegistry.d.ts.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ShowcaseRegistry.d.ts","sourceRoot":"","sources":["../src/ShowcaseRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,
|
1
|
+
{"version":3,"file":"ShowcaseRegistry.d.ts","sourceRoot":"","sources":["../src/ShowcaseRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,EACL,QAAQ,EACR,KAAK,gBAAgB,EAErB,KAAK,wBAAwB,EAC9B,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAIL,KAAK,WAAW,EAEjB,MAAM,sBAAsB,CAAC;AAgC9B,MAAM,MAAM,sBAAsB,GAAG;IACnC,WAAW,EAAE;QACX,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,EAAE,CAAC;CACL,CAAC;AAEF,qBAAa,gBAAgB;IAE3B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAuC;IACrE,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAG/B;IAEJ,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAC9D,OAAO,CAAC,QAAQ,CAAC,oBAAoB,CAA8B;IAGnE,OAAO;WA6CM,UAAU,CACrB,MAAM,EAAE,sBAAsB,GAC7B,OAAO,CAAC,gBAAgB,CAAC;IA6B5B,YAAY,IAAI,WAAW,CAAC,gBAAgB,CAAC,EAAE;IAI/C,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAAC,QAAQ,CAAC,GAAG,SAAS;IAItD,MAAM,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,wBAAwB,CAAC;CAqEpE"}
|
package/lib/ShowcaseRegistry.js
CHANGED
@@ -15,8 +15,8 @@
|
|
15
15
|
*/
|
16
16
|
import { get } from 'https';
|
17
17
|
import { readFileSync } from 'fs';
|
18
|
-
import { Showcase } from '@finos/legend-server-showcase';
|
19
|
-
import {} from '@finos/legend-shared';
|
18
|
+
import { Showcase, } from '@finos/legend-server-showcase';
|
19
|
+
import { ESM__FuzzySearchEngine, FuzzySearchEngine, promisify, getNonNullableEntry, } from '@finos/legend-shared';
|
20
20
|
async function fetchExternalLinkSiteData(url) {
|
21
21
|
return new Promise((resolve, reject) => {
|
22
22
|
get(url, (response) => {
|
@@ -48,8 +48,51 @@ export class ShowcaseRegistry {
|
|
48
48
|
RAW__metadata = [];
|
49
49
|
RAW__showcaseIndex = new Map();
|
50
50
|
showcasesIndex = new Map();
|
51
|
+
showcaseSearchEngine;
|
52
|
+
// private constructor to enforce singleton
|
51
53
|
constructor() {
|
52
|
-
//
|
54
|
+
// NOTE: due to the way we export the constructor of `FuzzySearchEngine`, when we run this with ESM
|
55
|
+
// we can remove this workaround once Fuse supports ESM
|
56
|
+
// See https://github.com/krisk/Fuse/pull/727
|
57
|
+
const FuzzySearchEngineConstructor =
|
58
|
+
// eslint-disable-next-line no-process-env
|
59
|
+
process.env.NODE_ENV === 'development'
|
60
|
+
? ESM__FuzzySearchEngine
|
61
|
+
: FuzzySearchEngine;
|
62
|
+
this.showcaseSearchEngine = new FuzzySearchEngineConstructor([], {
|
63
|
+
includeScore: true,
|
64
|
+
// NOTE: we must not sort/change the order in the grid since
|
65
|
+
// we want to ensure the element row is on top
|
66
|
+
shouldSort: false,
|
67
|
+
// Ignore location when computing the search score
|
68
|
+
// See https://fusejs.io/concepts/scoring-theory.html
|
69
|
+
ignoreLocation: true,
|
70
|
+
// This specifies the point the search gives up
|
71
|
+
// `0.0` means exact match where `1.0` would match anything
|
72
|
+
// We set a relatively low threshold to filter out irrelevant results
|
73
|
+
threshold: 0.2,
|
74
|
+
keys: [
|
75
|
+
{
|
76
|
+
name: 'title',
|
77
|
+
weight: 5,
|
78
|
+
},
|
79
|
+
{
|
80
|
+
name: 'description',
|
81
|
+
weight: 3,
|
82
|
+
},
|
83
|
+
{
|
84
|
+
name: 'path',
|
85
|
+
weight: 2,
|
86
|
+
},
|
87
|
+
{
|
88
|
+
name: 'documentation',
|
89
|
+
weight: 1,
|
90
|
+
},
|
91
|
+
],
|
92
|
+
// extended search allows for exact word match through single quote
|
93
|
+
// See https://fusejs.io/examples.html#extended-search
|
94
|
+
useExtendedSearch: true,
|
95
|
+
});
|
53
96
|
}
|
54
97
|
static async initialize(config) {
|
55
98
|
const registry = new ShowcaseRegistry();
|
@@ -69,6 +112,7 @@ export class ShowcaseRegistry {
|
|
69
112
|
}
|
70
113
|
});
|
71
114
|
}));
|
115
|
+
registry.showcaseSearchEngine.setCollection(Array.from(registry.showcasesIndex.values()));
|
72
116
|
return registry;
|
73
117
|
}
|
74
118
|
getShowcases() {
|
@@ -77,5 +121,50 @@ export class ShowcaseRegistry {
|
|
77
121
|
getShowcase(path) {
|
78
122
|
return this.RAW__showcaseIndex.get(path);
|
79
123
|
}
|
124
|
+
async search(searchText) {
|
125
|
+
const matches = [];
|
126
|
+
// NOTE: for text search, we only support case-insensitive search now
|
127
|
+
const lowerCaseSearchText = searchText.toLowerCase();
|
128
|
+
await Promise.all(Array.from(this.showcasesIndex.values()).map((showcase) => promisify(() => {
|
129
|
+
const result = {
|
130
|
+
path: showcase.path,
|
131
|
+
matches: [],
|
132
|
+
preview: [],
|
133
|
+
};
|
134
|
+
const previewLines = new Map();
|
135
|
+
const code = showcase.code;
|
136
|
+
const lines = code.split('\n');
|
137
|
+
lines.forEach((line, lineIdx) => {
|
138
|
+
const lowerCaseLine = line.toLowerCase();
|
139
|
+
let fromIdx = 0;
|
140
|
+
let currentMatchIdx = lowerCaseLine.indexOf(lowerCaseSearchText, fromIdx);
|
141
|
+
while (currentMatchIdx !== -1) {
|
142
|
+
const previewTextStartLineIdx = Math.max(lineIdx - 1, 0);
|
143
|
+
previewLines.set(previewTextStartLineIdx + 1, getNonNullableEntry(lines, previewTextStartLineIdx));
|
144
|
+
previewLines.set(lineIdx + 1, getNonNullableEntry(lines, lineIdx));
|
145
|
+
const previewTextEndLineIdx = Math.min(lineIdx + 1, lines.length - 1);
|
146
|
+
previewLines.set(previewTextEndLineIdx + 1, getNonNullableEntry(lines, previewTextEndLineIdx));
|
147
|
+
result.matches.push({
|
148
|
+
line: lineIdx + 1,
|
149
|
+
startColumn: currentMatchIdx + 1,
|
150
|
+
endColumn: currentMatchIdx + 1 + lowerCaseSearchText.length,
|
151
|
+
});
|
152
|
+
fromIdx = currentMatchIdx + lowerCaseSearchText.length;
|
153
|
+
currentMatchIdx = lowerCaseLine.indexOf(lowerCaseSearchText, fromIdx);
|
154
|
+
}
|
155
|
+
});
|
156
|
+
if (!result.matches.length) {
|
157
|
+
return;
|
158
|
+
}
|
159
|
+
result.preview = Array.from(previewLines.entries())
|
160
|
+
.map(([line, text]) => ({ line, text }))
|
161
|
+
.sort((a, b) => a.line - b.line);
|
162
|
+
matches.push(result);
|
163
|
+
})));
|
164
|
+
return {
|
165
|
+
showcases: Array.from(this.showcaseSearchEngine.search(searchText).values()).map((result) => result.item.path),
|
166
|
+
textMatches: matches,
|
167
|
+
};
|
168
|
+
}
|
80
169
|
}
|
81
170
|
//# sourceMappingURL=ShowcaseRegistry.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ShowcaseRegistry.js","sourceRoot":"","sources":["../src/ShowcaseRegistry.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,GAAG,EAAE,MAAM,OAAO,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,IAAI,CAAC;AAClC,OAAO,
|
1
|
+
{"version":3,"file":"ShowcaseRegistry.js","sourceRoot":"","sources":["../src/ShowcaseRegistry.ts"],"names":[],"mappings":"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"}
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ShowcaseRegistryServer.d.ts","sourceRoot":"","sources":["../src/ShowcaseRegistryServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;
|
1
|
+
{"version":3,"file":"ShowcaseRegistryServer.d.ts","sourceRoot":"","sources":["../src/ShowcaseRegistryServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAE,KAAK,eAAe,EAAgC,MAAM,SAAS,CAAC;AAC7E,OAAO,EAEL,KAAK,sBAAsB,EAC5B,MAAM,uBAAuB,CAAC;AAc/B,eAAO,MAAM,+BAA+B,WAClC,eAAe,UACf,sBAAsB,GAAG;IAC/B,UAAU,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CACjC,KACA,QAAQ,IAAI,CA8Bd,CAAC"}
|
@@ -30,8 +30,9 @@ export const configureShowcaseRegistryServer = async (server, config) => {
|
|
30
30
|
}
|
31
31
|
await reply.send(registry.getShowcase(path));
|
32
32
|
});
|
33
|
-
server.get(`${baseUrl}/
|
34
|
-
|
33
|
+
server.get(`${baseUrl}/showcases/search`, async (request, reply) => {
|
34
|
+
const { searchText } = request.query;
|
35
|
+
await reply.send(await registry.search(searchText));
|
35
36
|
});
|
36
37
|
};
|
37
38
|
//# sourceMappingURL=ShowcaseRegistryServer.js.map
|
@@ -1 +1 @@
|
|
1
|
-
{"version":3,"file":"ShowcaseRegistryServer.js","sourceRoot":"","sources":["../src/ShowcaseRegistryServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAsD,MAAM,SAAS,CAAC;AAC7E,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;
|
1
|
+
{"version":3,"file":"ShowcaseRegistryServer.js","sourceRoot":"","sources":["../src/ShowcaseRegistryServer.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,EAAsD,MAAM,SAAS,CAAC;AAC7E,OAAO,EACL,gBAAgB,GAEjB,MAAM,uBAAuB,CAAC;AAc/B,MAAM,CAAC,MAAM,+BAA+B,GAAG,KAAK,EAClD,MAAuB,EACvB,MAEC,EACc,EAAE;IACjB,MAAM,QAAQ,GAAG,MAAM,gBAAgB,CAAC,UAAU,CAAC,MAAM,CAAC,CAAC;IAC3D,MAAM,OAAO,GAAG,MAAM,CAAC,UAAU,IAAI,MAAM,CAAC;IAE5C,MAAM,CAAC,GAAG,CAAC,GAAG,OAAO,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QAC1D,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;IAC5C,CAAC,CAAC,CAAC;IAEH,MAAM,CAAC,GAAG,CACR,GAAG,OAAO,iBAAiB,EAC3B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,MAAM,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;QAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;QAC5C,IAAI,CAAC,QAAQ,EAAE;YACb,KAAK,CAAC,YAAY,EAAE,CAAC;YACrB,OAAO;SACR;QAED,MAAM,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;IAC/C,CAAC,CACF,CAAC;IAEF,MAAM,CAAC,GAAG,CACR,GAAG,OAAO,mBAAmB,EAC7B,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,EAAE;QACvB,MAAM,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,KAAK,CAAC;QAErC,MAAM,KAAK,CAAC,IAAI,CAAC,MAAM,QAAQ,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;IACtD,CAAC,CACF,CAAC;AACJ,CAAC,CAAC"}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@finos/legend-server-showcase-deployment",
|
3
|
-
"version": "10.
|
3
|
+
"version": "10.1.0",
|
4
4
|
"description": "Legend Showcase server deployment",
|
5
5
|
"keywords": [
|
6
6
|
"legend",
|
@@ -51,12 +51,12 @@
|
|
51
51
|
},
|
52
52
|
"dependencies": {
|
53
53
|
"@fastify/cors": "8.3.0",
|
54
|
-
"@finos/legend-server-showcase": "0.0.
|
55
|
-
"@finos/legend-shared": "10.0.
|
54
|
+
"@finos/legend-server-showcase": "0.0.5",
|
55
|
+
"@finos/legend-shared": "10.0.21",
|
56
56
|
"fastify": "4.20.0"
|
57
57
|
},
|
58
58
|
"devDependencies": {
|
59
|
-
"@finos/legend-dev-utils": "2.0.
|
59
|
+
"@finos/legend-dev-utils": "2.0.75",
|
60
60
|
"@jest/globals": "29.6.1",
|
61
61
|
"cross-env": "7.0.3",
|
62
62
|
"eslint": "8.45.0",
|
package/src/ShowcaseRegistry.ts
CHANGED
@@ -16,8 +16,19 @@
|
|
16
16
|
|
17
17
|
import { get } from 'https';
|
18
18
|
import { readFileSync } from 'fs';
|
19
|
-
import {
|
20
|
-
|
19
|
+
import {
|
20
|
+
Showcase,
|
21
|
+
type ShowcaseMetadata,
|
22
|
+
type ShowcaseTextSearchMatch,
|
23
|
+
type ShowcaseTextSearchResult,
|
24
|
+
} from '@finos/legend-server-showcase';
|
25
|
+
import {
|
26
|
+
ESM__FuzzySearchEngine,
|
27
|
+
FuzzySearchEngine,
|
28
|
+
promisify,
|
29
|
+
type PlainObject,
|
30
|
+
getNonNullableEntry,
|
31
|
+
} from '@finos/legend-shared';
|
21
32
|
|
22
33
|
async function fetchExternalLinkSiteData(url: string): Promise<string> {
|
23
34
|
return new Promise((resolve, reject) => {
|
@@ -65,9 +76,52 @@ export class ShowcaseRegistry {
|
|
65
76
|
>();
|
66
77
|
|
67
78
|
private readonly showcasesIndex = new Map<string, Showcase>();
|
79
|
+
private readonly showcaseSearchEngine: FuzzySearchEngine<Showcase>;
|
68
80
|
|
81
|
+
// private constructor to enforce singleton
|
69
82
|
private constructor() {
|
70
|
-
//
|
83
|
+
// NOTE: due to the way we export the constructor of `FuzzySearchEngine`, when we run this with ESM
|
84
|
+
// we can remove this workaround once Fuse supports ESM
|
85
|
+
// See https://github.com/krisk/Fuse/pull/727
|
86
|
+
const FuzzySearchEngineConstructor =
|
87
|
+
// eslint-disable-next-line no-process-env
|
88
|
+
process.env.NODE_ENV === 'development'
|
89
|
+
? ESM__FuzzySearchEngine
|
90
|
+
: FuzzySearchEngine;
|
91
|
+
this.showcaseSearchEngine = new FuzzySearchEngineConstructor([], {
|
92
|
+
includeScore: true,
|
93
|
+
// NOTE: we must not sort/change the order in the grid since
|
94
|
+
// we want to ensure the element row is on top
|
95
|
+
shouldSort: false,
|
96
|
+
// Ignore location when computing the search score
|
97
|
+
// See https://fusejs.io/concepts/scoring-theory.html
|
98
|
+
ignoreLocation: true,
|
99
|
+
// This specifies the point the search gives up
|
100
|
+
// `0.0` means exact match where `1.0` would match anything
|
101
|
+
// We set a relatively low threshold to filter out irrelevant results
|
102
|
+
threshold: 0.2,
|
103
|
+
keys: [
|
104
|
+
{
|
105
|
+
name: 'title',
|
106
|
+
weight: 5,
|
107
|
+
},
|
108
|
+
{
|
109
|
+
name: 'description',
|
110
|
+
weight: 3,
|
111
|
+
},
|
112
|
+
{
|
113
|
+
name: 'path',
|
114
|
+
weight: 2,
|
115
|
+
},
|
116
|
+
{
|
117
|
+
name: 'documentation',
|
118
|
+
weight: 1,
|
119
|
+
},
|
120
|
+
],
|
121
|
+
// extended search allows for exact word match through single quote
|
122
|
+
// See https://fusejs.io/examples.html#extended-search
|
123
|
+
useExtendedSearch: true,
|
124
|
+
});
|
71
125
|
}
|
72
126
|
|
73
127
|
static async initialize(
|
@@ -94,6 +148,10 @@ export class ShowcaseRegistry {
|
|
94
148
|
}),
|
95
149
|
);
|
96
150
|
|
151
|
+
registry.showcaseSearchEngine.setCollection(
|
152
|
+
Array.from(registry.showcasesIndex.values()),
|
153
|
+
);
|
154
|
+
|
97
155
|
return registry;
|
98
156
|
}
|
99
157
|
|
@@ -104,4 +162,74 @@ export class ShowcaseRegistry {
|
|
104
162
|
getShowcase(path: string): PlainObject<Showcase> | undefined {
|
105
163
|
return this.RAW__showcaseIndex.get(path);
|
106
164
|
}
|
165
|
+
|
166
|
+
async search(searchText: string): Promise<ShowcaseTextSearchResult> {
|
167
|
+
const matches: ShowcaseTextSearchMatch[] = [];
|
168
|
+
// NOTE: for text search, we only support case-insensitive search now
|
169
|
+
const lowerCaseSearchText = searchText.toLowerCase();
|
170
|
+
await Promise.all(
|
171
|
+
Array.from(this.showcasesIndex.values()).map((showcase) =>
|
172
|
+
promisify(() => {
|
173
|
+
const result: ShowcaseTextSearchMatch = {
|
174
|
+
path: showcase.path,
|
175
|
+
matches: [],
|
176
|
+
preview: [],
|
177
|
+
};
|
178
|
+
const previewLines = new Map<number, string>();
|
179
|
+
const code = showcase.code;
|
180
|
+
const lines = code.split('\n');
|
181
|
+
lines.forEach((line, lineIdx) => {
|
182
|
+
const lowerCaseLine = line.toLowerCase();
|
183
|
+
let fromIdx = 0;
|
184
|
+
let currentMatchIdx = lowerCaseLine.indexOf(
|
185
|
+
lowerCaseSearchText,
|
186
|
+
fromIdx,
|
187
|
+
);
|
188
|
+
while (currentMatchIdx !== -1) {
|
189
|
+
const previewTextStartLineIdx = Math.max(lineIdx - 1, 0);
|
190
|
+
previewLines.set(
|
191
|
+
previewTextStartLineIdx + 1,
|
192
|
+
getNonNullableEntry(lines, previewTextStartLineIdx),
|
193
|
+
);
|
194
|
+
previewLines.set(
|
195
|
+
lineIdx + 1,
|
196
|
+
getNonNullableEntry(lines, lineIdx),
|
197
|
+
);
|
198
|
+
const previewTextEndLineIdx = Math.min(
|
199
|
+
lineIdx + 1,
|
200
|
+
lines.length - 1,
|
201
|
+
);
|
202
|
+
previewLines.set(
|
203
|
+
previewTextEndLineIdx + 1,
|
204
|
+
getNonNullableEntry(lines, previewTextEndLineIdx),
|
205
|
+
);
|
206
|
+
result.matches.push({
|
207
|
+
line: lineIdx + 1,
|
208
|
+
startColumn: currentMatchIdx + 1,
|
209
|
+
endColumn: currentMatchIdx + 1 + lowerCaseSearchText.length,
|
210
|
+
});
|
211
|
+
fromIdx = currentMatchIdx + lowerCaseSearchText.length;
|
212
|
+
currentMatchIdx = lowerCaseLine.indexOf(
|
213
|
+
lowerCaseSearchText,
|
214
|
+
fromIdx,
|
215
|
+
);
|
216
|
+
}
|
217
|
+
});
|
218
|
+
if (!result.matches.length) {
|
219
|
+
return;
|
220
|
+
}
|
221
|
+
result.preview = Array.from(previewLines.entries())
|
222
|
+
.map(([line, text]) => ({ line, text }))
|
223
|
+
.sort((a, b) => a.line - b.line);
|
224
|
+
matches.push(result);
|
225
|
+
}),
|
226
|
+
),
|
227
|
+
);
|
228
|
+
return {
|
229
|
+
showcases: Array.from(
|
230
|
+
this.showcaseSearchEngine.search(searchText).values(),
|
231
|
+
).map((result) => result.item.path),
|
232
|
+
textMatches: matches,
|
233
|
+
};
|
234
|
+
}
|
107
235
|
}
|
@@ -26,6 +26,12 @@ interface GetShowcaseRequest extends RequestGenericInterface {
|
|
26
26
|
};
|
27
27
|
}
|
28
28
|
|
29
|
+
interface TextSearchRequest extends RequestGenericInterface {
|
30
|
+
Querystring: {
|
31
|
+
searchText: string;
|
32
|
+
};
|
33
|
+
}
|
34
|
+
|
29
35
|
export const configureShowcaseRegistryServer = async (
|
30
36
|
server: FastifyInstance,
|
31
37
|
config: ShowcaseRegistryConfig & {
|
@@ -53,7 +59,12 @@ export const configureShowcaseRegistryServer = async (
|
|
53
59
|
},
|
54
60
|
);
|
55
61
|
|
56
|
-
server.get(
|
57
|
-
|
58
|
-
|
62
|
+
server.get<TextSearchRequest>(
|
63
|
+
`${baseUrl}/showcases/search`,
|
64
|
+
async (request, reply) => {
|
65
|
+
const { searchText } = request.query;
|
66
|
+
|
67
|
+
await reply.send(await registry.search(searchText));
|
68
|
+
},
|
69
|
+
);
|
59
70
|
};
|