@o-lang/bank-account-lookup 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/README.md +83 -0
- package/bin/init-bank-db.js +107 -0
- package/index.js +54 -0
- package/package.json +27 -0
package/README.md
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# @o-lang/bank-account-lookup
|
|
2
|
+
|
|
3
|
+
[](https://github.com/olang/olang)
|
|
4
|
+
|
|
5
|
+
Secure, read-only O-Lang resolver for bank account balance lookups using SQLite.
|
|
6
|
+
|
|
7
|
+
## π Security Features
|
|
8
|
+
|
|
9
|
+
- **Read-only database access** - no mutations possible
|
|
10
|
+
- **Parameterized queries** - SQL injection protected
|
|
11
|
+
- **Sanitized output** - only returns balance (no PII)
|
|
12
|
+
- **Explicit initialization** - no hidden side effects
|
|
13
|
+
|
|
14
|
+
## π₯ Installation
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
npm install @0-lang/bank-account-lookup
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
# Initialize the database π CRITICAL STEP
|
|
22
|
+
|
|
23
|
+
npx init-bank-db ./bank.db
|
|
24
|
+
|
|
25
|
+
This creates a SQLite database with sample customer
|
|
26
|
+
|
|
27
|
+
Customer 12345: $1,500
|
|
28
|
+
Customer 67890: $250
|
|
29
|
+
|
|
30
|
+
3. Use in your O-Lang workflow
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
Allow resolvers:
|
|
34
|
+
- bank-account-lookup
|
|
35
|
+
|
|
36
|
+
Step 1: Action bank-account-lookup "{customer_id}" Save as account_info
|
|
37
|
+
|
|
38
|
+
---
|
|
39
|
+
|
|
40
|
+
### π **Why This Placement Works**
|
|
41
|
+
|
|
42
|
+
1. **Early visibility** β Users see it in the first 5 seconds
|
|
43
|
+
2. **Numbered steps** β Clear progression (Install β Initialize β Use)
|
|
44
|
+
3. **Highlighted as critical** β Prevents the #1 user mistake (forgetting to initialize)
|
|
45
|
+
4. **Shows output** β Users know what to expect
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### β οΈ **What Happens If You Donβt Include It**
|
|
50
|
+
|
|
51
|
+
Users will:
|
|
52
|
+
1. Install your resolver β
|
|
53
|
+
2. Try to run their workflow β
|
|
54
|
+
3. Get this confusing error:
|
|
55
|
+
|
|
56
|
+
Error: bank-account-lookup requires "bank_db_path" in context or BANK_DB_PATH environment variable
|
|
57
|
+
|
|
58
|
+
4. **Give up** or open a GitHub issue
|
|
59
|
+
|
|
60
|
+
By including the `npx init-bank-db` command prominently, you **prevent 90% of support requests**.
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
### π‘ **Pro Tips for README**
|
|
65
|
+
|
|
66
|
+
1. **Use emojis** β π οΈ `npx init-bank-db ./bank.db`
|
|
67
|
+
2. **Show full workflow**:
|
|
68
|
+
|
|
69
|
+
# Complete example
|
|
70
|
+
npm install @o-lang/bank-account-lookup
|
|
71
|
+
npx init-bank-db ./bank.db
|
|
72
|
+
npx olang run bank-demo.ol -i customer_id=12345 -i bank_db_path=./bank.db -r @o-lang/bank-account-lookup
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
## β Troubleshooting
|
|
76
|
+
|
|
77
|
+
**"Command not found: init-bank-db"**
|
|
78
|
+
β Make sure you ran `npm install` first
|
|
79
|
+
|
|
80
|
+
**"Database file not found"**
|
|
81
|
+
β Run `npx init-bank-db ./bank.db` to create it
|
|
82
|
+
|
|
83
|
+
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* Initialize Bank Database
|
|
4
|
+
*
|
|
5
|
+
* Usage: npx init-bank-db [path/to/database.db]
|
|
6
|
+
*
|
|
7
|
+
* Creates a SQLite database with sample customer balances
|
|
8
|
+
* for O-Lang bank-account-lookup resolver.
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
const Database = require('better-sqlite3');
|
|
12
|
+
const fs = require('fs');
|
|
13
|
+
const path = require('path');
|
|
14
|
+
|
|
15
|
+
function showUsage() {
|
|
16
|
+
console.log(`
|
|
17
|
+
Usage: npx init-bank-db [database-path]
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
npx init-bank-db ./bank.db # Create in current directory
|
|
21
|
+
npx init-bank-db /data/bank.db # Create in specific path
|
|
22
|
+
|
|
23
|
+
Creates a SQLite database with sample customer data:
|
|
24
|
+
- Customer 12342: $1,500
|
|
25
|
+
- Customer 67890: $250
|
|
26
|
+
- Customer 11111: $0
|
|
27
|
+
- Customer 99999: $5,000
|
|
28
|
+
`);
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
function main() {
|
|
32
|
+
const args = process.argv.slice(2);
|
|
33
|
+
|
|
34
|
+
// Show help if requested
|
|
35
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
36
|
+
showUsage();
|
|
37
|
+
process.exit(0);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// Get database path (default to ./bank.db)
|
|
41
|
+
const dbPath = args[0] || './bank.db';
|
|
42
|
+
const resolvedPath = path.resolve(dbPath);
|
|
43
|
+
const dbDir = path.dirname(resolvedPath);
|
|
44
|
+
|
|
45
|
+
console.log(`π§ Initializing bank database at: ${resolvedPath}`);
|
|
46
|
+
|
|
47
|
+
// Create directory if it doesn't exist
|
|
48
|
+
if (!fs.existsSync(dbDir)) {
|
|
49
|
+
console.log(`π Creating directory: ${dbDir}`);
|
|
50
|
+
fs.mkdirSync(dbDir, { recursive: true });
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Initialize database
|
|
54
|
+
let db;
|
|
55
|
+
try {
|
|
56
|
+
db = new Database(resolvedPath);
|
|
57
|
+
|
|
58
|
+
// Create table if not exists
|
|
59
|
+
db.exec(`
|
|
60
|
+
CREATE TABLE IF NOT EXISTS customer_balances (
|
|
61
|
+
id TEXT PRIMARY KEY,
|
|
62
|
+
balance INTEGER NOT NULL DEFAULT 0,
|
|
63
|
+
status TEXT NOT NULL DEFAULT 'active',
|
|
64
|
+
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
|
|
65
|
+
)
|
|
66
|
+
`);
|
|
67
|
+
|
|
68
|
+
// Check if table has data
|
|
69
|
+
const count = db.prepare('SELECT COUNT(*) as cnt FROM customer_balances').get();
|
|
70
|
+
|
|
71
|
+
if (count.cnt === 0) {
|
|
72
|
+
console.log('π Inserting sample customer data...');
|
|
73
|
+
const insert = db.prepare('INSERT INTO customer_balances (id, balance, status) VALUES (?, ?, ?)');
|
|
74
|
+
|
|
75
|
+
// Insert sample data
|
|
76
|
+
const sampleData = [
|
|
77
|
+
['12345', 1500, 'active'],
|
|
78
|
+
['67890', 250, 'active'],
|
|
79
|
+
['11111', 0, 'active'],
|
|
80
|
+
['99999', 5000, 'active']
|
|
81
|
+
];
|
|
82
|
+
|
|
83
|
+
for (const [id, balance, status] of sampleData) {
|
|
84
|
+
insert.run(id, balance, status);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
console.log('β
Sample data inserted successfully');
|
|
88
|
+
} else {
|
|
89
|
+
console.log(`βΉοΈ Database already contains ${count.cnt} records - skipping sample data`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
db.close();
|
|
93
|
+
console.log(`β
Bank database ready! Use with O-Lang:\n`);
|
|
94
|
+
console.log(` npx olang run workflow.ol -i customer_id=12345 -i bank_db_path=${resolvedPath} -r @yourname/bank-account-lookup`);
|
|
95
|
+
|
|
96
|
+
} catch (error) {
|
|
97
|
+
console.error('β Failed to initialize database:', error.message);
|
|
98
|
+
process.exit(1);
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Run if called directly
|
|
103
|
+
if (require.main === module) {
|
|
104
|
+
main();
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
module.exports = main; // Export for programmatic use
|
package/index.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
// O-Lang Resolver: Secure Bank Account Balance Lookup
|
|
2
|
+
// This resolver ONLY reads data - no mutations allowed
|
|
3
|
+
|
|
4
|
+
const Database = require('better-sqlite3');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Bank account balance lookup resolver
|
|
8
|
+
* @param {string} action - O-Lang action string
|
|
9
|
+
* @param {Object} context - Workflow context containing customer_id and bank_db_path
|
|
10
|
+
* @returns {Object|undefined} { balance: number } or undefined if not applicable
|
|
11
|
+
*/
|
|
12
|
+
module.exports = async (action, context) => {
|
|
13
|
+
// Only handle our specific action
|
|
14
|
+
if (!action.startsWith('Action bank-account-lookup ')) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
// Require database path (from context or env var)
|
|
19
|
+
const dbPath = context.bank_db_path || process.env.BANK_DB_PATH;
|
|
20
|
+
if (!dbPath) {
|
|
21
|
+
throw new Error('bank-account-lookup requires "bank_db_path" in context or BANK_DB_PATH environment variable');
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Validate customer ID
|
|
25
|
+
const customerId = context.customer_id;
|
|
26
|
+
if (!customerId || typeof customerId !== 'string') {
|
|
27
|
+
return { balance: 0 };
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
try {
|
|
31
|
+
// β
Open database in READ-ONLY mode (security critical)
|
|
32
|
+
const db = new Database(dbPath, { readonly: true });
|
|
33
|
+
|
|
34
|
+
// β
Parameterized query (SQL injection safe)
|
|
35
|
+
const stmt = db.prepare(`
|
|
36
|
+
SELECT balance
|
|
37
|
+
FROM customer_balances
|
|
38
|
+
WHERE id = ? AND status = 'active'
|
|
39
|
+
`);
|
|
40
|
+
|
|
41
|
+
const result = stmt.get(customerId);
|
|
42
|
+
db.close(); // β
Close immediately after query
|
|
43
|
+
|
|
44
|
+
return { balance: result?.balance || 0 };
|
|
45
|
+
|
|
46
|
+
} catch (error) {
|
|
47
|
+
// β
Never expose database errors to LLM/workflow
|
|
48
|
+
console.error('π¦ [bank-account-lookup] Database error:', error.message);
|
|
49
|
+
return { balance: 0 };
|
|
50
|
+
}
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// β
Required for O-Lang allowlist policy
|
|
54
|
+
module.exports.resolverName = 'bank-account-lookup';
|
package/package.json
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@o-lang/bank-account-lookup",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "O-Lang resolver for secure bank balance lookups",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"init-bank-db": "./bin/init-bank-db.js"
|
|
8
|
+
},
|
|
9
|
+
"type": "commonjs",
|
|
10
|
+
"keywords": ["olang", "resolver", "bank", "sqlite", "security", "read-only"],
|
|
11
|
+
"author": "Your Name <your.email@example.com>",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"repository": {
|
|
14
|
+
"type": "git",
|
|
15
|
+
"url": "https://github.com/o-lang/bank-account-lookup.git"
|
|
16
|
+
},
|
|
17
|
+
"homepage": "https://github.com/o-lang/bank-account-lookup#readme",
|
|
18
|
+
"bugs": {
|
|
19
|
+
"url": "https://github.com/o-lang/bank-account-lookup/issues"
|
|
20
|
+
},
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"better-sqlite3": "^9.0.0"
|
|
23
|
+
},
|
|
24
|
+
"engines": {
|
|
25
|
+
"node": ">=18.0.0"
|
|
26
|
+
}
|
|
27
|
+
}
|