@opencard-dev/core 0.1.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/dist/db.d.ts +145 -0
- package/dist/db.d.ts.map +1 -0
- package/dist/db.js +373 -0
- package/dist/db.js.map +1 -0
- package/dist/errors.d.ts +72 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +124 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +67 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +53 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js +109 -0
- package/dist/logger.js.map +1 -0
- package/dist/rules-engine.d.ts +159 -0
- package/dist/rules-engine.d.ts.map +1 -0
- package/dist/rules-engine.js +375 -0
- package/dist/rules-engine.js.map +1 -0
- package/dist/rules-store.d.ts +187 -0
- package/dist/rules-store.d.ts.map +1 -0
- package/dist/rules-store.js +291 -0
- package/dist/rules-store.js.map +1 -0
- package/dist/rules-validation.d.ts +54 -0
- package/dist/rules-validation.d.ts.map +1 -0
- package/dist/rules-validation.js +110 -0
- package/dist/rules-validation.js.map +1 -0
- package/dist/stripe-client.d.ts +154 -0
- package/dist/stripe-client.d.ts.map +1 -0
- package/dist/stripe-client.js +444 -0
- package/dist/stripe-client.js.map +1 -0
- package/dist/test-utils.d.ts +55 -0
- package/dist/test-utils.d.ts.map +1 -0
- package/dist/test-utils.js +91 -0
- package/dist/test-utils.js.map +1 -0
- package/dist/tracker.d.ts +130 -0
- package/dist/tracker.d.ts.map +1 -0
- package/dist/tracker.js +196 -0
- package/dist/tracker.js.map +1 -0
- package/dist/transaction-reconciler.d.ts +30 -0
- package/dist/transaction-reconciler.d.ts.map +1 -0
- package/dist/transaction-reconciler.js +131 -0
- package/dist/transaction-reconciler.js.map +1 -0
- package/dist/types.d.ts +194 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/dist/webhooks.d.ts +121 -0
- package/dist/webhooks.d.ts.map +1 -0
- package/dist/webhooks.js +307 -0
- package/dist/webhooks.js.map +1 -0
- package/package.json +46 -0
package/dist/db.d.ts
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCard SQLite Database
|
|
3
|
+
*
|
|
4
|
+
* ─── Instance-per-call pattern (intentional) ─────────────────────────────────
|
|
5
|
+
*
|
|
6
|
+
* Callers create a new OpenCardDatabase() per operation rather than sharing
|
|
7
|
+
* a singleton. This was a deliberate choice for launch:
|
|
8
|
+
*
|
|
9
|
+
* Why: Each handler is self-contained — opens DB, does work, closes it.
|
|
10
|
+
* No shared state, no initialization ordering bugs, no "who closed the
|
|
11
|
+
* connection" surprises. Easy to test, easy to reason about.
|
|
12
|
+
*
|
|
13
|
+
* Cost: ~5ms overhead per call (file handle + pragma setup). Negligible
|
|
14
|
+
* at current call volumes (a few per minute). SQLite handles multiple
|
|
15
|
+
* connections to the same file natively via WAL mode — no corruption
|
|
16
|
+
* risk, no lock contention at this scale.
|
|
17
|
+
*
|
|
18
|
+
* Future: If profiling shows this matters (it won't for a while),
|
|
19
|
+
* switch to dependency injection — initialize once at server startup,
|
|
20
|
+
* pass the instance into handlers. Same pattern the webhook server
|
|
21
|
+
* already uses for TransactionReconciler.
|
|
22
|
+
*
|
|
23
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
24
|
+
*/
|
|
25
|
+
import Database from 'better-sqlite3';
|
|
26
|
+
export interface ApprovalRequest {
|
|
27
|
+
id: string;
|
|
28
|
+
card_id: string;
|
|
29
|
+
amount: number;
|
|
30
|
+
currency: string;
|
|
31
|
+
merchant_name: string;
|
|
32
|
+
merchant_category: string | null;
|
|
33
|
+
reason: string;
|
|
34
|
+
status: string;
|
|
35
|
+
decided_by: string | null;
|
|
36
|
+
decided_at: string | null;
|
|
37
|
+
decision_note: string | null;
|
|
38
|
+
created_at: string;
|
|
39
|
+
expires_at: string;
|
|
40
|
+
}
|
|
41
|
+
export interface StoredTransaction {
|
|
42
|
+
id: string;
|
|
43
|
+
stripe_id: string;
|
|
44
|
+
card_id: string;
|
|
45
|
+
amount: number;
|
|
46
|
+
currency: string;
|
|
47
|
+
merchant_name: string | null;
|
|
48
|
+
merchant_category: string | null;
|
|
49
|
+
status: string;
|
|
50
|
+
stripe_created_at: string | null;
|
|
51
|
+
recorded_at: string;
|
|
52
|
+
}
|
|
53
|
+
export interface StoredAuthorization {
|
|
54
|
+
id: string;
|
|
55
|
+
stripe_id: string;
|
|
56
|
+
card_id: string;
|
|
57
|
+
amount: number;
|
|
58
|
+
currency: string;
|
|
59
|
+
merchant_name: string | null;
|
|
60
|
+
merchant_category: string | null;
|
|
61
|
+
status: string;
|
|
62
|
+
decision_reason: string | null;
|
|
63
|
+
created_at: string;
|
|
64
|
+
updated_at: string;
|
|
65
|
+
}
|
|
66
|
+
export interface RuleVersion {
|
|
67
|
+
id: number;
|
|
68
|
+
rule_id: string;
|
|
69
|
+
version: number;
|
|
70
|
+
config: string;
|
|
71
|
+
changed_by: string | null;
|
|
72
|
+
changed_at: string;
|
|
73
|
+
change_type: string;
|
|
74
|
+
}
|
|
75
|
+
export interface StoredRule {
|
|
76
|
+
id: string;
|
|
77
|
+
card_id: string | null;
|
|
78
|
+
name: string | null;
|
|
79
|
+
config: string;
|
|
80
|
+
enabled: number;
|
|
81
|
+
created_at: string;
|
|
82
|
+
updated_at: string;
|
|
83
|
+
}
|
|
84
|
+
export interface StoredCard {
|
|
85
|
+
id: string;
|
|
86
|
+
stripe_id: string;
|
|
87
|
+
status: string;
|
|
88
|
+
created_at: string;
|
|
89
|
+
}
|
|
90
|
+
export interface StoredCardholder {
|
|
91
|
+
id: string;
|
|
92
|
+
name: string;
|
|
93
|
+
email: string;
|
|
94
|
+
created_at: string;
|
|
95
|
+
}
|
|
96
|
+
export declare class OpenCardDatabase {
|
|
97
|
+
private readonly dbPath;
|
|
98
|
+
private db;
|
|
99
|
+
constructor(dbPath?: string);
|
|
100
|
+
private initialize;
|
|
101
|
+
private runMigrations;
|
|
102
|
+
getDb(): Database.Database;
|
|
103
|
+
close(): void;
|
|
104
|
+
createTransaction(record: Omit<StoredTransaction, 'id' | 'recorded_at'>): StoredTransaction;
|
|
105
|
+
getTransaction(id: string): StoredTransaction | null;
|
|
106
|
+
getTransactionsForCard(cardId: string, limit?: number): StoredTransaction[];
|
|
107
|
+
createAuthorization(record: Omit<StoredAuthorization, 'id' | 'created_at' | 'updated_at'>): StoredAuthorization;
|
|
108
|
+
updateAuthorization(id: string, updates: Partial<Omit<StoredAuthorization, 'id' | 'stripe_id' | 'created_at'>>): StoredAuthorization;
|
|
109
|
+
getAuthorization(id: string): StoredAuthorization | null;
|
|
110
|
+
getAuthorizationByStripeId(stripeId: string): StoredAuthorization | null;
|
|
111
|
+
getPendingAuthorizationsOlderThan(cardId: string, hours: number): StoredAuthorization[];
|
|
112
|
+
createRuleVersion(ruleId: string, config: string, changeType: string, changedBy?: string): RuleVersion;
|
|
113
|
+
getRuleHistory(ruleId: string): RuleVersion[];
|
|
114
|
+
getRuleAtVersion(ruleId: string, version: number): RuleVersion | null;
|
|
115
|
+
saveRule(id: string, cardId: string | null, name: string | null, config: string): void;
|
|
116
|
+
getRule(id: string): {
|
|
117
|
+
id: string;
|
|
118
|
+
config: string;
|
|
119
|
+
} | null;
|
|
120
|
+
deleteRule(id: string): void;
|
|
121
|
+
createApprovalRequest(record: {
|
|
122
|
+
card_id: string;
|
|
123
|
+
amount: number;
|
|
124
|
+
currency?: string;
|
|
125
|
+
merchant_name: string;
|
|
126
|
+
merchant_category?: string | null;
|
|
127
|
+
reason: string;
|
|
128
|
+
timeout_seconds?: number;
|
|
129
|
+
}): ApprovalRequest;
|
|
130
|
+
getApprovalRequest(id: string): ApprovalRequest | null;
|
|
131
|
+
listPendingApprovalRequests(): ApprovalRequest[];
|
|
132
|
+
listAllApprovalRequests(limit?: number): ApprovalRequest[];
|
|
133
|
+
approveRequest(id: string, decidedBy: string, note?: string): ApprovalRequest;
|
|
134
|
+
denyRequest(id: string, decidedBy: string, note?: string): ApprovalRequest;
|
|
135
|
+
expireStaleApprovalRequests(): number;
|
|
136
|
+
}
|
|
137
|
+
/**
|
|
138
|
+
* Initialize and return a new database instance.
|
|
139
|
+
* Call this at server startup to get a DB instance to inject into services.
|
|
140
|
+
* Prefer this over the module-level singleton to avoid import-time side effects.
|
|
141
|
+
*
|
|
142
|
+
* @param dbPath - Optional path override. Defaults to OPENCARD_DB_PATH env var or ~/.opencard/opencard.db
|
|
143
|
+
*/
|
|
144
|
+
export declare function initDatabase(dbPath?: string): OpenCardDatabase;
|
|
145
|
+
//# sourceMappingURL=db.d.ts.map
|
package/dist/db.d.ts.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.d.ts","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|
package/dist/db.js
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* OpenCard SQLite Database
|
|
4
|
+
*
|
|
5
|
+
* ─── Instance-per-call pattern (intentional) ─────────────────────────────────
|
|
6
|
+
*
|
|
7
|
+
* Callers create a new OpenCardDatabase() per operation rather than sharing
|
|
8
|
+
* a singleton. This was a deliberate choice for launch:
|
|
9
|
+
*
|
|
10
|
+
* Why: Each handler is self-contained — opens DB, does work, closes it.
|
|
11
|
+
* No shared state, no initialization ordering bugs, no "who closed the
|
|
12
|
+
* connection" surprises. Easy to test, easy to reason about.
|
|
13
|
+
*
|
|
14
|
+
* Cost: ~5ms overhead per call (file handle + pragma setup). Negligible
|
|
15
|
+
* at current call volumes (a few per minute). SQLite handles multiple
|
|
16
|
+
* connections to the same file natively via WAL mode — no corruption
|
|
17
|
+
* risk, no lock contention at this scale.
|
|
18
|
+
*
|
|
19
|
+
* Future: If profiling shows this matters (it won't for a while),
|
|
20
|
+
* switch to dependency injection — initialize once at server startup,
|
|
21
|
+
* pass the instance into handlers. Same pattern the webhook server
|
|
22
|
+
* already uses for TransactionReconciler.
|
|
23
|
+
*
|
|
24
|
+
* ─────────────────────────────────────────────────────────────────────────────
|
|
25
|
+
*/
|
|
26
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
27
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
28
|
+
};
|
|
29
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
30
|
+
exports.OpenCardDatabase = void 0;
|
|
31
|
+
exports.initDatabase = initDatabase;
|
|
32
|
+
const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
|
|
33
|
+
const fs_1 = __importDefault(require("fs"));
|
|
34
|
+
const path_1 = __importDefault(require("path"));
|
|
35
|
+
const os_1 = __importDefault(require("os"));
|
|
36
|
+
class OpenCardDatabase {
|
|
37
|
+
dbPath;
|
|
38
|
+
db = null;
|
|
39
|
+
constructor(dbPath) {
|
|
40
|
+
if (dbPath) {
|
|
41
|
+
this.dbPath = dbPath;
|
|
42
|
+
}
|
|
43
|
+
else if (process.env.OPENCARD_DB_PATH) {
|
|
44
|
+
this.dbPath = process.env.OPENCARD_DB_PATH;
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
const openCardDir = path_1.default.join(os_1.default.homedir(), '.opencard');
|
|
48
|
+
this.dbPath = path_1.default.join(openCardDir, 'opencard.db');
|
|
49
|
+
}
|
|
50
|
+
const dir = path_1.default.dirname(this.dbPath);
|
|
51
|
+
if (!fs_1.default.existsSync(dir)) {
|
|
52
|
+
fs_1.default.mkdirSync(dir, { recursive: true });
|
|
53
|
+
console.log(`[OpenCardDB] Created directory: ${dir}`);
|
|
54
|
+
}
|
|
55
|
+
this.initialize();
|
|
56
|
+
}
|
|
57
|
+
initialize() {
|
|
58
|
+
if (this.db)
|
|
59
|
+
return;
|
|
60
|
+
this.db = new better_sqlite3_1.default(this.dbPath);
|
|
61
|
+
this.db.pragma('journal_mode = WAL');
|
|
62
|
+
this.db.pragma('foreign_keys = ON');
|
|
63
|
+
console.log(`[OpenCardDB] Opened database: ${this.dbPath}`);
|
|
64
|
+
this.runMigrations();
|
|
65
|
+
}
|
|
66
|
+
runMigrations() {
|
|
67
|
+
if (!this.db) {
|
|
68
|
+
throw new Error('[OpenCardDB] Database not initialized');
|
|
69
|
+
}
|
|
70
|
+
const migrationsDir = path_1.default.join(__dirname, '..', 'migrations');
|
|
71
|
+
if (!fs_1.default.existsSync(migrationsDir)) {
|
|
72
|
+
console.warn(`[OpenCardDB] Migrations directory not found: ${migrationsDir}`);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
const files = fs_1.default.readdirSync(migrationsDir)
|
|
76
|
+
.filter(f => f.endsWith('.sql'))
|
|
77
|
+
.sort();
|
|
78
|
+
for (const file of files) {
|
|
79
|
+
const migrationName = file;
|
|
80
|
+
const migrationPath = path_1.default.join(migrationsDir, file);
|
|
81
|
+
const sql = fs_1.default.readFileSync(migrationPath, 'utf-8');
|
|
82
|
+
// Check if migrations table exists each iteration — the first migration creates it.
|
|
83
|
+
const migrationsTableExists = this.db
|
|
84
|
+
.prepare("SELECT 1 FROM sqlite_master WHERE type='table' AND name='migrations'")
|
|
85
|
+
.get();
|
|
86
|
+
if (migrationsTableExists) {
|
|
87
|
+
const alreadyApplied = this.db
|
|
88
|
+
.prepare('SELECT 1 FROM migrations WHERE name = ?')
|
|
89
|
+
.get(migrationName);
|
|
90
|
+
if (alreadyApplied) {
|
|
91
|
+
console.log(`[OpenCardDB] Already applied: ${migrationName}`);
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
try {
|
|
96
|
+
this.db.exec(sql);
|
|
97
|
+
this.db.prepare('INSERT INTO migrations (name) VALUES (?)').run(migrationName);
|
|
98
|
+
console.log(`[OpenCardDB] Applied migration: ${migrationName}`);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
throw new Error(`[OpenCardDB] Failed to apply migration ${migrationName}: ${error instanceof Error ? error.message : error}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
getDb() {
|
|
106
|
+
if (!this.db) {
|
|
107
|
+
throw new Error('[OpenCardDB] Database not initialized');
|
|
108
|
+
}
|
|
109
|
+
return this.db;
|
|
110
|
+
}
|
|
111
|
+
close() {
|
|
112
|
+
if (this.db) {
|
|
113
|
+
this.db.close();
|
|
114
|
+
this.db = null;
|
|
115
|
+
console.log(`[OpenCardDB] Closed database`);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
createTransaction(record) {
|
|
119
|
+
const db = this.getDb();
|
|
120
|
+
const id = `txn_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
121
|
+
const stmt = db.prepare(`
|
|
122
|
+
INSERT INTO transactions (
|
|
123
|
+
id, stripe_id, card_id, amount, currency,
|
|
124
|
+
merchant_name, merchant_category, status, stripe_created_at
|
|
125
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
126
|
+
`);
|
|
127
|
+
stmt.run(id, record.stripe_id, record.card_id, record.amount, record.currency, record.merchant_name, record.merchant_category, record.status, record.stripe_created_at);
|
|
128
|
+
const result = db
|
|
129
|
+
.prepare('SELECT * FROM transactions WHERE id = ?')
|
|
130
|
+
.get(id);
|
|
131
|
+
console.log(`[OpenCardDB] Created transaction: ${id}`);
|
|
132
|
+
return result;
|
|
133
|
+
}
|
|
134
|
+
getTransaction(id) {
|
|
135
|
+
const db = this.getDb();
|
|
136
|
+
return db
|
|
137
|
+
.prepare('SELECT * FROM transactions WHERE id = ?')
|
|
138
|
+
.get(id) || null;
|
|
139
|
+
}
|
|
140
|
+
getTransactionsForCard(cardId, limit = 100) {
|
|
141
|
+
const db = this.getDb();
|
|
142
|
+
return db
|
|
143
|
+
.prepare('SELECT * FROM transactions WHERE card_id = ? ORDER BY stripe_created_at DESC LIMIT ?')
|
|
144
|
+
.all(cardId, limit);
|
|
145
|
+
}
|
|
146
|
+
createAuthorization(record) {
|
|
147
|
+
const db = this.getDb();
|
|
148
|
+
const id = `auth_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
149
|
+
const stmt = db.prepare(`
|
|
150
|
+
INSERT INTO authorizations (
|
|
151
|
+
id, stripe_id, card_id, amount, currency,
|
|
152
|
+
merchant_name, merchant_category, status, decision_reason
|
|
153
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)
|
|
154
|
+
`);
|
|
155
|
+
stmt.run(id, record.stripe_id, record.card_id, record.amount, record.currency, record.merchant_name, record.merchant_category, record.status, record.decision_reason);
|
|
156
|
+
const result = db
|
|
157
|
+
.prepare('SELECT * FROM authorizations WHERE id = ?')
|
|
158
|
+
.get(id);
|
|
159
|
+
console.log(`[OpenCardDB] Created authorization: ${id}`);
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
updateAuthorization(id, updates) {
|
|
163
|
+
const db = this.getDb();
|
|
164
|
+
const existingAuth = db
|
|
165
|
+
.prepare('SELECT * FROM authorizations WHERE id = ?')
|
|
166
|
+
.get(id);
|
|
167
|
+
if (!existingAuth) {
|
|
168
|
+
throw new Error(`[OpenCardDB] Authorization ${id} not found`);
|
|
169
|
+
}
|
|
170
|
+
const updatedAuth = { ...existingAuth, ...updates };
|
|
171
|
+
const stmt = db.prepare(`
|
|
172
|
+
UPDATE authorizations
|
|
173
|
+
SET card_id = ?, amount = ?, currency = ?,
|
|
174
|
+
merchant_name = ?, merchant_category = ?, status = ?, decision_reason = ?,
|
|
175
|
+
updated_at = CURRENT_TIMESTAMP
|
|
176
|
+
WHERE id = ?
|
|
177
|
+
`);
|
|
178
|
+
stmt.run(updatedAuth.card_id, updatedAuth.amount, updatedAuth.currency, updatedAuth.merchant_name, updatedAuth.merchant_category, updatedAuth.status, updatedAuth.decision_reason, id);
|
|
179
|
+
const result = db
|
|
180
|
+
.prepare('SELECT * FROM authorizations WHERE id = ?')
|
|
181
|
+
.get(id);
|
|
182
|
+
console.log(`[OpenCardDB] Updated authorization: ${id}`);
|
|
183
|
+
return result;
|
|
184
|
+
}
|
|
185
|
+
getAuthorization(id) {
|
|
186
|
+
const db = this.getDb();
|
|
187
|
+
return db
|
|
188
|
+
.prepare('SELECT * FROM authorizations WHERE id = ?')
|
|
189
|
+
.get(id) || null;
|
|
190
|
+
}
|
|
191
|
+
getAuthorizationByStripeId(stripeId) {
|
|
192
|
+
const db = this.getDb();
|
|
193
|
+
return db
|
|
194
|
+
.prepare('SELECT * FROM authorizations WHERE stripe_id = ?')
|
|
195
|
+
.get(stripeId) || null;
|
|
196
|
+
}
|
|
197
|
+
getPendingAuthorizationsOlderThan(cardId, hours) {
|
|
198
|
+
const db = this.getDb();
|
|
199
|
+
// Use SQLite's datetime() to compute the cutoff relative to 'now' — this
|
|
200
|
+
// avoids timezone/format mismatches between JS ISO strings and SQLite's
|
|
201
|
+
// CURRENT_TIMESTAMP format ('YYYY-MM-DD HH:MM:SS' without timezone).
|
|
202
|
+
const cutoffExpr = `-${hours} hours`;
|
|
203
|
+
return db
|
|
204
|
+
.prepare("SELECT * FROM authorizations WHERE card_id = ? AND status = ? AND created_at < datetime('now', ?) ORDER BY created_at")
|
|
205
|
+
.all(cardId, 'pending', cutoffExpr);
|
|
206
|
+
}
|
|
207
|
+
createRuleVersion(ruleId, config, changeType, changedBy) {
|
|
208
|
+
const db = this.getDb();
|
|
209
|
+
const maxVersion = db
|
|
210
|
+
.prepare('SELECT MAX(version) as v FROM rule_versions WHERE rule_id = ?')
|
|
211
|
+
.get(ruleId);
|
|
212
|
+
const nextVersion = (maxVersion.v || 0) + 1;
|
|
213
|
+
const stmt = db.prepare(`
|
|
214
|
+
INSERT INTO rule_versions (rule_id, version, config, changed_by, change_type)
|
|
215
|
+
VALUES (?, ?, ?, ?, ?)
|
|
216
|
+
`);
|
|
217
|
+
stmt.run(ruleId, nextVersion, config, changedBy || null, changeType);
|
|
218
|
+
const result = db
|
|
219
|
+
.prepare('SELECT * FROM rule_versions WHERE rule_id = ? AND version = ?')
|
|
220
|
+
.get(ruleId, nextVersion);
|
|
221
|
+
console.log(`[OpenCardDB] Created rule version: ${ruleId} v${nextVersion} (${changeType})`);
|
|
222
|
+
return result;
|
|
223
|
+
}
|
|
224
|
+
getRuleHistory(ruleId) {
|
|
225
|
+
const db = this.getDb();
|
|
226
|
+
return db
|
|
227
|
+
.prepare('SELECT * FROM rule_versions WHERE rule_id = ? ORDER BY version ASC')
|
|
228
|
+
.all(ruleId);
|
|
229
|
+
}
|
|
230
|
+
getRuleAtVersion(ruleId, version) {
|
|
231
|
+
const db = this.getDb();
|
|
232
|
+
return db
|
|
233
|
+
.prepare('SELECT * FROM rule_versions WHERE rule_id = ? AND version = ?')
|
|
234
|
+
.get(ruleId, version) || null;
|
|
235
|
+
}
|
|
236
|
+
saveRule(id, cardId, name, config) {
|
|
237
|
+
const db = this.getDb();
|
|
238
|
+
const existing = db
|
|
239
|
+
.prepare('SELECT 1 FROM rules WHERE id = ?')
|
|
240
|
+
.get(id);
|
|
241
|
+
if (existing) {
|
|
242
|
+
const stmt = db.prepare(`
|
|
243
|
+
UPDATE rules
|
|
244
|
+
SET card_id = ?, name = ?, config = ?, updated_at = CURRENT_TIMESTAMP
|
|
245
|
+
WHERE id = ?
|
|
246
|
+
`);
|
|
247
|
+
stmt.run(cardId, name, config, id);
|
|
248
|
+
}
|
|
249
|
+
else {
|
|
250
|
+
const stmt = db.prepare(`
|
|
251
|
+
INSERT INTO rules (id, card_id, name, config)
|
|
252
|
+
VALUES (?, ?, ?, ?)
|
|
253
|
+
`);
|
|
254
|
+
stmt.run(id, cardId, name, config);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
getRule(id) {
|
|
258
|
+
const db = this.getDb();
|
|
259
|
+
return db
|
|
260
|
+
.prepare('SELECT id, config FROM rules WHERE id = ?')
|
|
261
|
+
.get(id) || null;
|
|
262
|
+
}
|
|
263
|
+
deleteRule(id) {
|
|
264
|
+
const db = this.getDb();
|
|
265
|
+
db.prepare('DELETE FROM rules WHERE id = ?').run(id);
|
|
266
|
+
console.log(`[OpenCardDB] Deleted rule: ${id}`);
|
|
267
|
+
}
|
|
268
|
+
// ─── Approval Requests ───────────────────────────────────────────────────
|
|
269
|
+
createApprovalRequest(record) {
|
|
270
|
+
const db = this.getDb();
|
|
271
|
+
const id = `apr_${Date.now()}_${Math.random().toString(36).substring(7)}`;
|
|
272
|
+
const timeoutSeconds = record.timeout_seconds ?? 300;
|
|
273
|
+
const expiresAt = new Date(Date.now() + timeoutSeconds * 1000)
|
|
274
|
+
.toISOString()
|
|
275
|
+
.replace('T', ' ')
|
|
276
|
+
.slice(0, 19);
|
|
277
|
+
const stmt = db.prepare(`
|
|
278
|
+
INSERT INTO approval_requests (
|
|
279
|
+
id, card_id, amount, currency, merchant_name, merchant_category,
|
|
280
|
+
reason, status, expires_at
|
|
281
|
+
) VALUES (?, ?, ?, ?, ?, ?, ?, 'pending', ?)
|
|
282
|
+
`);
|
|
283
|
+
stmt.run(id, record.card_id, record.amount, record.currency ?? 'usd', record.merchant_name, record.merchant_category ?? null, record.reason, expiresAt);
|
|
284
|
+
const result = db
|
|
285
|
+
.prepare('SELECT * FROM approval_requests WHERE id = ?')
|
|
286
|
+
.get(id);
|
|
287
|
+
console.log(`[OpenCardDB] Created approval request: ${id}`);
|
|
288
|
+
return result;
|
|
289
|
+
}
|
|
290
|
+
getApprovalRequest(id) {
|
|
291
|
+
const db = this.getDb();
|
|
292
|
+
return db
|
|
293
|
+
.prepare('SELECT * FROM approval_requests WHERE id = ?')
|
|
294
|
+
.get(id) || null;
|
|
295
|
+
}
|
|
296
|
+
listPendingApprovalRequests() {
|
|
297
|
+
const db = this.getDb();
|
|
298
|
+
return db
|
|
299
|
+
.prepare("SELECT * FROM approval_requests WHERE status = 'pending' ORDER BY created_at ASC")
|
|
300
|
+
.all();
|
|
301
|
+
}
|
|
302
|
+
listAllApprovalRequests(limit = 50) {
|
|
303
|
+
const db = this.getDb();
|
|
304
|
+
return db
|
|
305
|
+
.prepare('SELECT * FROM approval_requests ORDER BY created_at DESC LIMIT ?')
|
|
306
|
+
.all(limit);
|
|
307
|
+
}
|
|
308
|
+
approveRequest(id, decidedBy, note) {
|
|
309
|
+
const db = this.getDb();
|
|
310
|
+
const existing = db
|
|
311
|
+
.prepare('SELECT * FROM approval_requests WHERE id = ?')
|
|
312
|
+
.get(id);
|
|
313
|
+
if (!existing) {
|
|
314
|
+
throw new Error(`Approval request ${id} not found`);
|
|
315
|
+
}
|
|
316
|
+
if (existing.status !== 'pending') {
|
|
317
|
+
throw new Error(`Approval request ${id} is already ${existing.status}`);
|
|
318
|
+
}
|
|
319
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
320
|
+
db.prepare(`
|
|
321
|
+
UPDATE approval_requests
|
|
322
|
+
SET status = 'approved', decided_by = ?, decided_at = ?, decision_note = ?
|
|
323
|
+
WHERE id = ?
|
|
324
|
+
`).run(decidedBy, now, note ?? null, id);
|
|
325
|
+
console.log(`[OpenCardDB] Approved request: ${id} by ${decidedBy}`);
|
|
326
|
+
return db.prepare('SELECT * FROM approval_requests WHERE id = ?').get(id);
|
|
327
|
+
}
|
|
328
|
+
denyRequest(id, decidedBy, note) {
|
|
329
|
+
const db = this.getDb();
|
|
330
|
+
const existing = db
|
|
331
|
+
.prepare('SELECT * FROM approval_requests WHERE id = ?')
|
|
332
|
+
.get(id);
|
|
333
|
+
if (!existing) {
|
|
334
|
+
throw new Error(`Approval request ${id} not found`);
|
|
335
|
+
}
|
|
336
|
+
if (existing.status !== 'pending') {
|
|
337
|
+
throw new Error(`Approval request ${id} is already ${existing.status}`);
|
|
338
|
+
}
|
|
339
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
340
|
+
db.prepare(`
|
|
341
|
+
UPDATE approval_requests
|
|
342
|
+
SET status = 'denied', decided_by = ?, decided_at = ?, decision_note = ?
|
|
343
|
+
WHERE id = ?
|
|
344
|
+
`).run(decidedBy, now, note ?? null, id);
|
|
345
|
+
console.log(`[OpenCardDB] Denied request: ${id} by ${decidedBy}`);
|
|
346
|
+
return db.prepare('SELECT * FROM approval_requests WHERE id = ?').get(id);
|
|
347
|
+
}
|
|
348
|
+
expireStaleApprovalRequests() {
|
|
349
|
+
const db = this.getDb();
|
|
350
|
+
const now = new Date().toISOString().replace('T', ' ').slice(0, 19);
|
|
351
|
+
const result = db.prepare(`
|
|
352
|
+
UPDATE approval_requests
|
|
353
|
+
SET status = 'expired'
|
|
354
|
+
WHERE status = 'pending' AND expires_at <= ?
|
|
355
|
+
`).run(now);
|
|
356
|
+
if (result.changes > 0) {
|
|
357
|
+
console.log(`[OpenCardDB] Expired ${result.changes} stale approval request(s)`);
|
|
358
|
+
}
|
|
359
|
+
return result.changes;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
exports.OpenCardDatabase = OpenCardDatabase;
|
|
363
|
+
/**
|
|
364
|
+
* Initialize and return a new database instance.
|
|
365
|
+
* Call this at server startup to get a DB instance to inject into services.
|
|
366
|
+
* Prefer this over the module-level singleton to avoid import-time side effects.
|
|
367
|
+
*
|
|
368
|
+
* @param dbPath - Optional path override. Defaults to OPENCARD_DB_PATH env var or ~/.opencard/opencard.db
|
|
369
|
+
*/
|
|
370
|
+
function initDatabase(dbPath) {
|
|
371
|
+
return new OpenCardDatabase(dbPath);
|
|
372
|
+
}
|
|
373
|
+
//# sourceMappingURL=db.js.map
|
package/dist/db.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"db.js","sourceRoot":"","sources":["../src/db.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OpenCard Error Classes
|
|
3
|
+
* ======================
|
|
4
|
+
* Custom error types for OpenCard, designed to wrap Stripe errors while
|
|
5
|
+
* preserving the original error code, message, and type.
|
|
6
|
+
*
|
|
7
|
+
* This allows callers to recover from specific errors (e.g., retry on
|
|
8
|
+
* rate limits, handle authorization failures differently) rather than
|
|
9
|
+
* treating all errors as opaque strings.
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Base class for all OpenCard errors.
|
|
13
|
+
* Extends Error and preserves the Stripe error context.
|
|
14
|
+
*/
|
|
15
|
+
export declare class OpenCardError extends Error {
|
|
16
|
+
/** Original error if this is wrapping a thrown error */
|
|
17
|
+
cause?: Error;
|
|
18
|
+
/** Context about what operation failed (stripe-client, rules-engine, etc.) */
|
|
19
|
+
component: string;
|
|
20
|
+
/** Stripe error code if available (e.g., 'rate_limit_error', 'authentication_error') */
|
|
21
|
+
stripeCode?: string;
|
|
22
|
+
/** Stripe error type if available (e.g., 'StripeInvalidRequestError') */
|
|
23
|
+
stripeType?: string;
|
|
24
|
+
/** Additional context (cardId, ruleId, etc.) */
|
|
25
|
+
context: Record<string, unknown>;
|
|
26
|
+
constructor(message: string, component: string, context?: Record<string, unknown>);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Wraps a Stripe error, preserving its type and code.
|
|
30
|
+
* Useful for error recovery based on the specific Stripe error.
|
|
31
|
+
*
|
|
32
|
+
* @param error - The original error (likely from a Stripe SDK call)
|
|
33
|
+
* @param message - User-friendly message describing what we were doing
|
|
34
|
+
* @param component - Component name (e.g., 'stripe-client')
|
|
35
|
+
* @param context - Additional context (cardId, etc.)
|
|
36
|
+
* @returns OpenCardError with Stripe error info preserved
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* try {
|
|
40
|
+
* await stripe.issuing.cards.create({ ... });
|
|
41
|
+
* } catch (err) {
|
|
42
|
+
* throw wrapStripeError(err, 'Failed to create card', 'stripe-client', { cardholderId });
|
|
43
|
+
* }
|
|
44
|
+
*/
|
|
45
|
+
export declare function wrapStripeError(error: unknown, message: string, component: string, context?: Record<string, unknown>): OpenCardError;
|
|
46
|
+
/**
|
|
47
|
+
* Specific error: Stripe authentication failed (invalid key, revoked key, etc.)
|
|
48
|
+
*/
|
|
49
|
+
export declare class StripeAuthenticationError extends OpenCardError {
|
|
50
|
+
constructor(message: string, context?: Record<string, unknown>);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Specific error: Rate limit exceeded — client should retry with backoff.
|
|
54
|
+
*/
|
|
55
|
+
export declare class RateLimitError extends OpenCardError {
|
|
56
|
+
/** Seconds to wait before retrying (from Stripe's Retry-After header) */
|
|
57
|
+
retryAfter?: number;
|
|
58
|
+
constructor(message: string, component: string, retryAfter?: number, context?: Record<string, unknown>);
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Specific error: Invalid parameters (e.g., missing required field, bad enum value)
|
|
62
|
+
*/
|
|
63
|
+
export declare class InvalidParameterError extends OpenCardError {
|
|
64
|
+
constructor(message: string, context?: Record<string, unknown>);
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Specific error: Rule not found or invalid in the rules store.
|
|
68
|
+
*/
|
|
69
|
+
export declare class RuleError extends OpenCardError {
|
|
70
|
+
constructor(message: string, context?: Record<string, unknown>);
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,qBAAa,aAAc,SAAQ,KAAK;IACtC,wDAAwD;IACxD,KAAK,CAAC,EAAE,KAAK,CAAC;IAEd,8EAA8E;IAC9E,SAAS,EAAE,MAAM,CAAC;IAElB,wFAAwF;IACxF,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,gDAAgD;IAChD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;gBAG/B,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CASxC;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,OAAO,EACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GACpC,aAAa,CAqBf;AAED;;GAEG;AACH,qBAAa,yBAA0B,SAAQ,aAAa;gBAC9C,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAKnE;AAED;;GAEG;AACH,qBAAa,cAAe,SAAQ,aAAa;IAC/C,yEAAyE;IACzE,UAAU,CAAC,EAAE,MAAM,CAAC;gBAGlB,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,UAAU,CAAC,EAAE,MAAM,EACnB,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAOxC;AAED;;GAEG;AACH,qBAAa,qBAAsB,SAAQ,aAAa;gBAC1C,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAKnE;AAED;;GAEG;AACH,qBAAa,SAAU,SAAQ,aAAa;gBAC9B,OAAO,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;CAKnE"}
|