@algolia/wizard 0.19.0 → 0.20.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 +106 -80
- package/package.json +1 -1
package/dist/main.js
CHANGED
|
@@ -2246,7 +2246,7 @@ async function ensureApplication() {
|
|
|
2246
2246
|
}
|
|
2247
2247
|
|
|
2248
2248
|
// src/workflows/default.ts
|
|
2249
|
-
import { z as
|
|
2249
|
+
import { z as z30 } from "zod";
|
|
2250
2250
|
|
|
2251
2251
|
// src/actions/listIndices.ts
|
|
2252
2252
|
import { z as z5 } from "zod";
|
|
@@ -2767,6 +2767,28 @@ async function ensureGitIgnored(root, target) {
|
|
|
2767
2767
|
var APP_ID_VAR = "ALGOLIA_APPLICATION_ID";
|
|
2768
2768
|
var API_KEY_VAR = "ALGOLIA_WRITE_API_KEY";
|
|
2769
2769
|
var INDEX_NAME_VAR = "ALGOLIA_INDEX_NAME";
|
|
2770
|
+
var PUBLIC_APP_ID_SUFFIX = "ALGOLIA_APP_ID";
|
|
2771
|
+
var PUBLIC_SEARCH_KEY_SUFFIX = "ALGOLIA_SEARCH_KEY";
|
|
2772
|
+
var PUBLIC_INDEX_NAME_SUFFIX = "ALGOLIA_INDEX_NAME";
|
|
2773
|
+
function publicAppIdVar(prefix) {
|
|
2774
|
+
return `${prefix}${PUBLIC_APP_ID_SUFFIX}`;
|
|
2775
|
+
}
|
|
2776
|
+
function publicSearchKeyVar(prefix) {
|
|
2777
|
+
return `${prefix}${PUBLIC_SEARCH_KEY_SUFFIX}`;
|
|
2778
|
+
}
|
|
2779
|
+
function publicIndexNameVar(prefix) {
|
|
2780
|
+
return `${prefix}${PUBLIC_INDEX_NAME_SUFFIX}`;
|
|
2781
|
+
}
|
|
2782
|
+
function publicSearchEnvVars(prefix, index, appId, searchKey) {
|
|
2783
|
+
return [
|
|
2784
|
+
{ name: publicAppIdVar(prefix), value: appId ?? "<your-algolia-app-id>" },
|
|
2785
|
+
{
|
|
2786
|
+
name: publicSearchKeyVar(prefix),
|
|
2787
|
+
value: searchKey ?? "<your-algolia-search-only-api-key>"
|
|
2788
|
+
},
|
|
2789
|
+
{ name: publicIndexNameVar(prefix), value: index }
|
|
2790
|
+
];
|
|
2791
|
+
}
|
|
2770
2792
|
function appendEnv(content, entries) {
|
|
2771
2793
|
const prefix = content.length > 0 && !content.endsWith("\n") ? "\n" : "";
|
|
2772
2794
|
const lines = entries.map(([name, value]) => `${name}=${value}
|
|
@@ -3500,7 +3522,10 @@ async function runAgent(req) {
|
|
|
3500
3522
|
import z21 from "zod";
|
|
3501
3523
|
var detectLanguageSchema = z21.object({
|
|
3502
3524
|
languages: z21.array(z21.object({ name: z21.string(), version: z21.string() })),
|
|
3503
|
-
frameworks: z21.array(z21.object({ name: z21.string(), version: z21.string() }))
|
|
3525
|
+
frameworks: z21.array(z21.object({ name: z21.string(), version: z21.string() })),
|
|
3526
|
+
publicEnvVarPrefix: z21.string().regex(/^([A-Z0-9]+_)*$/).describe(
|
|
3527
|
+
`The prefix a bundler/framework requires for an env var to reach client-side code (e.g. "NEXT_PUBLIC_", "VITE_", "NUXT_PUBLIC_"), uppercase with a trailing underscore when non-empty. Prefer the project's own existing convention over a framework default. Empty string when the project has no client-side env var exposure (e.g. a backend-only project).`
|
|
3528
|
+
)
|
|
3504
3529
|
});
|
|
3505
3530
|
var detectLanguage = () => runAgent({
|
|
3506
3531
|
instructions: [
|
|
@@ -3509,6 +3534,7 @@ var detectLanguage = () => runAgent({
|
|
|
3509
3534
|
"If a meta-framework is used, exclude the framework it builds on (e.g. Next.js over React, Rails over Rack).",
|
|
3510
3535
|
"Return the exact version",
|
|
3511
3536
|
"Exclude things like CSS frameworks, build tools, or testing frameworks",
|
|
3537
|
+
`Determine publicEnvVarPrefix: check the project's own env var usage first (e.g. names already referenced in code, .env/.env.example); if none exists, fall back to the detected framework's known convention for exposing env vars to client-side code; use "" when the project has no such convention (e.g. a backend-only project).`,
|
|
3512
3538
|
'Use as few tools as possible, but do not guess. If you cant find the answer, say "unknown"',
|
|
3513
3539
|
"When done, call reportStatus"
|
|
3514
3540
|
],
|
|
@@ -3604,7 +3630,7 @@ async function runAnalysis(mode, extraInstructions = []) {
|
|
|
3604
3630
|
// package.json
|
|
3605
3631
|
var package_default = {
|
|
3606
3632
|
name: "@algolia/wizard",
|
|
3607
|
-
version: "0.
|
|
3633
|
+
version: "0.20.0",
|
|
3608
3634
|
description: "Magically implement Algolia functionality in your codebase",
|
|
3609
3635
|
type: "module",
|
|
3610
3636
|
engines: {
|
|
@@ -4009,7 +4035,7 @@ ${formatCompletedSteps(ctx.completedSteps)}`,
|
|
|
4009
4035
|
};
|
|
4010
4036
|
|
|
4011
4037
|
// src/actions/implement.ts
|
|
4012
|
-
import
|
|
4038
|
+
import z29 from "zod";
|
|
4013
4039
|
import { join as join12 } from "node:path";
|
|
4014
4040
|
|
|
4015
4041
|
// src/lib/worktree.ts
|
|
@@ -4259,31 +4285,48 @@ function shellQuote(value) {
|
|
|
4259
4285
|
return "'" + value.replace(/'/g, "'\\''") + "'";
|
|
4260
4286
|
}
|
|
4261
4287
|
|
|
4288
|
+
// src/actions/resolveEnvVarPrefix.ts
|
|
4289
|
+
import z28 from "zod";
|
|
4290
|
+
var resolveEnvVarPrefixSchema = z28.object({
|
|
4291
|
+
publicEnvVarPrefix: detectLanguageSchema.shape.publicEnvVarPrefix
|
|
4292
|
+
});
|
|
4293
|
+
var resolveEnvVarPrefix = (frameworkName) => runAgent({
|
|
4294
|
+
instructions: [
|
|
4295
|
+
`The developer corrected the project's framework to "${frameworkName}".`,
|
|
4296
|
+
`Determine publicEnvVarPrefix for this framework: check the project's own env var usage first (e.g. names already referenced in code, .env/.env.example); if none exists, fall back to this framework's known convention for exposing env vars to client-side code; use "" when the framework has no such convention (e.g. a backend-only framework).`,
|
|
4297
|
+
'Use as few tools as possible, but do not guess. If you cant find the answer, say "unknown"',
|
|
4298
|
+
"When done, call reportStatus"
|
|
4299
|
+
],
|
|
4300
|
+
tools: ["listFiles", "changeDirectory", "readFile", "searchFiles"],
|
|
4301
|
+
outputSchema: resolveEnvVarPrefixSchema,
|
|
4302
|
+
modelSize: "small"
|
|
4303
|
+
});
|
|
4304
|
+
|
|
4262
4305
|
// src/actions/implement.ts
|
|
4263
|
-
var implementSchema =
|
|
4264
|
-
filesChanged:
|
|
4265
|
-
summary:
|
|
4266
|
-
worktreePath:
|
|
4267
|
-
ingestCommand:
|
|
4268
|
-
ingestScriptRan:
|
|
4269
|
-
ingestRecordCount:
|
|
4270
|
-
ingestDurationMs:
|
|
4271
|
-
ingestionSource:
|
|
4272
|
-
searchEnvVars:
|
|
4273
|
-
|
|
4274
|
-
name:
|
|
4275
|
-
value:
|
|
4306
|
+
var implementSchema = z29.object({
|
|
4307
|
+
filesChanged: z29.array(z29.string()),
|
|
4308
|
+
summary: z29.string(),
|
|
4309
|
+
worktreePath: z29.string().optional(),
|
|
4310
|
+
ingestCommand: z29.string().optional(),
|
|
4311
|
+
ingestScriptRan: z29.boolean().optional(),
|
|
4312
|
+
ingestRecordCount: z29.number().optional(),
|
|
4313
|
+
ingestDurationMs: z29.number().optional(),
|
|
4314
|
+
ingestionSource: z29.enum(["local", "fileUpload", "generated"]),
|
|
4315
|
+
searchEnvVars: z29.array(
|
|
4316
|
+
z29.object({
|
|
4317
|
+
name: z29.string(),
|
|
4318
|
+
value: z29.string()
|
|
4276
4319
|
})
|
|
4277
4320
|
).optional()
|
|
4278
4321
|
});
|
|
4279
|
-
var implementationOutputSchema =
|
|
4280
|
-
summary:
|
|
4281
|
-
ingestCommand:
|
|
4322
|
+
var implementationOutputSchema = z29.object({
|
|
4323
|
+
summary: z29.string(),
|
|
4324
|
+
ingestCommand: z29.string().optional()
|
|
4282
4325
|
});
|
|
4283
|
-
var verificationOutputSchema =
|
|
4284
|
-
summary:
|
|
4285
|
-
sufficient:
|
|
4286
|
-
additionalInstructions:
|
|
4326
|
+
var verificationOutputSchema = z29.object({
|
|
4327
|
+
summary: z29.string(),
|
|
4328
|
+
sufficient: z29.boolean(),
|
|
4329
|
+
additionalInstructions: z29.string().optional()
|
|
4287
4330
|
});
|
|
4288
4331
|
var MAX_IMPLEMENT_VERIFICATION_ATTEMPTS = 3;
|
|
4289
4332
|
var DEFAULT_IMPLEMENT_USE_CASES = ["ingestion", "search"];
|
|
@@ -4314,53 +4357,6 @@ function searchUiTarget(language) {
|
|
|
4314
4357
|
function frameworksForDoc(language) {
|
|
4315
4358
|
return [matchUiFramework(language)?.doc ?? "js"];
|
|
4316
4359
|
}
|
|
4317
|
-
function publicEnvPrefix(language) {
|
|
4318
|
-
const frameworkNames = lower(language.frameworks);
|
|
4319
|
-
if (frameworkNames.some((name) => name.includes("next"))) {
|
|
4320
|
-
return "NEXT_PUBLIC_";
|
|
4321
|
-
}
|
|
4322
|
-
if (frameworkNames.some((name) => name.includes("nuxt"))) {
|
|
4323
|
-
return "NUXT_PUBLIC_";
|
|
4324
|
-
}
|
|
4325
|
-
if (frameworkNames.some((name) => name.includes("astro"))) {
|
|
4326
|
-
return "PUBLIC_";
|
|
4327
|
-
}
|
|
4328
|
-
if (frameworkNames.some((name) => name.includes("vite"))) {
|
|
4329
|
-
return "VITE_";
|
|
4330
|
-
}
|
|
4331
|
-
return isJsProject(language) ? "PUBLIC_" : "";
|
|
4332
|
-
}
|
|
4333
|
-
var APP_ID_VAR_SUFFIX = "ALGOLIA_APP_ID";
|
|
4334
|
-
var SEARCH_KEY_VAR_SUFFIX = "ALGOLIA_SEARCH_API_KEY";
|
|
4335
|
-
var INDEX_VAR_SUFFIX = "ALGOLIA_INDEX_NAME";
|
|
4336
|
-
function appIdVar(language) {
|
|
4337
|
-
return `${publicEnvPrefix(language)}${APP_ID_VAR_SUFFIX}`;
|
|
4338
|
-
}
|
|
4339
|
-
function searchKeyVar(language) {
|
|
4340
|
-
return `${publicEnvPrefix(language)}${SEARCH_KEY_VAR_SUFFIX}`;
|
|
4341
|
-
}
|
|
4342
|
-
function searchIndexVar(language) {
|
|
4343
|
-
return `${publicEnvPrefix(language)}${INDEX_VAR_SUFFIX}`;
|
|
4344
|
-
}
|
|
4345
|
-
function searchEnvVars(language, index, appId, searchKey) {
|
|
4346
|
-
return [
|
|
4347
|
-
{
|
|
4348
|
-
name: appIdVar(language),
|
|
4349
|
-
value: appId ?? "<your-algolia-app-id>"
|
|
4350
|
-
},
|
|
4351
|
-
{
|
|
4352
|
-
name: searchKeyVar(language),
|
|
4353
|
-
value: searchKey ?? "<your-algolia-search-only-api-key>"
|
|
4354
|
-
},
|
|
4355
|
-
// Wizard-supplied rather than written into the generated code, because an
|
|
4356
|
-
// agent that retypes the name (appending the project name, re-casing it)
|
|
4357
|
-
// leaves the UI querying an index that does not exist.
|
|
4358
|
-
{
|
|
4359
|
-
name: searchIndexVar(language),
|
|
4360
|
-
value: index
|
|
4361
|
-
}
|
|
4362
|
-
];
|
|
4363
|
-
}
|
|
4364
4360
|
function baseInstructions(input) {
|
|
4365
4361
|
return [
|
|
4366
4362
|
// Agents have renamed this (e.g. appending the project name), which the
|
|
@@ -4436,7 +4432,7 @@ function searchInstructions(input) {
|
|
|
4436
4432
|
],
|
|
4437
4433
|
`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.`,
|
|
4438
4434
|
"If a search box already exists, replace it with yours.",
|
|
4439
|
-
`Read the index name from the ${
|
|
4435
|
+
`Read the index name from the ${publicIndexNameVar(input.publicEnvVarPrefix)} env var, which the wizard sets to "${input.targetIndex}". Never hardcode an index name or derive one from the project, file, or component name.`,
|
|
4440
4436
|
"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.",
|
|
4441
4437
|
// The key is provisioned only after verification passes, so the agent never
|
|
4442
4438
|
// sees one. It must also leave .env alone: the wizard reads that file to
|
|
@@ -4580,6 +4576,21 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
4580
4576
|
languages: ctx.getStepOutput("confirm-language")?.languages ?? scan.languages,
|
|
4581
4577
|
frameworks: ctx.getStepOutput("confirm-framework")?.frameworks ?? scan.frameworks
|
|
4582
4578
|
};
|
|
4579
|
+
const normalizeFrameworkName = (name) => name.toLowerCase().replace(/[^a-z0-9]/g, "");
|
|
4580
|
+
const confirmedPrimaryFramework = language.frameworks[0]?.name;
|
|
4581
|
+
const frameworkWasCorrected = confirmedPrimaryFramework !== void 0 && !scan.frameworks.some(
|
|
4582
|
+
(fw) => normalizeFrameworkName(fw.name) === normalizeFrameworkName(confirmedPrimaryFramework)
|
|
4583
|
+
);
|
|
4584
|
+
const publicEnvVarPrefixPromise = frameworkWasCorrected ? resolveEnvVarPrefix(confirmedPrimaryFramework).then(
|
|
4585
|
+
(r) => r.publicEnvVarPrefix,
|
|
4586
|
+
(err) => {
|
|
4587
|
+
logger.warn(
|
|
4588
|
+
{ err, framework: confirmedPrimaryFramework },
|
|
4589
|
+
"implement: could not re-resolve publicEnvVarPrefix after a framework correction; using the stale scan value"
|
|
4590
|
+
);
|
|
4591
|
+
return scan.publicEnvVarPrefix;
|
|
4592
|
+
}
|
|
4593
|
+
) : Promise.resolve(scan.publicEnvVarPrefix);
|
|
4583
4594
|
const selected = ctx.getStepOutput(
|
|
4584
4595
|
"select-index"
|
|
4585
4596
|
);
|
|
@@ -4667,14 +4678,20 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
4667
4678
|
);
|
|
4668
4679
|
}
|
|
4669
4680
|
}
|
|
4681
|
+
const publicEnvVarPrefix = await publicEnvVarPrefixPromise;
|
|
4670
4682
|
const input = {
|
|
4671
4683
|
findings: normalized,
|
|
4672
4684
|
confirmed: confirmed2,
|
|
4673
4685
|
searchLocation,
|
|
4674
4686
|
targetIndex,
|
|
4675
4687
|
language,
|
|
4688
|
+
publicEnvVarPrefix,
|
|
4676
4689
|
appId,
|
|
4677
|
-
searchEnvVars:
|
|
4690
|
+
searchEnvVars: publicSearchEnvVars(
|
|
4691
|
+
publicEnvVarPrefix,
|
|
4692
|
+
targetIndex,
|
|
4693
|
+
appId
|
|
4694
|
+
),
|
|
4678
4695
|
ingestDir: INGEST_DIR,
|
|
4679
4696
|
ingestionSource,
|
|
4680
4697
|
uploadFilePath,
|
|
@@ -4685,13 +4702,21 @@ async function implement(ctx, useCases = DEFAULT_IMPLEMENT_USE_CASES, existingWo
|
|
|
4685
4702
|
let envSearchKey;
|
|
4686
4703
|
let envAppIdMismatch = false;
|
|
4687
4704
|
if (useCases.includes("search") && appId) {
|
|
4688
|
-
const envAppId = await readEnvVar(
|
|
4705
|
+
const envAppId = await readEnvVar(
|
|
4706
|
+
worktree,
|
|
4707
|
+
publicAppIdVar(publicEnvVarPrefix)
|
|
4708
|
+
);
|
|
4689
4709
|
if (envAppId === appId) {
|
|
4690
|
-
envSearchKey = await readEnvVar(
|
|
4710
|
+
envSearchKey = await readEnvVar(
|
|
4711
|
+
worktree,
|
|
4712
|
+
publicSearchKeyVar(publicEnvVarPrefix)
|
|
4713
|
+
);
|
|
4691
4714
|
} else if (envAppId) {
|
|
4692
4715
|
envAppIdMismatch = true;
|
|
4716
|
+
const appIdVarName = publicAppIdVar(publicEnvVarPrefix);
|
|
4717
|
+
const searchKeyVarName = publicSearchKeyVar(publicEnvVarPrefix);
|
|
4693
4718
|
summaries.push(
|
|
4694
|
-
`\u26A0\uFE0F .env already sets ${
|
|
4719
|
+
`\u26A0\uFE0F .env already sets ${appIdVarName}=${envAppId}, but the active Algolia application is ${appId}. The wizard left those values alone \u2014 update ${appIdVarName} and ${searchKeyVarName} by hand, or searches will fail.`
|
|
4695
4720
|
);
|
|
4696
4721
|
logger.warn(
|
|
4697
4722
|
{ envAppId, appId },
|
|
@@ -4877,8 +4902,8 @@ ${detail}` : ""}`
|
|
|
4877
4902
|
);
|
|
4878
4903
|
}
|
|
4879
4904
|
}
|
|
4880
|
-
finalSearchEnvVars =
|
|
4881
|
-
|
|
4905
|
+
finalSearchEnvVars = publicSearchEnvVars(
|
|
4906
|
+
publicEnvVarPrefix,
|
|
4882
4907
|
targetIndex,
|
|
4883
4908
|
appId,
|
|
4884
4909
|
searchKey
|
|
@@ -4990,8 +5015,8 @@ var defaultWorkflow = {
|
|
|
4990
5015
|
defineStep({
|
|
4991
5016
|
id: "select-index",
|
|
4992
5017
|
title: "Set up index",
|
|
4993
|
-
outputSchema:
|
|
4994
|
-
selection:
|
|
5018
|
+
outputSchema: z30.object({
|
|
5019
|
+
selection: z30.string()
|
|
4995
5020
|
}),
|
|
4996
5021
|
run: (ctx) => selectIndexStep(ctx)
|
|
4997
5022
|
}),
|
|
@@ -5063,6 +5088,7 @@ function getWorkflow(id) {
|
|
|
5063
5088
|
var projectScan2 = {
|
|
5064
5089
|
languages: [{ name: "TypeScript", version: "5.7.2" }],
|
|
5065
5090
|
frameworks: [{ name: "Next.js", version: "15.1.0" }],
|
|
5091
|
+
publicEnvVarPrefix: "NEXT_PUBLIC_",
|
|
5066
5092
|
ingestionAnalysis: [
|
|
5067
5093
|
{
|
|
5068
5094
|
name: "Product",
|