batteryincluded 1.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026-present Frederik Bußmann
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,119 @@
1
+ <p align="center">
2
+ <picture>
3
+ <img src="https://batteryincluded.ai/wp-content/uploads/2026/04/full-logo-compact-4c-header.webp" alt="BatteryIncluded" width="290">
4
+ </picture>
5
+ </p>
6
+
7
+ # 🔋 BatteryIncluded TypeScript SDK
8
+
9
+ [![Github Actions][github-actions-src]][github-actions-href]
10
+ [![NPM version][npm-version-src]][npm-version-href]
11
+ [![NPM last update][npm-last-update-src]][npm-last-update-href]
12
+ [![License][license-src]][license-href]
13
+
14
+ An unofficial TypeScript SDK for [BatteryIncluded](https://batteryincluded.ai), the AI-infrastructure for E-Commerce search.
15
+ Provides type-safe access to the BatteryIncluded API for search, filters, recommendations and more.
16
+
17
+ ## Installation
18
+
19
+ ```sh
20
+ npm install batteryincluded
21
+ ```
22
+
23
+ ## Usage
24
+
25
+ 1. Create a .env file in the root of your project with the following content:
26
+
27
+ ```
28
+ BATTERYINCLUDED_COLLECTION=your-collection-name
29
+ BATTERYINCLUDED_API_KEY=your-api-key
30
+ ```
31
+
32
+ 2. Run the CLI to generate types based on your collection schema:
33
+
34
+ ```sh
35
+ npx batteryincluded ./path/to/output/dir
36
+ ```
37
+
38
+ 3. Use the client with full type safety:
39
+
40
+ ```typescript
41
+ import { createClient } from 'batteryincluded'
42
+
43
+ const client = createClient({
44
+ collection: 'your-collection-name',
45
+ apiKey: 'your-api-key',
46
+ })
47
+
48
+ const { data, error } = await client.GET('/browse', {
49
+ params: {
50
+ query: {
51
+ page: 1,
52
+ per_page: 20,
53
+ }
54
+ }
55
+ })
56
+
57
+ // Fully typed response data
58
+ console.log(data)
59
+ ```
60
+
61
+ > Make sure the output directory is included in your TypeScript project's `tsconfig.json` under the `include` array to ensure the generated types are available for import.
62
+
63
+ ## Available Endpoints
64
+
65
+ The SDK provides type-safe access to the following BatteryIncluded API endpoints:
66
+
67
+ - `/browse`: Search endpoint for retrieving documents.
68
+ - `/highlights`: Endpoint for retrieving query highlights.
69
+ - `/suggest`: Endpoint for getting search suggestions based on a text query.
70
+ - `/recommendations`: Endpoint for getting product recommendations based on a document ID.
71
+ - `/recommendations/cart`: Endpoint for getting product recommendations based on a cart ID.
72
+ - `/similar-search`: Endpoint for finding similar products based on a text query.
73
+ - `/presets`: Endpoint for retrieving available search presets.
74
+
75
+ ## Type Generation
76
+
77
+ The SDK includes a CLI tool that generates TypeScript types based on the responses from your BatteryIncluded collection.
78
+ This is a workaround to provide type safety for the API responses, as BatteryIncluded does not currently provide an OpenAPI schema.
79
+
80
+ In order to generate the types for these endpoints, the CLI will attempt to discover the schema by making requests to the API. For the `/recommendations` endpoint, it requires a document ID to generate recommendations. If no document ID is provided via the `--recommendation-id` flag, the CLI will automatically fetch the first document from the `/browse` endpoint to use its ID for generating recommendation types.
81
+
82
+ The query used for the `/suggest` and `/similar-search` endpoints can be customized using the `--suggest-query` flag, which defaults to 'a' to ensure it returns results for discovery.
83
+
84
+ ### Custom Probe Config
85
+
86
+ The CLI also supports loading custom probe configurations from a `batteryincluded.config.{js,json,mjs}` file in your project. This allows you to specify additional endpoints or customize the discovery process. If no custom config is provided, the CLI will use a default configuration that includes the necessary endpoints for generating types for search, suggestions, and recommendations.
87
+
88
+ ```ts
89
+ // batteryincluded.config.mjs
90
+ import { defineCodegenConfig } from 'batteryincluded'
91
+
92
+ export default defineCodegenConfig({
93
+ '/browse': {
94
+ query: {
95
+ page: 1,
96
+ // Load more documents for better schema discovery
97
+ per_page: 100,
98
+ },
99
+ },
100
+ })
101
+ ```
102
+
103
+ For more information on the code generator and how to customize the probe configuration, see the [AutoDisco](https://github.com/freb97/autodisco) documentation.
104
+
105
+ ## License
106
+
107
+ Published under the [MIT License](https://github.com/freb97/autodisco/tree/main/LICENSE).
108
+
109
+ [github-actions-src]: https://github.com/freb97/batteryincluded-ts/actions/workflows/test.yml/badge.svg
110
+ [github-actions-href]: https://github.com/freb97/batteryincluded-ts/actions
111
+
112
+ [npm-version-src]: https://img.shields.io/npm/v/batteryincluded-ts/latest.svg?style=flat&colorA=18181B&colorB=31C553
113
+ [npm-version-href]: https://npmjs.com/package/batteryincluded-ts
114
+
115
+ [npm-last-update-src]: https://img.shields.io/npm/last-update/batteryincluded-ts.svg?style=flat&colorA=18181B&colorB=31C553
116
+ [npm-last-update-href]: https://npmjs.com/package/batteryincluded-ts
117
+
118
+ [license-src]: https://img.shields.io/github/license/freb97/batteryincluded-ts.svg?style=flat&colorA=18181B&colorB=31C553
119
+ [license-href]: https://github.com/freb97/batteryincluded-ts/tree/main/LICENSE
@@ -0,0 +1,10 @@
1
+ import createOpenAPIClient from "openapi-fetch";
2
+ const buildBaseUrl = (collection) => `https://api.batteryincluded.io/api/v1/collections/${collection}/documents`;
3
+ const buildHeaders = (apiKey) => ({ "X-BI-API-KEY": apiKey });
4
+ function createClient(config) {
5
+ return createOpenAPIClient({
6
+ baseUrl: buildBaseUrl(config.collection),
7
+ headers: buildHeaders(config.apiKey)
8
+ });
9
+ }
10
+ export { buildBaseUrl, buildHeaders, createClient };
@@ -0,0 +1 @@
1
+ export { };
@@ -0,0 +1,105 @@
1
+ #!/usr/bin/env node
2
+ import { buildBaseUrl, buildHeaders, createClient } from "../_chunks/client.mjs";
3
+ import { writeFile } from "node:fs/promises";
4
+ import { join } from "node:path";
5
+ import process from "node:process";
6
+ import discover from "autodisco";
7
+ import { loadConfig } from "c12";
8
+ import { defineCommand, runMain } from "citty";
9
+ import defu from "defu";
10
+ import { config } from "dotenv";
11
+ const { parsed } = config({ quiet: true });
12
+ const env = parsed ?? process.env;
13
+ const COLLECTION = Object.entries(env).find(([key]) => key.endsWith("BATTERYINCLUDED_COLLECTION"))?.[1];
14
+ const API_KEY = Object.entries(env).find(([key]) => key.endsWith("BATTERYINCLUDED_API_KEY"))?.[1];
15
+ function buildAugmentationFile() {
16
+ return [
17
+ "import type { paths as generatedPaths, components as generatedComponents } from './openapi/types'",
18
+ "",
19
+ "declare module 'batteryincluded' {",
20
+ " interface paths extends generatedPaths {}",
21
+ " interface components extends generatedComponents {}",
22
+ "}",
23
+ "",
24
+ "export {}",
25
+ ""
26
+ ].join("\n");
27
+ }
28
+ runMain(defineCommand({
29
+ meta: {
30
+ name: "codegen",
31
+ description: "Generate OpenAPI Schema and TypeScript types for a BatteryIncluded collection."
32
+ },
33
+ args: {
34
+ outputDir: {
35
+ type: "positional",
36
+ description: "Location of the output directory.",
37
+ default: env.BATTERYINCLUDED_CODEGEN_OUTDIR ?? "batteryincluded/types",
38
+ required: false
39
+ },
40
+ collection: {
41
+ type: "string",
42
+ description: "The BatteryIncluded collection to use.",
43
+ default: COLLECTION,
44
+ required: false
45
+ },
46
+ apiKey: {
47
+ type: "string",
48
+ description: "The BatteryIncluded API key to use for authentication.",
49
+ default: API_KEY,
50
+ required: false
51
+ },
52
+ recommendationId: {
53
+ type: "string",
54
+ description: "The ID of the document to scan for generating recommendation types.",
55
+ required: false
56
+ },
57
+ suggestQuery: {
58
+ type: "string",
59
+ description: "The query for the suggestions to scan for generating suggestion types.",
60
+ required: false
61
+ }
62
+ },
63
+ run: async ({ args }) => {
64
+ if (!args.collection) throw new Error("Collection name is required. Please specify it using the --collection flag or set the BATTERYINCLUDED_COLLECTION environment variable.");
65
+ if (!args.apiKey) throw new Error("API key is required. Please specify it using the --api-key flag or set the BATTERYINCLUDED_API_KEY environment variable.");
66
+ const { config: resolved } = await loadConfig({
67
+ name: "batteryincluded",
68
+ cwd: process.cwd(),
69
+ rcFile: "batteryincluded-rc",
70
+ globalRc: false,
71
+ dotenv: false
72
+ });
73
+ let config = resolved ?? {};
74
+ const suggestQuery = args.suggestQuery ?? "a";
75
+ let recommendationId = args.recommendationId;
76
+ if (!recommendationId) recommendationId = await createClient({
77
+ collection: args.collection,
78
+ apiKey: args.apiKey
79
+ }).GET("/browse", { params: { query: { per_page: 1 } } }).then(({ data }) => data?.hits?.[0]?.document?.id);
80
+ if (!recommendationId) throw new Error("No document found in the collection to use for generating recommendation types. Please specify a document ID using the --recommendation-id flag or ensure that the collection contains at least one document.");
81
+ config = defu(config, {
82
+ "/browse": { query: {
83
+ page: 1,
84
+ per_page: 10
85
+ } },
86
+ "/highlights": {},
87
+ "/suggest": { query: { q: suggestQuery } },
88
+ "/recommendations": { query: { id: recommendationId } },
89
+ "/similar-search": { query: { q: suggestQuery } },
90
+ "/presets": {}
91
+ });
92
+ await discover({
93
+ baseUrl: buildBaseUrl(args.collection),
94
+ headers: buildHeaders(args.apiKey),
95
+ outputDir: args.outputDir,
96
+ generate: {
97
+ markdown: false,
98
+ openapi: { typescript: true }
99
+ },
100
+ probes: { get: { ...config } }
101
+ });
102
+ await writeFile(join(args.outputDir, "index.d.ts"), buildAugmentationFile(), "utf8");
103
+ }
104
+ }));
105
+ export {};
@@ -0,0 +1,30 @@
1
+ import { ProbeConfig } from "autodisco";
2
+ interface paths {}
3
+ interface components {}
4
+ type Suggest = components['schemas']['GetApiV1CollectionsDocumentsSuggest'];
5
+ type Browse = components['schemas']['GetApiV1CollectionsDocumentsBrowse'];
6
+ type Highlights = components['schemas']['GetApiV1CollectionsDocumentsHighlights'];
7
+ type Recommendations = components['schemas']['GetApiV1CollectionsDocumentsRecommendations'];
8
+ type SelectFacet = Extract<Browse['facet_counts'][number], {
9
+ type: 'select';
10
+ }>;
11
+ type RangeFacet = Extract<Browse['facet_counts'][number], {
12
+ type: 'range';
13
+ }>;
14
+ interface Filter {
15
+ field: string;
16
+ values: string[] | {
17
+ min?: string;
18
+ max?: string;
19
+ };
20
+ }
21
+ declare const buildBaseUrl: (collection: string) => string;
22
+ declare const buildHeaders: (apiKey: string) => {
23
+ 'X-BI-API-KEY': string;
24
+ };
25
+ declare function createClient<customPaths extends object = paths>(config: {
26
+ collection: string;
27
+ apiKey: string;
28
+ }): import("openapi-fetch").Client<customPaths, `${string}/${string}`>;
29
+ declare function defineCodegenConfig(config: Record<string, ProbeConfig | ProbeConfig[]>): Record<string, ProbeConfig | ProbeConfig[]>;
30
+ export { type Browse, type Filter, type Highlights, type RangeFacet, type Recommendations, type SelectFacet, type Suggest, buildBaseUrl, buildHeaders, type components, createClient, defineCodegenConfig, type paths };
package/dist/index.mjs ADDED
@@ -0,0 +1,5 @@
1
+ import { buildBaseUrl, buildHeaders, createClient } from "./_chunks/client.mjs";
2
+ function defineCodegenConfig(config) {
3
+ return config;
4
+ }
5
+ export { buildBaseUrl, buildHeaders, createClient, defineCodegenConfig };
package/package.json ADDED
@@ -0,0 +1,42 @@
1
+ {
2
+ "name": "batteryincluded",
3
+ "type": "module",
4
+ "version": "1.0.0",
5
+ "description": "A TypeScript client for the BatteryIncluded API",
6
+ "author": "Frederik Bußmann <frederik@bussmann.io>",
7
+ "license": "MIT",
8
+ "repository": "freb97/batteryincluded",
9
+ "exports": {
10
+ ".": "./dist/index.mjs"
11
+ },
12
+ "types": "./dist/index.d.mts",
13
+ "bin": {
14
+ "batteryincluded": "dist/cli/index.mjs"
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "obuild",
21
+ "lint": "eslint .",
22
+ "lint:fix": "eslint . --fix",
23
+ "prepack": "bun run build",
24
+ "release": "bun test && npm publish && git push --follow-tags",
25
+ "typecheck": "tsc --noEmit"
26
+ },
27
+ "dependencies": {
28
+ "autodisco": "^2.0.5",
29
+ "c12": "^4.0.0-beta.5",
30
+ "citty": "^0.2.2",
31
+ "defu": "^6.1.7",
32
+ "dotenv": "^17.4.2",
33
+ "openapi-fetch": "^0.17.0"
34
+ },
35
+ "devDependencies": {
36
+ "@antfu/eslint-config": "^9.0.0",
37
+ "@types/node": "^24",
38
+ "eslint": "^10.4.1",
39
+ "obuild": "^0.4.34",
40
+ "typescript": "^6.0.3"
41
+ }
42
+ }