@algolia/wizard 0.8.0-rc.64.51 → 0.8.0-rc.67.55

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
@@ -2206,6 +2206,8 @@ function shellQuote(value) {
2206
2206
  // src/lib/languages.ts
2207
2207
  var ENTRYPOINT_TOKEN = "{entrypoint}";
2208
2208
  var INGEST_DIR = ".algolia-wizard";
2209
+ var SWIFT_PACKAGE_DIR = `${INGEST_DIR}/Ingest`;
2210
+ var CSHARP_PROJECT = `${INGEST_DIR}/ingest/ingest.csproj`;
2209
2211
  var VISIBLE_INGEST_DIR = "algolia-wizard";
2210
2212
  var PY_VENV = `${INGEST_DIR}/.venv`;
2211
2213
  var PY_VENV_PYTHON = `${PY_VENV}/bin/python`;
@@ -2578,6 +2580,137 @@ var LANGUAGE_PROFILES = {
2578
2580
  // that some repos use it for source; scanning it is cheap, missing source
2579
2581
  // is not.
2580
2582
  skipDirs: ["target"]
2583
+ },
2584
+ csharp: {
2585
+ id: "csharp",
2586
+ displayName: "C#",
2587
+ aliases: ["c#", "csharp", "cs", ".net", "dotnet", "net", "asp.net"],
2588
+ manifests: ["*.csproj", "*.sln", "global.json"],
2589
+ packageManagers: [
2590
+ {
2591
+ id: "dotnet",
2592
+ // A self-contained project under .algolia-wizard keeps the ingest script
2593
+ // out of the repo's own build graph.
2594
+ dependency: { mode: "agent-declares", file: CSHARP_PROJECT },
2595
+ installSteps: [{ argv: ["dotnet", "restore", CSHARP_PROJECT] }],
2596
+ ingest: {
2597
+ kind: "auto",
2598
+ argv: ["dotnet", "run", "--project", ENTRYPOINT_TOKEN],
2599
+ entrypointExtensions: [".csproj"]
2600
+ }
2601
+ }
2602
+ ],
2603
+ sdk: {
2604
+ packageName: "Algolia.Search",
2605
+ versionPin: "7.*",
2606
+ docKey: "csharp"
2607
+ },
2608
+ ingestEntrypointExample: CSHARP_PROJECT,
2609
+ verification: [
2610
+ {
2611
+ label: "dotnet build",
2612
+ argv: ["dotnet", "build", CSHARP_PROJECT, "--nologo"],
2613
+ requiresFile: CSHARP_PROJECT
2614
+ }
2615
+ ],
2616
+ envReadInstruction: 'Read them from `Environment.GetEnvironmentVariable("NAME")`.',
2617
+ // Deliberately not `packages`: modern .NET uses PackageReference, and
2618
+ // `packages/` is where pnpm/Lerna/Turborepo monorepos keep all their source —
2619
+ // skipping it would hide the entities the scan is looking for.
2620
+ skipDirs: ["bin", "obj"]
2621
+ },
2622
+ swift: {
2623
+ id: "swift",
2624
+ displayName: "Swift",
2625
+ aliases: ["swift", "swiftui", "ios", "vapor"],
2626
+ manifests: ["Package.swift", "*.xcodeproj", "*.xcworkspace"],
2627
+ packageManagers: [
2628
+ {
2629
+ id: "swiftpm",
2630
+ dependency: {
2631
+ mode: "agent-declares",
2632
+ file: `${SWIFT_PACKAGE_DIR}/Package.swift`
2633
+ },
2634
+ // `swift build` resolves and fetches; a cold build of the client is slow
2635
+ // (minutes), which is why the caller degrades to the manual command when
2636
+ // this fails.
2637
+ installSteps: [
2638
+ {
2639
+ argv: ["swift", "build", "--package-path", SWIFT_PACKAGE_DIR],
2640
+ requiresFile: `${SWIFT_PACKAGE_DIR}/Package.swift`
2641
+ }
2642
+ ],
2643
+ ingest: {
2644
+ kind: "auto",
2645
+ argv: ["swift", "run", "--package-path", SWIFT_PACKAGE_DIR],
2646
+ entrypointExtensions: [".swift"]
2647
+ }
2648
+ }
2649
+ ],
2650
+ sdk: {
2651
+ packageName: "algoliasearch-client-swift",
2652
+ // SwiftPM range syntax, not an exact version — a bare "9.0.0" in a
2653
+ // Package.swift dependency pins the patch.
2654
+ versionPin: 'from: "9.0.0"',
2655
+ docKey: "swift"
2656
+ },
2657
+ ingestEntrypointExample: `${SWIFT_PACKAGE_DIR}/Sources/Ingest/main.swift`,
2658
+ verification: [
2659
+ {
2660
+ label: "swift build",
2661
+ argv: ["swift", "build", "--package-path", SWIFT_PACKAGE_DIR],
2662
+ requiresFile: `${SWIFT_PACKAGE_DIR}/Package.swift`
2663
+ }
2664
+ ],
2665
+ envReadInstruction: "Read them from `ProcessInfo.processInfo.environment`.",
2666
+ skipDirs: ["Pods", "DerivedData", "Carthage", ".build"]
2667
+ },
2668
+ dart: {
2669
+ id: "dart",
2670
+ displayName: "Dart",
2671
+ aliases: ["dart", "flutter"],
2672
+ manifests: ["pubspec.yaml"],
2673
+ packageManagers: [
2674
+ {
2675
+ id: "flutter-pub",
2676
+ detectFiles: [".metadata"],
2677
+ dependency: { mode: "agent-declares", file: "pubspec.yaml" },
2678
+ installSteps: [{ argv: ["flutter", "pub", "get"] }],
2679
+ ingest: {
2680
+ kind: "auto",
2681
+ argv: ["dart", "run", ENTRYPOINT_TOKEN],
2682
+ entrypointExtensions: [".dart"]
2683
+ }
2684
+ },
2685
+ {
2686
+ id: "pub",
2687
+ dependency: { mode: "agent-declares", file: "pubspec.yaml" },
2688
+ installSteps: [{ argv: ["dart", "pub", "get"] }],
2689
+ ingest: {
2690
+ kind: "auto",
2691
+ argv: ["dart", "run", ENTRYPOINT_TOKEN],
2692
+ entrypointExtensions: [".dart"]
2693
+ }
2694
+ }
2695
+ ],
2696
+ sdk: {
2697
+ packageName: "algolia_client_search",
2698
+ versionPin: "^1.0.0",
2699
+ docKey: "dart"
2700
+ },
2701
+ ingestEntrypointExample: `${INGEST_DIR}/ingest.dart`,
2702
+ verification: [
2703
+ {
2704
+ // Gated on the directory it analyzes, not just pubspec.yaml: a run that
2705
+ // only built a search UI never created it, and `dart analyze` on a
2706
+ // missing path fails the whole verification pass.
2707
+ label: "dart analyze",
2708
+ argv: ["dart", "analyze", INGEST_DIR],
2709
+ requiresFile: INGEST_DIR
2710
+ }
2711
+ ],
2712
+ envReadInstruction: "Read them from `Platform.environment`.",
2713
+ skipDirs: ["build"]
2581
2714
  }
2582
2715
  };
2583
2716
  var DEFAULT_LANGUAGE_ID = "javascript";
@@ -3260,7 +3393,7 @@ var detectLanguageSchema = z16.object({
3260
3393
  var detectLanguage = () => runAgent({
3261
3394
  instructions: [
3262
3395
  "Analyze the codebase and determine the programming languages and frameworks used",
3263
- "Start from the dependency manifests: package.json, pyproject.toml, requirements.txt, Gemfile, composer.json, go.mod, pom.xml, build.gradle(.kts), build.sbt.",
3396
+ "Start from the dependency manifests: package.json, pyproject.toml, requirements.txt, Gemfile, composer.json, go.mod, pom.xml, build.gradle(.kts), *.csproj, build.sbt, Package.swift, pubspec.yaml.",
3264
3397
  "List the language that owns the backend/data code first \u2014 that is the one an ingestion script will be written in.",
3265
3398
  "If a superset language is found, exclude the subset language. TS-over-JS. Kotlin-over-Java when Kotlin is primary.",
3266
3399
  "If a meta-framework is used, exclude the framework. Next-over-React.",
@@ -3313,7 +3446,7 @@ var MODE_CONFIG = {
3313
3446
  "Analyze the codebase to find the data entities (models) that should be ingested into Algolia.",
3314
3447
  "For each entity, return its name, the file path(s) where it is defined, and its indexable attribute keys (the fields a user would search or filter on).",
3315
3448
  "Inspect the source of each entity to extract real field names for attributes \u2014 do not guess or leave attributes empty.",
3316
- "Entities live wherever the stack keeps them: TypeScript interfaces or a Prisma schema, Django models.py, Rails app/models, Laravel Eloquent models, JPA @Entity classes, Go structs, Pydantic models.",
3449
+ "Entities live wherever the stack keeps them: TypeScript interfaces or a Prisma schema, Django models.py, Rails app/models, Laravel Eloquent models, JPA @Entity classes, Go structs, C# entity classes, Pydantic models.",
3317
3450
  "Prefer domain models (e.g. Document, Product, User) over framework or infrastructure types.",
3318
3451
  "Use as few tools as possible, but do not guess. If you cannot find any entities, return an empty array.",
3319
3452
  "Ignore directories that may be related to testing, like `/fixtures`, `/tests`, etc",
@@ -3336,7 +3469,7 @@ var MODE_CONFIG = {
3336
3469
  verification: {
3337
3470
  instructions: [
3338
3471
  "Analyze the codebase to determine which code-quality tools are available to validate changes.",
3339
- "Look at the dependency manifest and config files for the project's languages: package.json scripts with tsconfig/eslint/prettier, pyproject.toml or setup.cfg (ruff, mypy, black), Gemfile with .rubocop.yml, composer.json scripts (phpstan, pint), go.mod with a golangci-lint config, Maven/Gradle verification tasks.",
3472
+ "Look at the dependency manifest and config files for the project's languages: package.json scripts with tsconfig/eslint/prettier, pyproject.toml or setup.cfg (ruff, mypy, black), Gemfile with .rubocop.yml, composer.json scripts (phpstan, pint), go.mod with a golangci-lint config, Maven/Gradle verification tasks, .NET analyzers, analysis_options.yaml.",
3340
3473
  'Return the tool names as an array, e.g. ["eslint", "prettier", "tsc"] or ["ruff", "mypy"].',
3341
3474
  "Use as few tools as possible, but do not guess. If you cannot find any, return an empty array.",
3342
3475
  "Ignore directories that may be related to testing, like `/fixtures`, `/tests`, etc",
@@ -3364,7 +3497,7 @@ async function runAnalysis(mode, extraInstructions = []) {
3364
3497
  // package.json
3365
3498
  var package_default = {
3366
3499
  name: "@algolia/wizard",
3367
- version: "0.8.0-rc.64.51",
3500
+ version: "0.8.0-rc.67.55",
3368
3501
  description: "Magically implement Algolia functionality in your codebase",
3369
3502
  type: "module",
3370
3503
  engines: {
@@ -23,6 +23,9 @@ Install the latest stable within the major; never pin an exact patch.
23
23
  | Java | `com.algolia:algoliasearch` | `4.+` |
24
24
  | Kotlin | `com.algolia:algoliasearch-client-kotlin` | `3.+` |
25
25
  | Scala | `com.algolia:algoliasearch-scala_2.13` | `2.+` |
26
+ | C# | `Algolia.Search` | `7.*` |
27
+ | Swift | `algoliasearch-client-swift` | `9.0.0` |
28
+ | Dart | `algolia_client_search` | `^1.0.0` |
26
29
 
27
30
  ## Search UI
28
31
 
@@ -0,0 +1,71 @@
1
+ # Save records (Algolia.Search v7)
2
+
3
+ Adds records to an index. Write op — use a **write key**, server-side only.
4
+
5
+ The generated script is a self-contained console project at
6
+ `.algolia-wizard/ingest/ingest.csproj` + `Program.cs`, run with
7
+ `dotnet run --project .algolia-wizard/ingest/ingest.csproj`.
8
+
9
+ ```xml
10
+ <Project Sdk="Microsoft.NET.Sdk">
11
+ <PropertyGroup>
12
+ <OutputType>Exe</OutputType>
13
+ <TargetFramework>net8.0</TargetFramework>
14
+ <ImplicitUsings>enable</ImplicitUsings>
15
+ <Nullable>enable</Nullable>
16
+ </PropertyGroup>
17
+ <ItemGroup>
18
+ <PackageReference Include="Algolia.Search" Version="7.*" />
19
+ </ItemGroup>
20
+ </Project>
21
+ ```
22
+
23
+ `<OutputType>Exe</OutputType>` is required — `dotnet run` on a library has no entry
24
+ point. `<TargetFramework>` must match an installed SDK; `net8.0` (LTS) is the safe
25
+ default. Under Central Package Management (`Directory.Packages.props` at the repo
26
+ root) omit `Version` here and pin it there — `Version` on a `PackageReference` is
27
+ an error under CPM (NU1008).
28
+
29
+ ```csharp
30
+ using System.Text.Json;
31
+ using Algolia.Search.Clients;
32
+
33
+ var appId = Environment.GetEnvironmentVariable("ALGOLIA_APPLICATION_ID")
34
+ ?? throw new InvalidOperationException("ALGOLIA_APPLICATION_ID is not set");
35
+ var writeKey = Environment.GetEnvironmentVariable("ALGOLIA_WRITE_API_KEY")
36
+ ?? throw new InvalidOperationException("ALGOLIA_WRITE_API_KEY is not set");
37
+
38
+ var client = new SearchClient(new SearchConfig(appId, writeKey));
39
+ var indexName = "products";
40
+
41
+ var records = new List<Dictionary<string, object>>
42
+ {
43
+ new() { ["objectID"] = "1", ["name"] = "Adam" },
44
+ new() { ["objectID"] = "2", ["name"] = "Benoit" },
45
+ };
46
+
47
+ var responses = await client.SaveObjectsAsync(indexName, records, waitForTasks: true);
48
+ ```
49
+
50
+ ```csharp
51
+ Task<List<BatchResponse>> SaveObjectsAsync<T>(
52
+ string indexName, IEnumerable<T> objects, bool waitForTasks = false,
53
+ int batchSize = 1000, RequestOptions options = null,
54
+ CancellationToken cancellationToken = default) where T : class;
55
+ ```
56
+
57
+ Records need an `objectID`; batching in 1,000s is automatic. Returns
58
+ `List<BatchResponse>` — one entry per batch, each `{ TaskID, ObjectIDs }`, never a
59
+ single response. `T` is constrained to `class`, so use `Dictionary<string, object>`
60
+ or a record/class, never a struct.
61
+
62
+ Read records from a JSON file:
63
+
64
+ ```csharp
65
+ var json = await File.ReadAllTextAsync("records.json");
66
+ var records = JsonSerializer.Deserialize<List<Dictionary<string, object>>>(json)
67
+ ?? new List<Dictionary<string, object>>();
68
+ ```
69
+
70
+ After a successful ingest, print `ALGOLIA_WIZARD_RECORD_COUNT=<n>` as the last
71
+ stdout line; send all other logging to stderr so nothing follows it on stdout.
@@ -0,0 +1,74 @@
1
+ # Save records (algolia_client_search v1)
2
+
3
+ Adds records to an index. Write op — use a **write key**, server-side only.
4
+
5
+ Use the generated v2 client `algolia_client_search`, never the legacy community
6
+ `algolia` package. The script is run with `dart run .algolia-wizard/ingest.dart`.
7
+
8
+ ```yaml
9
+ dependencies:
10
+ algolia_client_search: ^1.0.0
11
+ ```
12
+
13
+ This client has **no `saveObjects` helper** (only `saveObjectsWithTransformation`,
14
+ which needs an Ingestion transformation) — use `batch` with `addObject` actions.
15
+
16
+ ```dart
17
+ import 'dart:convert';
18
+ import 'dart:io';
19
+ import 'dart:math';
20
+
21
+ import 'package:algolia_client_search/algolia_client_search.dart';
22
+
23
+ Future<void> main() async {
24
+ final appId = Platform.environment['ALGOLIA_APPLICATION_ID'];
25
+ final writeKey = Platform.environment['ALGOLIA_WRITE_API_KEY'];
26
+ if (appId == null || writeKey == null) {
27
+ stderr.writeln('missing Algolia credentials');
28
+ exit(1);
29
+ }
30
+
31
+ const indexName = 'products';
32
+ final client = SearchClient(appId: appId, apiKey: writeKey);
33
+
34
+ final records = <Map<String, dynamic>>[
35
+ {'objectID': '1', 'name': 'Adam'},
36
+ {'objectID': '2', 'name': 'Benoit'},
37
+ ];
38
+
39
+ try {
40
+ for (var i = 0; i < records.length; i += 1000) {
41
+ final chunk = records.sublist(i, min(i + 1000, records.length));
42
+ final response = await client.batch(
43
+ indexName: indexName,
44
+ batchWriteParams: BatchWriteParams(
45
+ requests: chunk
46
+ .map((r) => BatchRequest(action: Action.addObject, body: r))
47
+ .toList(),
48
+ ),
49
+ );
50
+ stderr.writeln('task ${response.taskID}');
51
+ }
52
+ print('ALGOLIA_WIZARD_RECORD_COUNT=${records.length}');
53
+ } finally {
54
+ client.dispose();
55
+ }
56
+ }
57
+ ```
58
+
59
+ `batch` returns a **single** `BatchResponse { int taskID, List<String> objectIDs }`,
60
+ not a list. Gotchas: every record needs an `objectID`; there is no auto-chunking,
61
+ so cap each call at 1,000 records yourself; use the `Action.addObject` enum value
62
+ (`Action.updateObject` replaces instead of adds); and `client.dispose()` is
63
+ mandatory — without it `dart run` never exits.
64
+
65
+ Read records from a JSON file:
66
+
67
+ ```dart
68
+ final json = await File('records.json').readAsString();
69
+ final records = (jsonDecode(json) as List).cast<Map<String, dynamic>>();
70
+ ```
71
+
72
+ After a successful ingest, print `ALGOLIA_WIZARD_RECORD_COUNT=<n>` as the last
73
+ stdout line (before `dispose()` is fine); send all other logging to stderr so
74
+ nothing follows it on stdout.
@@ -0,0 +1,88 @@
1
+ # Save records (algoliasearch-client-swift v9)
2
+
3
+ Adds records to an index. Write op — use a **write key**, server-side only.
4
+
5
+ The generated script is a standalone SwiftPM executable package at
6
+ `.algolia-wizard/Ingest` (`Package.swift` + `Sources/Ingest/main.swift`), run with
7
+ `swift run --package-path .algolia-wizard/Ingest`.
8
+
9
+ ```swift
10
+ // swift-tools-version: 5.9
11
+ import PackageDescription
12
+
13
+ let package = Package(
14
+ name: "Ingest",
15
+ platforms: [.macOS(.v13)],
16
+ products: [.executable(name: "Ingest", targets: ["Ingest"])],
17
+ dependencies: [
18
+ .package(url: "https://github.com/algolia/algoliasearch-client-swift", from: "9.0.0"),
19
+ ],
20
+ targets: [
21
+ .executableTarget(name: "Ingest", dependencies: [
22
+ .product(name: "AlgoliaSearch", package: "algoliasearch-client-swift"),
23
+ .product(name: "AlgoliaCore", package: "algoliasearch-client-swift"),
24
+ ]),
25
+ ]
26
+ )
27
+ ```
28
+
29
+ Exactly one executable product, so `swift run --package-path` needs no target name.
30
+ `platforms:` must be declared (the client requires macOS 11+); it is ignored on
31
+ Linux. `package:` is the repo name, not the manifest's `AlgoliaSearchClient`.
32
+
33
+ `main.swift` top-level code can't propagate a thrown error — wrap calls in `do`/`catch`.
34
+
35
+ ```swift
36
+ import Foundation
37
+ #if canImport(AlgoliaCore)
38
+ import AlgoliaCore
39
+ #endif
40
+ import AlgoliaSearch
41
+
42
+ let env = ProcessInfo.processInfo.environment
43
+ guard let appID = env["ALGOLIA_APPLICATION_ID"],
44
+ let writeKey = env["ALGOLIA_WRITE_API_KEY"]
45
+ else {
46
+ FileHandle.standardError.write(Data("missing Algolia credentials\n".utf8))
47
+ exit(1)
48
+ }
49
+ let indexName = "products"
50
+
51
+ do {
52
+ let client = try SearchClient(appID: appID, apiKey: writeKey)
53
+ let records: [AnyCodable] = [
54
+ ["objectID": "1", "name": "Adam"],
55
+ ["objectID": "2", "name": "Benoit"],
56
+ ]
57
+ let responses = try await client.saveObjects(
58
+ indexName: indexName, objects: records, waitForTasks: true
59
+ )
60
+ FileHandle.standardError.write(Data("batches: \(responses.count)\n".utf8))
61
+ print("ALGOLIA_WIZARD_RECORD_COUNT=\(records.count)")
62
+ } catch {
63
+ FileHandle.standardError.write(Data("\(error)\n".utf8))
64
+ exit(1)
65
+ }
66
+ ```
67
+
68
+ ```swift
69
+ func saveObjects(
70
+ indexName: String, objects: [some Encodable], waitForTasks: Bool = false,
71
+ batchSize: Int = 1000, requestOptions: RequestOptions? = nil
72
+ ) async throws -> [BatchResponse]
73
+ ```
74
+
75
+ Records need an `objectID`; batching in 1,000s is automatic. Returns an **array**
76
+ of `BatchResponse` (`taskID`, `objectIDs`), one per batch. `objects` is
77
+ `[some Encodable]` — one homogeneous element type, so use `[AnyCodable]` (from
78
+ `AlgoliaCore`) for arbitrary JSON records.
79
+
80
+ Read records from a JSON file:
81
+
82
+ ```swift
83
+ let data = try Data(contentsOf: URL(fileURLWithPath: "records.json"))
84
+ let records = try JSONDecoder().decode([AnyCodable].self, from: data)
85
+ ```
86
+
87
+ After a successful ingest, print `ALGOLIA_WIZARD_RECORD_COUNT=<n>` as the last
88
+ stdout line; send all other logging to stderr so nothing follows it on stdout.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@algolia/wizard",
3
- "version": "0.8.0-rc.64.51",
3
+ "version": "0.8.0-rc.67.55",
4
4
  "description": "Magically implement Algolia functionality in your codebase",
5
5
  "type": "module",
6
6
  "engines": {