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 +21 -0
- package/README.md +119 -0
- package/dist/_chunks/client.mjs +10 -0
- package/dist/cli/index.d.mts +1 -0
- package/dist/cli/index.mjs +105 -0
- package/dist/index.d.mts +30 -0
- package/dist/index.mjs +5 -0
- package/package.json +42 -0
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 {};
|
package/dist/index.d.mts
ADDED
|
@@ -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
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
|
+
}
|