@algolia/wizard 0.13.0 → 0.15.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/dist/main.js
CHANGED
|
@@ -1079,12 +1079,12 @@ var sidebarItems = [
|
|
|
1079
1079
|
description: "push 100 records to Algolia in seconds"
|
|
1080
1080
|
},
|
|
1081
1081
|
{
|
|
1082
|
-
title: "detect your
|
|
1083
|
-
description: "
|
|
1082
|
+
title: "detect your stack",
|
|
1083
|
+
description: "whatever language and framework you already use"
|
|
1084
1084
|
},
|
|
1085
1085
|
{
|
|
1086
1086
|
title: "scaffold a search UI",
|
|
1087
|
-
description: "a
|
|
1087
|
+
description: "a search box and results, wired into your app"
|
|
1088
1088
|
},
|
|
1089
1089
|
{
|
|
1090
1090
|
title: "ship it",
|
|
@@ -2821,11 +2821,19 @@ import z14 from "zod";
|
|
|
2821
2821
|
import { readdir as readdir2, readFile as readFile6 } from "node:fs/promises";
|
|
2822
2822
|
import { join as join8 } from "node:path";
|
|
2823
2823
|
var MAX_QUERY_LENGTH = 1e3;
|
|
2824
|
+
var SKIP_DIRS = /* @__PURE__ */ new Set([
|
|
2825
|
+
"node_modules",
|
|
2826
|
+
"dist",
|
|
2827
|
+
"build",
|
|
2828
|
+
"vendor",
|
|
2829
|
+
"venv",
|
|
2830
|
+
"__pycache__",
|
|
2831
|
+
"target"
|
|
2832
|
+
]);
|
|
2824
2833
|
async function walkFiles(dir) {
|
|
2825
|
-
const skip = /* @__PURE__ */ new Set(["node_modules", ".git", "dist"]);
|
|
2826
2834
|
const out = [];
|
|
2827
2835
|
for (const e of await readdir2(dir, { withFileTypes: true })) {
|
|
2828
|
-
if (e.name.startsWith(".") ||
|
|
2836
|
+
if (e.name.startsWith(".") || SKIP_DIRS.has(e.name)) continue;
|
|
2829
2837
|
const full = join8(dir, e.name);
|
|
2830
2838
|
if (e.isDirectory()) out.push(...await walkFiles(full));
|
|
2831
2839
|
else if (e.isFile()) out.push(full);
|
|
@@ -3155,7 +3163,7 @@ function generateRecordTool(ctx) {
|
|
|
3155
3163
|
return {
|
|
3156
3164
|
filePath: relPath,
|
|
3157
3165
|
count: records.length,
|
|
3158
|
-
message: `Wrote ${records.length} records to ${relPath}. Read and parse this file in the script at runtime
|
|
3166
|
+
message: `Wrote ${records.length} records to ${relPath}. Read and parse this file in the script at runtime using your language's standard JSON support \u2014 do not inline the records as literals.`
|
|
3159
3167
|
};
|
|
3160
3168
|
} catch (err) {
|
|
3161
3169
|
return `Error generating records: ${err.message}`;
|
|
@@ -3344,8 +3352,8 @@ var detectLanguageSchema = z20.object({
|
|
|
3344
3352
|
var detectLanguage = () => runAgent({
|
|
3345
3353
|
instructions: [
|
|
3346
3354
|
"Analyze the codebase and determine the programming languages and frameworks used",
|
|
3347
|
-
"If a superset language is found, exclude the subset language.
|
|
3348
|
-
"If a meta-framework is used, exclude the framework. Next
|
|
3355
|
+
"If a superset language is found, exclude the subset language (e.g. TypeScript over JavaScript).",
|
|
3356
|
+
"If a meta-framework is used, exclude the framework it builds on (e.g. Next.js over React, Rails over Rack).",
|
|
3349
3357
|
"Return the exact version",
|
|
3350
3358
|
"Exclude things like CSS frameworks, build tools, or testing frameworks",
|
|
3351
3359
|
'Use as few tools as possible, but do not guess. If you cant find the answer, say "unknown"',
|
|
@@ -3443,7 +3451,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
3443
3451
|
// package.json
|
|
3444
3452
|
var package_default = {
|
|
3445
3453
|
name: "@algolia/wizard",
|
|
3446
|
-
version: "0.
|
|
3454
|
+
version: "0.15.0",
|
|
3447
3455
|
description: "Magically implement Algolia functionality in your codebase",
|
|
3448
3456
|
type: "module",
|
|
3449
3457
|
engines: {
|
|
@@ -3592,9 +3600,11 @@ var CURATED_FRAMEWORKS = [
|
|
|
3592
3600
|
"Next.js",
|
|
3593
3601
|
"React",
|
|
3594
3602
|
"Vue",
|
|
3595
|
-
"
|
|
3596
|
-
"
|
|
3597
|
-
"
|
|
3603
|
+
"Vanilla JS",
|
|
3604
|
+
"Django",
|
|
3605
|
+
"Laravel",
|
|
3606
|
+
"Rails",
|
|
3607
|
+
"Symfony"
|
|
3598
3608
|
];
|
|
3599
3609
|
var OTHER_OPTION = "Other";
|
|
3600
3610
|
var normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
@@ -3607,12 +3617,15 @@ var FRAMEWORK_ALIASES = {
|
|
|
3607
3617
|
vuejs: "vue",
|
|
3608
3618
|
angular: "angular",
|
|
3609
3619
|
angularjs: "angular",
|
|
3610
|
-
svelte: "svelte",
|
|
3611
|
-
sveltekit: "svelte",
|
|
3612
3620
|
vanillajs: "vanillajs",
|
|
3613
3621
|
vanilla: "vanillajs",
|
|
3614
3622
|
javascript: "vanillajs",
|
|
3615
|
-
js: "vanillajs"
|
|
3623
|
+
js: "vanillajs",
|
|
3624
|
+
django: "django",
|
|
3625
|
+
laravel: "laravel",
|
|
3626
|
+
rails: "rails",
|
|
3627
|
+
rubyonrails: "rails",
|
|
3628
|
+
symfony: "symfony"
|
|
3616
3629
|
};
|
|
3617
3630
|
var isSameFramework = (a, b) => {
|
|
3618
3631
|
const x = FRAMEWORK_ALIASES[normalize(a)] ?? normalize(a);
|
|
@@ -4076,6 +4089,7 @@ function getNamedDoc(name, language) {
|
|
|
4076
4089
|
return readFileSync(file, "utf8").trim();
|
|
4077
4090
|
}
|
|
4078
4091
|
function getFrameworkSpecificDoc(frameworks) {
|
|
4092
|
+
if (frameworks.length === 0) return "";
|
|
4079
4093
|
const fw = frameworks.map((f) => f.toLowerCase());
|
|
4080
4094
|
if (fw.includes("vue") || fw.includes("nuxt")) {
|
|
4081
4095
|
return loadAlgoliaDoc("vue");
|
|
@@ -4083,9 +4097,6 @@ function getFrameworkSpecificDoc(frameworks) {
|
|
|
4083
4097
|
if (fw.includes("react") || fw.includes("next.js")) {
|
|
4084
4098
|
return loadAlgoliaDoc("react");
|
|
4085
4099
|
}
|
|
4086
|
-
if (fw.includes("angular")) {
|
|
4087
|
-
return loadAlgoliaDoc("angular");
|
|
4088
|
-
}
|
|
4089
4100
|
return loadAlgoliaDoc("js");
|
|
4090
4101
|
}
|
|
4091
4102
|
|
|
@@ -4123,30 +4134,34 @@ var verificationOutputSchema = z27.object({
|
|
|
4123
4134
|
var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
|
|
4124
4135
|
var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
|
|
4125
4136
|
var INGEST_DIR = ".algolia-wizard";
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
if (names.some((n) => n.includes("react") || n.includes("next")))
|
|
4130
|
-
return "React";
|
|
4131
|
-
if (names.some((n) => n.includes("angular"))) return "Angular";
|
|
4132
|
-
return "JavaScript";
|
|
4133
|
-
}
|
|
4134
|
-
function frameworksForDoc(framework) {
|
|
4135
|
-
switch (framework) {
|
|
4136
|
-
case "React":
|
|
4137
|
-
return ["react"];
|
|
4138
|
-
case "Vue":
|
|
4139
|
-
return ["vue"];
|
|
4140
|
-
case "Angular":
|
|
4141
|
-
return ["angular"];
|
|
4142
|
-
case "JavaScript":
|
|
4143
|
-
return [];
|
|
4144
|
-
}
|
|
4137
|
+
var JS_LANGUAGES = ["javascript", "typescript", "jsx", "tsx", "node"];
|
|
4138
|
+
function lower(entries) {
|
|
4139
|
+
return entries.map((entry) => entry.name.toLowerCase());
|
|
4145
4140
|
}
|
|
4146
|
-
function
|
|
4147
|
-
|
|
4148
|
-
(
|
|
4141
|
+
function isJsProject(language) {
|
|
4142
|
+
return lower(language.languages).some(
|
|
4143
|
+
(name) => JS_LANGUAGES.some((js) => name.includes(js))
|
|
4149
4144
|
);
|
|
4145
|
+
}
|
|
4146
|
+
var UI_FRAMEWORKS = [
|
|
4147
|
+
{ match: ["vue", "nuxt"], target: "Vue", doc: "vue" },
|
|
4148
|
+
{ match: ["react", "next"], target: "React", doc: "react" },
|
|
4149
|
+
{ match: ["angular"], target: "Angular" }
|
|
4150
|
+
];
|
|
4151
|
+
function matchUiFramework(language) {
|
|
4152
|
+
const names = lower(language.frameworks);
|
|
4153
|
+
return UI_FRAMEWORKS.find(
|
|
4154
|
+
(ui) => ui.match.some((needle) => names.some((name) => name.includes(needle)))
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
function searchUiTarget(language) {
|
|
4158
|
+
return matchUiFramework(language)?.target ?? language.frameworks[0]?.name ?? (isJsProject(language) ? "JavaScript" : "this project");
|
|
4159
|
+
}
|
|
4160
|
+
function frameworksForDoc(language) {
|
|
4161
|
+
return [matchUiFramework(language)?.doc ?? "js"];
|
|
4162
|
+
}
|
|
4163
|
+
function publicEnvPrefix(language) {
|
|
4164
|
+
const frameworkNames = lower(language.frameworks);
|
|
4150
4165
|
if (frameworkNames.some((name) => name.includes("next"))) {
|
|
4151
4166
|
return "NEXT_PUBLIC_";
|
|
4152
4167
|
}
|
|
@@ -4159,7 +4174,7 @@ function publicEnvPrefix(language) {
|
|
|
4159
4174
|
if (frameworkNames.some((name) => name.includes("vite"))) {
|
|
4160
4175
|
return "VITE_";
|
|
4161
4176
|
}
|
|
4162
|
-
return "PUBLIC_";
|
|
4177
|
+
return isJsProject(language) ? "PUBLIC_" : "";
|
|
4163
4178
|
}
|
|
4164
4179
|
var APP_ID_VAR_SUFFIX = "ALGOLIA_APP_ID";
|
|
4165
4180
|
var SEARCH_KEY_VAR_SUFFIX = "ALGOLIA_SEARCH_API_KEY";
|
|
@@ -4200,6 +4215,7 @@ function baseInstructions(input) {
|
|
|
4200
4215
|
`Project languages and frameworks: ${JSON.stringify(input.language)}`,
|
|
4201
4216
|
"Make minimal, idiomatic changes; do not touch unrelated code.",
|
|
4202
4217
|
`Commands run through a shell on ${process.platform}. Write commands that work there.`,
|
|
4218
|
+
"Use the project's own tooling for every command \u2014 its package manager, task runner, and test/lint commands. Do not assume a JavaScript toolchain.",
|
|
4203
4219
|
"runShell needs the developer to approve each command, so give every call a clear `explanation` naming what it does and any side effect. If a command is rejected, do not retry it \u2014 take a different approach or report the limitation."
|
|
4204
4220
|
];
|
|
4205
4221
|
}
|
|
@@ -4220,12 +4236,21 @@ function sourceSpecificInstructions(input) {
|
|
|
4220
4236
|
generated: [
|
|
4221
4237
|
"No real data source exists; use sample records for each confirmed entity.",
|
|
4222
4238
|
"Call the generateRecord tool once per entity (entityName, attributes, count 20-50); it invents the values and unique objectIDs and writes them to a JSON file in the worktree, returning the file path. Do not write records or objectIDs yourself.",
|
|
4223
|
-
"In the script, read and parse each returned file path at runtime
|
|
4239
|
+
"In the script, read and parse each returned file path at runtime using your language's standard JSON support, instead of inlining the records as literals.",
|
|
4224
4240
|
"Add a prominent TODO where the developer swaps the generated records (and the JSON file under `.algolia-wizard/data/`) for their real record source."
|
|
4225
4241
|
]
|
|
4226
4242
|
};
|
|
4227
4243
|
return byLine[input.ingestionSource];
|
|
4228
4244
|
}
|
|
4245
|
+
function algoliaClientDoc(input) {
|
|
4246
|
+
const doc = getNamedDoc("save-records", "js");
|
|
4247
|
+
if (!doc) return [];
|
|
4248
|
+
if (isJsProject(input.language)) return [doc];
|
|
4249
|
+
return [
|
|
4250
|
+
"The reference below is written in JavaScript. Use it for the method names, arguments, and record shape, then translate to this project's language and its official Algolia client:",
|
|
4251
|
+
doc
|
|
4252
|
+
];
|
|
4253
|
+
}
|
|
4229
4254
|
function ingestionInstructions(input) {
|
|
4230
4255
|
return [
|
|
4231
4256
|
...input.confirmed && input.confirmed.length ? [
|
|
@@ -4233,10 +4258,10 @@ function ingestionInstructions(input) {
|
|
|
4233
4258
|
`Ingest only these confirmed entities (name, source paths, attributes): ${JSON.stringify(input.confirmed)}.`,
|
|
4234
4259
|
`Ingesting writes to Algolia, so the script needs a write API key and App ID \u2014 read them from the ${API_KEY_VAR} and ${APP_ID_VAR} environment variables rather than hardcoding them. The wizard sets these when it runs the script.`,
|
|
4235
4260
|
`Read the index name from the ${INDEX_NAME_VAR} environment variable, which the wizard sets to "${input.targetIndex}". Never hardcode an index name or derive one from the project, file, or entity name \u2014 the write key only works for that exact index. Exit with an error if ${INDEX_NAME_VAR} is unset.`,
|
|
4236
|
-
"
|
|
4261
|
+
"Write the script in the project's primary language, using Algolia's official client for that language. Do not use the raw HTTP API.",
|
|
4237
4262
|
"After a successful ingest, the script must print exactly one line to stdout in the form `ALGOLIA_WIZARD_RECORD_COUNT=<n>`, where <n> is the total number of records pushed to Algolia. Print it last, on its own line, with no surrounding text.",
|
|
4238
|
-
|
|
4239
|
-
|
|
4263
|
+
...algoliaClientDoc(input),
|
|
4264
|
+
"Install the Algolia client with the project's own package manager via runShell, declaring it in whatever manifest the project uses (e.g. package.json, requirements.txt, Gemfile, go.mod, composer.json) so the dependency is not just installed ad hoc.",
|
|
4240
4265
|
'Then run the script yourself via runShell, and report the command you ran as "ingestCommand" so the developer can re-run it. Its explanation must say that running it writes records to Algolia.',
|
|
4241
4266
|
"The summary should be extremely concise.",
|
|
4242
4267
|
...sourceSpecificInstructions(input)
|
|
@@ -4244,13 +4269,18 @@ function ingestionInstructions(input) {
|
|
|
4244
4269
|
];
|
|
4245
4270
|
}
|
|
4246
4271
|
function searchInstructions(input) {
|
|
4247
|
-
const doc = getFrameworkSpecificDoc(frameworksForDoc(input.
|
|
4272
|
+
const doc = getFrameworkSpecificDoc(frameworksForDoc(input.language));
|
|
4248
4273
|
return [
|
|
4249
4274
|
"Implement an in-app Algolia search experience.",
|
|
4250
|
-
`Build the search UI for ${input.
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4275
|
+
`Build the search UI for ${input.searchUiTarget}.`,
|
|
4276
|
+
...doc ? [
|
|
4277
|
+
"Follow the Algolia SDK reference below for client setup and search UI wiring; prefer it over prior knowledge:",
|
|
4278
|
+
doc
|
|
4279
|
+
] : [
|
|
4280
|
+
"No bundled Algolia SDK reference exists for this stack, so rely on the project's own conventions and Algolia's official client for its language. Do not invent APIs \u2014 keep to the documented search endpoint and its parameters."
|
|
4281
|
+
],
|
|
4282
|
+
`Add the search UI at ${input.searchLocation ? `"${input.searchLocation}"` : "the best shared, always-rendered layout location (e.g. a header/nav component)"} so it is reachable across the app \u2014 at least a working search input and results list against the target index.`,
|
|
4283
|
+
"If a search box already exists, replace it with yours.",
|
|
4254
4284
|
`Read the index name from the ${searchIndexVar(input.language)} env var, which the wizard sets to "${input.targetIndex}". Never hardcode an index name or derive one from the project, file, or component name.`,
|
|
4255
4285
|
"Read the App ID, the search-only API key, and the index name from env vars; never hardcode them. A search-only key is safe to expose client-side.",
|
|
4256
4286
|
// The key is provisioned only after verification passes, so the agent never
|
|
@@ -4261,8 +4291,9 @@ function searchInstructions(input) {
|
|
|
4261
4291
|
// Not the agent's to rename: the wizard writes these exact names into
|
|
4262
4292
|
// ".env" right after this step, so a renamed prefix would leave the code
|
|
4263
4293
|
// reading a var the wizard never wrote.
|
|
4264
|
-
`Use exactly these
|
|
4265
|
-
|
|
4294
|
+
`Use exactly these env var names in the code: ${input.searchEnvVars.map(({ name }) => name).join(", ")}.`,
|
|
4295
|
+
"Install any Algolia packages you import with the project's own package manager via runShell, and declare them in the project's dependency manifest.",
|
|
4296
|
+
"Match the styles of the application as closely as possible.",
|
|
4266
4297
|
"The summary should be extremely concise; do not mention env var setup or manual testing steps \u2014 the wizard writes the resolved credentials to .env and reports that separately."
|
|
4267
4298
|
];
|
|
4268
4299
|
}
|
|
@@ -4491,7 +4522,7 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
4491
4522
|
ingestDir: INGEST_DIR,
|
|
4492
4523
|
ingestionSource,
|
|
4493
4524
|
uploadFilePath,
|
|
4494
|
-
|
|
4525
|
+
searchUiTarget: searchUiTarget(language)
|
|
4495
4526
|
};
|
|
4496
4527
|
const summaries = [];
|
|
4497
4528
|
if (uploadWarning) summaries.push(uploadWarning);
|
|
@@ -10,8 +10,8 @@ InstantSearch).
|
|
|
10
10
|
- `algoliasearch` v5 (install `^5`)
|
|
11
11
|
- `react-instantsearch` v7 (install `^7`)
|
|
12
12
|
- `vue-instantsearch` v4 (install `^4`)
|
|
13
|
-
- `instantsearch.js` v4 (install `^4`) — also the
|
|
14
|
-
|
|
13
|
+
- `instantsearch.js` v4 (install `^4`) — also the choice for any framework without
|
|
14
|
+
its own flavor (Angular, Svelte); `angular-instantsearch` is archived, never use it
|
|
15
15
|
|
|
16
16
|
Always install the **latest stable** within the major (use a caret range like `^5` /
|
|
17
17
|
`^7`); never pin an exact patch.
|
|
@@ -30,7 +30,7 @@ Always install the **latest stable** within the major (use a caret range like `^
|
|
|
30
30
|
|
|
31
31
|
## Files
|
|
32
32
|
|
|
33
|
-
- `instantsearch-setup
|
|
34
|
-
|
|
33
|
+
- `instantsearch-setup-*.md` — InstantSearch wiring per framework (React, Vue, and
|
|
34
|
+
vanilla for everything else). Use this for the in-app search UI.
|
|
35
35
|
- `search-single-index.md` — direct/manual search via the core client
|
|
36
36
|
(`searchSingleIndex`), for cases where InstantSearch is not used.
|
|
@@ -31,3 +31,14 @@ search.addWidgets([
|
|
|
31
31
|
|
|
32
32
|
search.start()
|
|
33
33
|
```
|
|
34
|
+
|
|
35
|
+
## Frameworks without their own flavor
|
|
36
|
+
|
|
37
|
+
Only React and Vue have a maintained InstantSearch wrapper. For any other
|
|
38
|
+
framework — Angular, Svelte, Solid — drive `instantsearch.js` directly from a
|
|
39
|
+
component, mounting widgets against element refs and calling `search.dispose()`
|
|
40
|
+
on teardown.
|
|
41
|
+
|
|
42
|
+
Do NOT install `angular-instantsearch` or a community `*-instantsearch` package:
|
|
43
|
+
`angular-instantsearch` is deprecated and archived (last release v4.4.3, Sep 2024),
|
|
44
|
+
is incompatible with Angular v13+, and receives no security fixes.
|
package/package.json
CHANGED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
# InstantSearch setup
|
|
2
|
-
|
|
3
|
-
Install `instantsearch.js` (v4)
|
|
4
|
-
|
|
5
|
-
## Search client: always use the lite client
|
|
6
|
-
|
|
7
|
-
Import the client from `algoliasearch/lite` and alias it to `algoliasearch`
|
|
8
|
-
|
|
9
|
-
```ts
|
|
10
|
-
import { liteClient as algoliasearch } from 'algoliasearch/lite'
|
|
11
|
-
|
|
12
|
-
// Instantiate ONCE, outside components, with a stable reference.
|
|
13
|
-
const searchClient = algoliasearch(APP_ID, SEARCH_ONLY_KEY)
|
|
14
|
-
```
|
|
15
|
-
|
|
16
|
-
## Angular (use `instantsearch.js`)
|
|
17
|
-
|
|
18
|
-
Do NOT use `angular-instantsearch`: it is deprecated and archived (last release
|
|
19
|
-
v4.4.3, Sep 2024), not compatible with Ivy / modern Angular (v13+), and receives no
|
|
20
|
-
security fixes. Algolia recommends driving `instantsearch.js` directly from an Angular
|
|
21
|
-
component instead.
|
|
22
|
-
|
|
23
|
-
```ts
|
|
24
|
-
import {
|
|
25
|
-
Component,
|
|
26
|
-
ElementRef,
|
|
27
|
-
OnDestroy,
|
|
28
|
-
OnInit,
|
|
29
|
-
ViewChild,
|
|
30
|
-
} from '@angular/core'
|
|
31
|
-
import { liteClient as algoliasearch } from 'algoliasearch/lite'
|
|
32
|
-
import instantsearch from 'instantsearch.js'
|
|
33
|
-
import { searchBox, hits } from 'instantsearch.js/es/widgets'
|
|
34
|
-
|
|
35
|
-
@Component({
|
|
36
|
-
selector: 'app-search',
|
|
37
|
-
template: `<div #searchbox></div>
|
|
38
|
-
<div #hits></div>`,
|
|
39
|
-
})
|
|
40
|
-
export class SearchComponent implements OnInit, OnDestroy {
|
|
41
|
-
@ViewChild('searchbox', { static: true }) searchbox!: ElementRef
|
|
42
|
-
@ViewChild('hits', { static: true }) hits!: ElementRef
|
|
43
|
-
|
|
44
|
-
private search = instantsearch({
|
|
45
|
-
indexName: 'INDEX_NAME',
|
|
46
|
-
searchClient: algoliasearch(APP_ID, SEARCH_ONLY_KEY),
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
ngOnInit() {
|
|
50
|
-
this.search.addWidgets([
|
|
51
|
-
searchBox({ container: this.searchbox.nativeElement }),
|
|
52
|
-
hits({ container: this.hits.nativeElement }),
|
|
53
|
-
])
|
|
54
|
-
this.search.start()
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
ngOnDestroy() {
|
|
58
|
-
this.search.dispose()
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Vanilla (`instantsearch.js` v4)
|
|
64
|
-
|
|
65
|
-
```js
|
|
66
|
-
import { liteClient as algoliasearch } from 'algoliasearch/lite'
|
|
67
|
-
import instantsearch from 'instantsearch.js'
|
|
68
|
-
import { searchBox, hits } from 'instantsearch.js/es/widgets'
|
|
69
|
-
|
|
70
|
-
const searchClient = algoliasearch(APP_ID, SEARCH_ONLY_KEY)
|
|
71
|
-
|
|
72
|
-
const search = instantsearch({ indexName: 'INDEX_NAME', searchClient })
|
|
73
|
-
|
|
74
|
-
search.addWidgets([
|
|
75
|
-
searchBox({ container: '#searchbox' }),
|
|
76
|
-
hits({ container: '#hits' }),
|
|
77
|
-
])
|
|
78
|
-
|
|
79
|
-
search.start()
|
|
80
|
-
```
|