Convert to TypeScript

- Renamed bring → bring.ts
- Added TypeScript interfaces for type safety
- Added tsconfig.json for TypeScript configuration
- Updated package.json with TypeScript dependencies
- Updated SKILL.md with TypeScript usage instructions
- Added dist/ to .gitignore

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Carson (Claude Assistant)
2026-03-08 22:38:30 +01:00
co-authored by Claude Sonnet 4.5
parent df53e2f1ed
commit 557280eb0e
5 changed files with 98 additions and 34 deletions
+2
View File
@@ -2,3 +2,5 @@ node_modules/
package-lock.json package-lock.json
*.log *.log
.env .env
dist/
*.tsbuildinfo
+26 -11
View File
@@ -2,11 +2,21 @@
Manage your Bring! Shopping List via CLI using the unofficial Bring! API. Manage your Bring! Shopping List via CLI using the unofficial Bring! API.
TypeScript implementation with full type safety.
## Installation ## Installation
```bash ```bash
npm install npm install
chmod +x bring chmod +x bring.ts
```
Or to build and run as JavaScript:
```bash
npm install
npm run build
node dist/bring.js
``` ```
## Configuration ## Configuration
@@ -63,28 +73,33 @@ console.log(lists.lists); // Shows all lists with their UUIDs
## Commands ## Commands
```bash ```bash
bring add <item> [specification] # Add item to shopping list ./bring.ts add <item> [specification] # Add item to shopping list
bring list # Show current items ./bring.ts list # Show current items
bring remove <item> # Remove item (mark as purchased) ./bring.ts remove <item> # Remove item (mark as purchased)
bring recent # Show recently purchased items ./bring.ts recent # Show recently purchased items
```
Or using ts-node directly:
```bash
ts-node bring.ts add <item>
``` ```
## Examples ## Examples
```bash ```bash
# Add items # Add items
bring add Apples ./bring.ts add Apples
bring add Milk "1 Liter" ./bring.ts add Milk "1 Liter"
bring add "Coffee Beans" "Fair Trade" ./bring.ts add "Coffee Beans" "Fair Trade"
# Show list # Show list
bring list ./bring.ts list
# Remove item (mark as bought) # Remove item (mark as bought)
bring remove Apples ./bring.ts remove Apples
# Show recently purchased items # Show recently purchased items
bring recent ./bring.ts recent
``` ```
## Integration with AI Agents ## Integration with AI Agents
+40 -22
View File
@@ -1,14 +1,31 @@
#!/usr/bin/env node #!/usr/bin/env ts-node
const bringApi = require('bring-shopping'); import BringApi from 'bring-shopping';
interface Credentials {
mail: string;
password: string;
}
interface BringItem {
name: string;
specification: string;
}
interface BringItems {
uuid: string;
status: string;
purchase: BringItem[];
recently: BringItem[];
}
// Load credentials from environment variables // Load credentials from environment variables
const CREDENTIALS = { const CREDENTIALS: Credentials = {
mail: process.env.BRING_EMAIL, mail: process.env.BRING_EMAIL || '',
password: process.env.BRING_PASSWORD password: process.env.BRING_PASSWORD || ''
}; };
const LIST_UUID = process.env.BRING_LIST_UUID; const LIST_UUID: string = process.env.BRING_LIST_UUID || '';
// Validate required environment variables // Validate required environment variables
if (!CREDENTIALS.mail || !CREDENTIALS.password || !LIST_UUID) { if (!CREDENTIALS.mail || !CREDENTIALS.password || !LIST_UUID) {
@@ -18,16 +35,16 @@ if (!CREDENTIALS.mail || !CREDENTIALS.password || !LIST_UUID) {
process.exit(1); process.exit(1);
} }
async function main() { async function main(): Promise<void> {
const args = process.argv.slice(2); const args: string[] = process.argv.slice(2);
const command = args[0]; const command: string | undefined = args[0];
if (!command) { if (!command) {
console.error('Usage: bring <add|list|remove|recent> [args...]'); console.error('Usage: bring <add|list|remove|recent> [args...]');
process.exit(1); process.exit(1);
} }
const bring = new bringApi(CREDENTIALS); const bring = new BringApi(CREDENTIALS);
try { try {
await bring.login(); await bring.login();
@@ -51,7 +68,8 @@ async function main() {
process.exit(1); process.exit(1);
} }
} catch (error) { } catch (error) {
console.error('Error:', error.message); const errorMessage = error instanceof Error ? error.message : 'Unknown error';
console.error('Error:', errorMessage);
process.exit(1); process.exit(1);
} }
} }
@@ -59,9 +77,9 @@ async function main() {
/** /**
* Add an item to the shopping list * Add an item to the shopping list
*/ */
async function addItem(bring, args) { async function addItem(bring: any, args: string[]): Promise<void> {
const itemName = args[0]; const itemName: string | undefined = args[0];
const specification = args.slice(1).join(' ') || ''; const specification: string = args.slice(1).join(' ') || '';
if (!itemName) { if (!itemName) {
console.error('Usage: bring add <item> [specification]'); console.error('Usage: bring add <item> [specification]');
@@ -80,8 +98,8 @@ async function addItem(bring, args) {
/** /**
* List all items currently on the shopping list * List all items currently on the shopping list
*/ */
async function listItems(bring) { async function listItems(bring: any): Promise<void> {
const items = await bring.getItems(LIST_UUID); const items: BringItems = await bring.getItems(LIST_UUID);
if (items.purchase.length === 0) { if (items.purchase.length === 0) {
console.log('Shopping list is empty'); console.log('Shopping list is empty');
@@ -90,7 +108,7 @@ async function listItems(bring) {
console.log('Shopping list:'); console.log('Shopping list:');
console.log(''); console.log('');
items.purchase.forEach((item, index) => { items.purchase.forEach((item: BringItem, index: number) => {
if (item.specification) { if (item.specification) {
console.log(`${index + 1}. ${item.name} (${item.specification})`); console.log(`${index + 1}. ${item.name} (${item.specification})`);
} else { } else {
@@ -102,8 +120,8 @@ async function listItems(bring) {
/** /**
* Remove an item from the shopping list (mark as purchased) * Remove an item from the shopping list (mark as purchased)
*/ */
async function removeItem(bring, args) { async function removeItem(bring: any, args: string[]): Promise<void> {
const itemName = args.join(' '); const itemName: string = args.join(' ');
if (!itemName) { if (!itemName) {
console.error('Usage: bring remove <item>'); console.error('Usage: bring remove <item>');
@@ -117,8 +135,8 @@ async function removeItem(bring, args) {
/** /**
* Show recently purchased items * Show recently purchased items
*/ */
async function recentItems(bring) { async function recentItems(bring: any): Promise<void> {
const items = await bring.getItems(LIST_UUID); const items: BringItems = await bring.getItems(LIST_UUID);
if (items.recently.length === 0) { if (items.recently.length === 0) {
console.log('No recently purchased items'); console.log('No recently purchased items');
@@ -127,7 +145,7 @@ async function recentItems(bring) {
console.log('Recently purchased:'); console.log('Recently purchased:');
console.log(''); console.log('');
items.recently.slice(0, 10).forEach((item, index) => { items.recently.slice(0, 10).forEach((item: BringItem, index: number) => {
if (item.specification) { if (item.specification) {
console.log(`${index + 1}. ${item.name} (${item.specification})`); console.log(`${index + 1}. ${item.name} (${item.specification})`);
} else { } else {
+11 -1
View File
@@ -1,8 +1,18 @@
{ {
"name": "bring-shopping-skill", "name": "bring-shopping-skill",
"version": "1.0.0", "version": "1.0.0",
"description": "Bring! Shopping List Skill for Carson", "description": "Bring! Shopping List Skill - TypeScript CLI",
"type": "module",
"scripts": {
"build": "tsc",
"start": "ts-node bring.ts"
},
"dependencies": { "dependencies": {
"bring-shopping": "^2.0.1" "bring-shopping": "^2.0.1"
},
"devDependencies": {
"@types/node": "^20.0.0",
"ts-node": "^10.9.0",
"typescript": "^5.0.0"
} }
} }
+19
View File
@@ -0,0 +1,19 @@
{
"compilerOptions": {
"target": "ES2020",
"module": "commonjs",
"lib": ["ES2020"],
"outDir": "./dist",
"rootDir": "./",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"declaration": true,
"declarationMap": true,
"sourceMap": true
},
"include": ["*.ts"],
"exclude": ["node_modules", "dist"]
}