@hasna/invoices 0.0.1
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 +190 -0
- package/README.md +125 -0
- package/dashboard/dist/assets/index-BhR1BMmj.js +139 -0
- package/dashboard/dist/assets/index-khzrvnCp.css +1 -0
- package/dashboard/dist/index.html +13 -0
- package/dashboard/dist/logo.jpg +0 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +2757 -0
- package/dist/cli/tui.d.ts +2 -0
- package/dist/cli/tui.d.ts.map +1 -0
- package/dist/db/agents.d.ts +19 -0
- package/dist/db/agents.d.ts.map +1 -0
- package/dist/db/core.test.d.ts +2 -0
- package/dist/db/core.test.d.ts.map +1 -0
- package/dist/db/database.d.ts +7 -0
- package/dist/db/database.d.ts.map +1 -0
- package/dist/db/invoices.d.ts +92 -0
- package/dist/db/invoices.d.ts.map +1 -0
- package/dist/db/migrate.d.ts +5 -0
- package/dist/db/migrate.d.ts.map +1 -0
- package/dist/db/schema.d.ts +6 -0
- package/dist/db/schema.d.ts.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +457 -0
- package/dist/lib/version.d.ts +2 -0
- package/dist/lib/version.d.ts.map +1 -0
- package/dist/mcp/index.d.ts +3 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +4675 -0
- package/dist/server/index.d.ts +3 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +4691 -0
- package/dist/types/index.d.ts +18 -0
- package/dist/types/index.d.ts.map +1 -0
- package/package.json +77 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tui.d.ts","sourceRoot":"","sources":["../../src/cli/tui.tsx"],"names":[],"mappings":"AA6CA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAGpD"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface AgentRecord {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
description?: string;
|
|
6
|
+
focus?: string;
|
|
7
|
+
createdAt: string;
|
|
8
|
+
lastSeenAt: string;
|
|
9
|
+
}
|
|
10
|
+
export declare function registerAgent(db: Database, input: {
|
|
11
|
+
name: string;
|
|
12
|
+
description?: string;
|
|
13
|
+
}): AgentRecord;
|
|
14
|
+
export declare function getAgentById(db: Database, id: string): AgentRecord | null;
|
|
15
|
+
export declare function getAgentByName(db: Database, name: string): AgentRecord | null;
|
|
16
|
+
export declare function heartbeatAgent(db: Database, agentId: string): AgentRecord | null;
|
|
17
|
+
export declare function setAgentFocus(db: Database, agentId: string, focus?: string): AgentRecord | null;
|
|
18
|
+
export declare function listAgents(db: Database): AgentRecord[];
|
|
19
|
+
//# sourceMappingURL=agents.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agents.d.ts","sourceRoot":"","sources":["../../src/db/agents.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;CACpB;AAaD,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,WAAW,CAatG;AAED,wBAAgB,YAAY,CAAC,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAGzE;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAG7E;AAED,wBAAgB,cAAc,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAGhF;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,IAAI,CAG/F;AAED,wBAAgB,UAAU,CAAC,EAAE,EAAE,QAAQ,GAAG,WAAW,EAAE,CAEtD"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"core.test.d.ts","sourceRoot":"","sources":["../../src/db/core.test.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { Database } from "bun:sqlite";
|
|
2
|
+
export interface InvoiceDatabaseOptions {
|
|
3
|
+
dbPath?: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function defaultDatabasePath(): string;
|
|
6
|
+
export declare function openInvoiceDatabase(options?: InvoiceDatabaseOptions): Database;
|
|
7
|
+
//# sourceMappingURL=database.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/db/database.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAEtC,MAAM,WAAW,sBAAsB;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,wBAAgB,mBAAmB,IAAI,MAAM,CAI5C;AAED,wBAAgB,mBAAmB,CAAC,OAAO,GAAE,sBAA2B,GAAG,QAAQ,CASlF"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
export interface PartyRecord {
|
|
3
|
+
id: string;
|
|
4
|
+
kind: "issuer" | "customer";
|
|
5
|
+
legalName: string;
|
|
6
|
+
email?: string;
|
|
7
|
+
taxId?: string;
|
|
8
|
+
country?: string;
|
|
9
|
+
address?: string;
|
|
10
|
+
createdAt: string;
|
|
11
|
+
updatedAt: string;
|
|
12
|
+
}
|
|
13
|
+
export interface NewPartyInput {
|
|
14
|
+
id?: string;
|
|
15
|
+
kind: "issuer" | "customer";
|
|
16
|
+
legalName: string;
|
|
17
|
+
email?: string;
|
|
18
|
+
taxId?: string;
|
|
19
|
+
country?: string;
|
|
20
|
+
address?: string;
|
|
21
|
+
}
|
|
22
|
+
export interface InvoiceLineRecord {
|
|
23
|
+
id: string;
|
|
24
|
+
invoiceId: string;
|
|
25
|
+
position: number;
|
|
26
|
+
description: string;
|
|
27
|
+
quantity: number;
|
|
28
|
+
unitPriceCents: number;
|
|
29
|
+
taxRateBasisPoints: number;
|
|
30
|
+
lineTotalCents: number;
|
|
31
|
+
createdAt: string;
|
|
32
|
+
}
|
|
33
|
+
export interface NewInvoiceLineInput {
|
|
34
|
+
id?: string;
|
|
35
|
+
description: string;
|
|
36
|
+
quantity: number;
|
|
37
|
+
unitPriceCents: number;
|
|
38
|
+
taxRateBasisPoints?: number;
|
|
39
|
+
}
|
|
40
|
+
export interface InvoiceRecord {
|
|
41
|
+
id: string;
|
|
42
|
+
number: string;
|
|
43
|
+
issuerId: string;
|
|
44
|
+
customerId: string;
|
|
45
|
+
status: "draft" | "sent" | "partially_paid" | "paid" | "void" | "overdue";
|
|
46
|
+
currency: string;
|
|
47
|
+
notes?: string;
|
|
48
|
+
issuedAt: string;
|
|
49
|
+
dueAt?: string;
|
|
50
|
+
subtotalCents: number;
|
|
51
|
+
taxCents: number;
|
|
52
|
+
totalCents: number;
|
|
53
|
+
createdAt: string;
|
|
54
|
+
updatedAt: string;
|
|
55
|
+
}
|
|
56
|
+
export interface InvoiceWithLines extends InvoiceRecord {
|
|
57
|
+
lines: InvoiceLineRecord[];
|
|
58
|
+
}
|
|
59
|
+
export interface NewInvoiceInput {
|
|
60
|
+
id?: string;
|
|
61
|
+
number: string;
|
|
62
|
+
issuerId: string;
|
|
63
|
+
customerId: string;
|
|
64
|
+
currency: string;
|
|
65
|
+
notes?: string;
|
|
66
|
+
issuedAt: string;
|
|
67
|
+
dueAt?: string;
|
|
68
|
+
lines: NewInvoiceLineInput[];
|
|
69
|
+
}
|
|
70
|
+
interface ListInvoicesOptions {
|
|
71
|
+
status?: InvoiceRecord["status"];
|
|
72
|
+
limit?: number;
|
|
73
|
+
offset?: number;
|
|
74
|
+
}
|
|
75
|
+
interface SearchInvoicesOptions {
|
|
76
|
+
status?: InvoiceRecord["status"];
|
|
77
|
+
limit?: number;
|
|
78
|
+
offset?: number;
|
|
79
|
+
}
|
|
80
|
+
export declare function createParty(db: Database, input: NewPartyInput): PartyRecord;
|
|
81
|
+
export declare function updateParty(db: Database, id: string, updates: Partial<Omit<NewPartyInput, "id" | "kind">>): PartyRecord | null;
|
|
82
|
+
export declare function getPartyById(db: Database, id: string): PartyRecord | null;
|
|
83
|
+
export declare function listParties(db: Database, kind?: PartyRecord["kind"]): PartyRecord[];
|
|
84
|
+
export declare function createInvoice(db: Database, input: NewInvoiceInput): InvoiceWithLines;
|
|
85
|
+
export declare function getInvoiceById(db: Database, id: string): InvoiceWithLines | null;
|
|
86
|
+
export declare function listInvoices(db: Database, options?: ListInvoicesOptions): InvoiceRecord[];
|
|
87
|
+
export declare function updateInvoiceStatus(db: Database, id: string, status: InvoiceRecord["status"]): InvoiceRecord | null;
|
|
88
|
+
export declare function deleteInvoice(db: Database, id: string): boolean;
|
|
89
|
+
export declare function rebuildInvoiceSearchIndex(db: Database): void;
|
|
90
|
+
export declare function searchInvoices(db: Database, query: string, options?: SearchInvoicesOptions): InvoiceRecord[];
|
|
91
|
+
export {};
|
|
92
|
+
//# sourceMappingURL=invoices.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invoices.d.ts","sourceRoot":"","sources":["../../src/db/invoices.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { Database } from "bun:sqlite";
|
|
2
|
+
import { type InvoiceDatabaseOptions } from "./database.js";
|
|
3
|
+
export declare function applyMigrations(db: Database): string[];
|
|
4
|
+
export declare function migrateDatabase(options?: InvoiceDatabaseOptions): string[];
|
|
5
|
+
//# sourceMappingURL=migrate.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"migrate.d.ts","sourceRoot":"","sources":["../../src/db/migrate.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,eAAe,CAAC;AAYjF,wBAAgB,eAAe,CAAC,EAAE,EAAE,QAAQ,GAAG,MAAM,EAAE,CAmBtD;AAED,wBAAgB,eAAe,CAAC,OAAO,GAAE,sBAA2B,GAAG,MAAM,EAAE,CAO9E"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/db/schema.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,SAAS;IACxB,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb;AAED,eAAO,MAAM,UAAU,EAAE,SAAS,EAkJjC,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,kBAAkB,CAAC;AACjC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,457 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
// src/lib/version.ts
|
|
3
|
+
var VERSION = "0.0.1";
|
|
4
|
+
// src/db/database.ts
|
|
5
|
+
import { mkdirSync } from "fs";
|
|
6
|
+
import { dirname, join } from "path";
|
|
7
|
+
import { Database } from "bun:sqlite";
|
|
8
|
+
function defaultDatabasePath() {
|
|
9
|
+
const baseDir = join(process.env.HOME ?? ".", ".hasna", "invoices");
|
|
10
|
+
mkdirSync(baseDir, { recursive: true });
|
|
11
|
+
return join(baseDir, "invoices.db");
|
|
12
|
+
}
|
|
13
|
+
function openInvoiceDatabase(options = {}) {
|
|
14
|
+
const dbPath = options.dbPath ?? defaultDatabasePath();
|
|
15
|
+
mkdirSync(dirname(dbPath), { recursive: true });
|
|
16
|
+
const db = new Database(dbPath, { create: true, strict: true });
|
|
17
|
+
db.exec("PRAGMA journal_mode = WAL;");
|
|
18
|
+
db.exec("PRAGMA foreign_keys = ON;");
|
|
19
|
+
db.exec("PRAGMA busy_timeout = 5000;");
|
|
20
|
+
return db;
|
|
21
|
+
}
|
|
22
|
+
// src/db/schema.ts
|
|
23
|
+
var MIGRATIONS = [
|
|
24
|
+
{
|
|
25
|
+
id: "0001_init",
|
|
26
|
+
sql: `
|
|
27
|
+
CREATE TABLE IF NOT EXISTS migrations (
|
|
28
|
+
id TEXT PRIMARY KEY,
|
|
29
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
CREATE TABLE IF NOT EXISTS parties (
|
|
33
|
+
id TEXT PRIMARY KEY,
|
|
34
|
+
kind TEXT NOT NULL CHECK(kind IN ('issuer', 'customer')),
|
|
35
|
+
legal_name TEXT NOT NULL,
|
|
36
|
+
email TEXT,
|
|
37
|
+
tax_id TEXT,
|
|
38
|
+
country TEXT,
|
|
39
|
+
address TEXT,
|
|
40
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
41
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
42
|
+
);
|
|
43
|
+
|
|
44
|
+
CREATE TABLE IF NOT EXISTS invoices (
|
|
45
|
+
id TEXT PRIMARY KEY,
|
|
46
|
+
number TEXT NOT NULL UNIQUE,
|
|
47
|
+
issuer_id TEXT NOT NULL REFERENCES parties(id),
|
|
48
|
+
customer_id TEXT NOT NULL REFERENCES parties(id),
|
|
49
|
+
status TEXT NOT NULL CHECK(status IN ('draft', 'sent', 'partially_paid', 'paid', 'void', 'overdue')),
|
|
50
|
+
currency TEXT NOT NULL,
|
|
51
|
+
notes TEXT,
|
|
52
|
+
issued_at TEXT NOT NULL,
|
|
53
|
+
due_at TEXT,
|
|
54
|
+
subtotal_cents INTEGER NOT NULL DEFAULT 0,
|
|
55
|
+
tax_cents INTEGER NOT NULL DEFAULT 0,
|
|
56
|
+
total_cents INTEGER NOT NULL DEFAULT 0,
|
|
57
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
58
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
CREATE TABLE IF NOT EXISTS invoice_lines (
|
|
62
|
+
id TEXT PRIMARY KEY,
|
|
63
|
+
invoice_id TEXT NOT NULL REFERENCES invoices(id) ON DELETE CASCADE,
|
|
64
|
+
position INTEGER NOT NULL,
|
|
65
|
+
description TEXT NOT NULL,
|
|
66
|
+
quantity REAL NOT NULL DEFAULT 1,
|
|
67
|
+
unit_price_cents INTEGER NOT NULL DEFAULT 0,
|
|
68
|
+
tax_rate_basis_points INTEGER NOT NULL DEFAULT 0,
|
|
69
|
+
line_total_cents INTEGER NOT NULL DEFAULT 0,
|
|
70
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
CREATE UNIQUE INDEX IF NOT EXISTS idx_invoice_lines_invoice_position
|
|
74
|
+
ON invoice_lines(invoice_id, position);
|
|
75
|
+
|
|
76
|
+
CREATE INDEX IF NOT EXISTS idx_invoices_number ON invoices(number);
|
|
77
|
+
CREATE INDEX IF NOT EXISTS idx_invoices_status ON invoices(status);
|
|
78
|
+
CREATE INDEX IF NOT EXISTS idx_invoices_issued_at ON invoices(issued_at);
|
|
79
|
+
CREATE INDEX IF NOT EXISTS idx_invoices_due_at ON invoices(due_at);
|
|
80
|
+
|
|
81
|
+
CREATE VIRTUAL TABLE IF NOT EXISTS invoices_fts USING fts5(
|
|
82
|
+
invoice_id UNINDEXED,
|
|
83
|
+
number,
|
|
84
|
+
issuer_name,
|
|
85
|
+
customer_name,
|
|
86
|
+
notes
|
|
87
|
+
);
|
|
88
|
+
|
|
89
|
+
CREATE TRIGGER IF NOT EXISTS invoices_ai_fts
|
|
90
|
+
AFTER INSERT ON invoices
|
|
91
|
+
BEGIN
|
|
92
|
+
INSERT INTO invoices_fts(invoice_id, number, issuer_name, customer_name, notes)
|
|
93
|
+
VALUES (
|
|
94
|
+
NEW.id,
|
|
95
|
+
NEW.number,
|
|
96
|
+
COALESCE((SELECT legal_name FROM parties WHERE id = NEW.issuer_id), ''),
|
|
97
|
+
COALESCE((SELECT legal_name FROM parties WHERE id = NEW.customer_id), ''),
|
|
98
|
+
COALESCE(NEW.notes, '')
|
|
99
|
+
);
|
|
100
|
+
END;
|
|
101
|
+
|
|
102
|
+
CREATE TRIGGER IF NOT EXISTS invoices_au_fts
|
|
103
|
+
AFTER UPDATE ON invoices
|
|
104
|
+
BEGIN
|
|
105
|
+
DELETE FROM invoices_fts WHERE invoice_id = OLD.id;
|
|
106
|
+
INSERT INTO invoices_fts(invoice_id, number, issuer_name, customer_name, notes)
|
|
107
|
+
VALUES (
|
|
108
|
+
NEW.id,
|
|
109
|
+
NEW.number,
|
|
110
|
+
COALESCE((SELECT legal_name FROM parties WHERE id = NEW.issuer_id), ''),
|
|
111
|
+
COALESCE((SELECT legal_name FROM parties WHERE id = NEW.customer_id), ''),
|
|
112
|
+
COALESCE(NEW.notes, '')
|
|
113
|
+
);
|
|
114
|
+
END;
|
|
115
|
+
|
|
116
|
+
CREATE TRIGGER IF NOT EXISTS invoices_ad_fts
|
|
117
|
+
AFTER DELETE ON invoices
|
|
118
|
+
BEGIN
|
|
119
|
+
DELETE FROM invoices_fts WHERE invoice_id = OLD.id;
|
|
120
|
+
END;
|
|
121
|
+
`
|
|
122
|
+
},
|
|
123
|
+
{
|
|
124
|
+
id: "0002_party_fts_sync",
|
|
125
|
+
sql: `
|
|
126
|
+
CREATE TRIGGER IF NOT EXISTS parties_au_invoice_fts
|
|
127
|
+
AFTER UPDATE ON parties
|
|
128
|
+
BEGIN
|
|
129
|
+
DELETE FROM invoices_fts
|
|
130
|
+
WHERE invoice_id IN (
|
|
131
|
+
SELECT id FROM invoices WHERE issuer_id = NEW.id OR customer_id = NEW.id
|
|
132
|
+
);
|
|
133
|
+
|
|
134
|
+
INSERT INTO invoices_fts(invoice_id, number, issuer_name, customer_name, notes)
|
|
135
|
+
SELECT
|
|
136
|
+
i.id,
|
|
137
|
+
i.number,
|
|
138
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.issuer_id), ''),
|
|
139
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.customer_id), ''),
|
|
140
|
+
COALESCE(i.notes, '')
|
|
141
|
+
FROM invoices i
|
|
142
|
+
WHERE i.issuer_id = NEW.id OR i.customer_id = NEW.id;
|
|
143
|
+
END;
|
|
144
|
+
|
|
145
|
+
INSERT INTO invoices_fts(invoice_id, number, issuer_name, customer_name, notes)
|
|
146
|
+
SELECT
|
|
147
|
+
i.id,
|
|
148
|
+
i.number,
|
|
149
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.issuer_id), ''),
|
|
150
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.customer_id), ''),
|
|
151
|
+
COALESCE(i.notes, '')
|
|
152
|
+
FROM invoices i
|
|
153
|
+
WHERE i.id NOT IN (SELECT invoice_id FROM invoices_fts);
|
|
154
|
+
`
|
|
155
|
+
},
|
|
156
|
+
{
|
|
157
|
+
id: "0003_agents",
|
|
158
|
+
sql: `
|
|
159
|
+
CREATE TABLE IF NOT EXISTS agents (
|
|
160
|
+
id TEXT PRIMARY KEY,
|
|
161
|
+
name TEXT NOT NULL UNIQUE,
|
|
162
|
+
description TEXT,
|
|
163
|
+
focus TEXT,
|
|
164
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
165
|
+
last_seen_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
166
|
+
);
|
|
167
|
+
`
|
|
168
|
+
}
|
|
169
|
+
];
|
|
170
|
+
|
|
171
|
+
// src/db/migrate.ts
|
|
172
|
+
function ensureMigrationsTable(db) {
|
|
173
|
+
db.exec(`
|
|
174
|
+
CREATE TABLE IF NOT EXISTS migrations (
|
|
175
|
+
id TEXT PRIMARY KEY,
|
|
176
|
+
applied_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
177
|
+
);
|
|
178
|
+
`);
|
|
179
|
+
}
|
|
180
|
+
function applyMigrations(db) {
|
|
181
|
+
ensureMigrationsTable(db);
|
|
182
|
+
const getMigration = db.query("SELECT id FROM migrations WHERE id = ?1");
|
|
183
|
+
const markMigration = db.query("INSERT INTO migrations (id) VALUES (?1)");
|
|
184
|
+
const applied = [];
|
|
185
|
+
for (const migration of MIGRATIONS) {
|
|
186
|
+
const row = getMigration.get(migration.id);
|
|
187
|
+
if (row) {
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
db.transaction(() => {
|
|
191
|
+
db.exec(migration.sql);
|
|
192
|
+
markMigration.run(migration.id);
|
|
193
|
+
})();
|
|
194
|
+
applied.push(migration.id);
|
|
195
|
+
}
|
|
196
|
+
return applied;
|
|
197
|
+
}
|
|
198
|
+
function migrateDatabase(options = {}) {
|
|
199
|
+
const db = openInvoiceDatabase(options);
|
|
200
|
+
try {
|
|
201
|
+
return applyMigrations(db);
|
|
202
|
+
} finally {
|
|
203
|
+
db.close();
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
// src/db/invoices.ts
|
|
207
|
+
import { randomUUID } from "crypto";
|
|
208
|
+
function toLineTotalCents(line) {
|
|
209
|
+
const subtotal = Math.round(line.quantity * line.unitPriceCents);
|
|
210
|
+
const taxRate = line.taxRateBasisPoints ?? 0;
|
|
211
|
+
const tax = Math.round(subtotal * taxRate / 1e4);
|
|
212
|
+
return { lineTotalCents: subtotal, lineTaxCents: tax };
|
|
213
|
+
}
|
|
214
|
+
function mapPartyRow(row) {
|
|
215
|
+
return {
|
|
216
|
+
id: row.id,
|
|
217
|
+
kind: row.kind,
|
|
218
|
+
legalName: row.legal_name,
|
|
219
|
+
email: row.email ?? undefined,
|
|
220
|
+
taxId: row.tax_id ?? undefined,
|
|
221
|
+
country: row.country ?? undefined,
|
|
222
|
+
address: row.address ?? undefined,
|
|
223
|
+
createdAt: row.created_at,
|
|
224
|
+
updatedAt: row.updated_at
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
function mapInvoiceRow(row) {
|
|
228
|
+
return {
|
|
229
|
+
id: row.id,
|
|
230
|
+
number: row.number,
|
|
231
|
+
issuerId: row.issuer_id,
|
|
232
|
+
customerId: row.customer_id,
|
|
233
|
+
status: row.status,
|
|
234
|
+
currency: row.currency,
|
|
235
|
+
notes: row.notes ?? undefined,
|
|
236
|
+
issuedAt: row.issued_at,
|
|
237
|
+
dueAt: row.due_at ?? undefined,
|
|
238
|
+
subtotalCents: row.subtotal_cents,
|
|
239
|
+
taxCents: row.tax_cents,
|
|
240
|
+
totalCents: row.total_cents,
|
|
241
|
+
createdAt: row.created_at,
|
|
242
|
+
updatedAt: row.updated_at
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
function mapInvoiceLineRow(row) {
|
|
246
|
+
return {
|
|
247
|
+
id: row.id,
|
|
248
|
+
invoiceId: row.invoice_id,
|
|
249
|
+
position: row.position,
|
|
250
|
+
description: row.description,
|
|
251
|
+
quantity: row.quantity,
|
|
252
|
+
unitPriceCents: row.unit_price_cents,
|
|
253
|
+
taxRateBasisPoints: row.tax_rate_basis_points,
|
|
254
|
+
lineTotalCents: row.line_total_cents,
|
|
255
|
+
createdAt: row.created_at
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function createParty(db, input) {
|
|
259
|
+
const id = input.id ?? randomUUID();
|
|
260
|
+
db.query(`
|
|
261
|
+
INSERT INTO parties (id, kind, legal_name, email, tax_id, country, address)
|
|
262
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7)
|
|
263
|
+
`).run(id, input.kind, input.legalName, input.email ?? null, input.taxId ?? null, input.country ?? null, input.address ?? null);
|
|
264
|
+
return getPartyById(db, id);
|
|
265
|
+
}
|
|
266
|
+
function updateParty(db, id, updates) {
|
|
267
|
+
db.query(`
|
|
268
|
+
UPDATE parties
|
|
269
|
+
SET legal_name = COALESCE(?2, legal_name),
|
|
270
|
+
email = COALESCE(?3, email),
|
|
271
|
+
tax_id = COALESCE(?4, tax_id),
|
|
272
|
+
country = COALESCE(?5, country),
|
|
273
|
+
address = COALESCE(?6, address),
|
|
274
|
+
updated_at = datetime('now')
|
|
275
|
+
WHERE id = ?1
|
|
276
|
+
`).run(id, updates.legalName ?? null, updates.email ?? null, updates.taxId ?? null, updates.country ?? null, updates.address ?? null);
|
|
277
|
+
return getPartyById(db, id);
|
|
278
|
+
}
|
|
279
|
+
function getPartyById(db, id) {
|
|
280
|
+
const row = db.query("SELECT * FROM parties WHERE id = ?1").get(id);
|
|
281
|
+
return row ? mapPartyRow(row) : null;
|
|
282
|
+
}
|
|
283
|
+
function listParties(db, kind) {
|
|
284
|
+
if (kind) {
|
|
285
|
+
return db.query("SELECT * FROM parties WHERE kind = ?1 ORDER BY legal_name ASC").all(kind).map(mapPartyRow);
|
|
286
|
+
}
|
|
287
|
+
return db.query("SELECT * FROM parties ORDER BY legal_name ASC").all().map(mapPartyRow);
|
|
288
|
+
}
|
|
289
|
+
function createInvoice(db, input) {
|
|
290
|
+
const invoiceId = input.id ?? randomUUID();
|
|
291
|
+
const preparedLines = input.lines.map((line, index) => {
|
|
292
|
+
const { lineTotalCents, lineTaxCents } = toLineTotalCents(line);
|
|
293
|
+
return {
|
|
294
|
+
id: line.id ?? randomUUID(),
|
|
295
|
+
position: index,
|
|
296
|
+
description: line.description,
|
|
297
|
+
quantity: line.quantity,
|
|
298
|
+
unitPriceCents: line.unitPriceCents,
|
|
299
|
+
taxRateBasisPoints: line.taxRateBasisPoints ?? 0,
|
|
300
|
+
lineTotalCents,
|
|
301
|
+
lineTaxCents
|
|
302
|
+
};
|
|
303
|
+
});
|
|
304
|
+
const subtotalCents = preparedLines.reduce((sum, line) => sum + line.lineTotalCents, 0);
|
|
305
|
+
const taxCents = preparedLines.reduce((sum, line) => sum + line.lineTaxCents, 0);
|
|
306
|
+
const totalCents = subtotalCents + taxCents;
|
|
307
|
+
db.transaction(() => {
|
|
308
|
+
db.query(`
|
|
309
|
+
INSERT INTO invoices (
|
|
310
|
+
id, number, issuer_id, customer_id, status, currency, notes, issued_at, due_at, subtotal_cents, tax_cents, total_cents
|
|
311
|
+
)
|
|
312
|
+
VALUES (?1, ?2, ?3, ?4, 'draft', ?5, ?6, ?7, ?8, ?9, ?10, ?11)
|
|
313
|
+
`).run(invoiceId, input.number, input.issuerId, input.customerId, input.currency, input.notes ?? null, input.issuedAt, input.dueAt ?? null, subtotalCents, taxCents, totalCents);
|
|
314
|
+
const insertLine = db.query(`
|
|
315
|
+
INSERT INTO invoice_lines (
|
|
316
|
+
id, invoice_id, position, description, quantity, unit_price_cents, tax_rate_basis_points, line_total_cents
|
|
317
|
+
)
|
|
318
|
+
VALUES (?1, ?2, ?3, ?4, ?5, ?6, ?7, ?8)
|
|
319
|
+
`);
|
|
320
|
+
for (const line of preparedLines) {
|
|
321
|
+
insertLine.run(line.id, invoiceId, line.position, line.description, line.quantity, line.unitPriceCents, line.taxRateBasisPoints, line.lineTotalCents);
|
|
322
|
+
}
|
|
323
|
+
})();
|
|
324
|
+
return getInvoiceById(db, invoiceId);
|
|
325
|
+
}
|
|
326
|
+
function getInvoiceById(db, id) {
|
|
327
|
+
const invoiceRow = db.query("SELECT * FROM invoices WHERE id = ?1").get(id);
|
|
328
|
+
if (!invoiceRow) {
|
|
329
|
+
return null;
|
|
330
|
+
}
|
|
331
|
+
const lines = db.query("SELECT * FROM invoice_lines WHERE invoice_id = ?1 ORDER BY position ASC").all(id).map(mapInvoiceLineRow);
|
|
332
|
+
return {
|
|
333
|
+
...mapInvoiceRow(invoiceRow),
|
|
334
|
+
lines
|
|
335
|
+
};
|
|
336
|
+
}
|
|
337
|
+
function listInvoices(db, options = {}) {
|
|
338
|
+
const limit = options.limit ?? 50;
|
|
339
|
+
const offset = options.offset ?? 0;
|
|
340
|
+
if (options.status) {
|
|
341
|
+
return db.query("SELECT * FROM invoices WHERE status = ?1 ORDER BY issued_at DESC, created_at DESC LIMIT ?2 OFFSET ?3").all(options.status, limit, offset).map(mapInvoiceRow);
|
|
342
|
+
}
|
|
343
|
+
return db.query("SELECT * FROM invoices ORDER BY issued_at DESC, created_at DESC LIMIT ?1 OFFSET ?2").all(limit, offset).map(mapInvoiceRow);
|
|
344
|
+
}
|
|
345
|
+
function updateInvoiceStatus(db, id, status) {
|
|
346
|
+
db.query("UPDATE invoices SET status = ?2, updated_at = datetime('now') WHERE id = ?1").run(id, status);
|
|
347
|
+
const row = db.query("SELECT * FROM invoices WHERE id = ?1").get(id);
|
|
348
|
+
return row ? mapInvoiceRow(row) : null;
|
|
349
|
+
}
|
|
350
|
+
function deleteInvoice(db, id) {
|
|
351
|
+
const result = db.query("DELETE FROM invoices WHERE id = ?1").run(id);
|
|
352
|
+
return result.changes > 0;
|
|
353
|
+
}
|
|
354
|
+
function rebuildInvoiceSearchIndex(db) {
|
|
355
|
+
db.exec("DELETE FROM invoices_fts;");
|
|
356
|
+
db.exec(`
|
|
357
|
+
INSERT INTO invoices_fts(invoice_id, number, issuer_name, customer_name, notes)
|
|
358
|
+
SELECT
|
|
359
|
+
i.id,
|
|
360
|
+
i.number,
|
|
361
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.issuer_id), ''),
|
|
362
|
+
COALESCE((SELECT legal_name FROM parties p WHERE p.id = i.customer_id), ''),
|
|
363
|
+
COALESCE(i.notes, '')
|
|
364
|
+
FROM invoices i;
|
|
365
|
+
`);
|
|
366
|
+
}
|
|
367
|
+
function searchInvoices(db, query, options = {}) {
|
|
368
|
+
const limit = options.limit ?? 20;
|
|
369
|
+
const offset = options.offset ?? 0;
|
|
370
|
+
const escapedPhrase = `"${query.replace(/"/g, '""')}"`;
|
|
371
|
+
if (options.status) {
|
|
372
|
+
return db.query(`
|
|
373
|
+
SELECT i.*
|
|
374
|
+
FROM invoices_fts f
|
|
375
|
+
JOIN invoices i ON i.id = f.invoice_id
|
|
376
|
+
WHERE invoices_fts MATCH ?1
|
|
377
|
+
AND i.status = ?2
|
|
378
|
+
ORDER BY bm25(invoices_fts)
|
|
379
|
+
LIMIT ?3
|
|
380
|
+
OFFSET ?4
|
|
381
|
+
`).all(escapedPhrase, options.status, limit, offset).map(mapInvoiceRow);
|
|
382
|
+
}
|
|
383
|
+
return db.query(`
|
|
384
|
+
SELECT i.*
|
|
385
|
+
FROM invoices_fts f
|
|
386
|
+
JOIN invoices i ON i.id = f.invoice_id
|
|
387
|
+
WHERE invoices_fts MATCH ?1
|
|
388
|
+
ORDER BY bm25(invoices_fts)
|
|
389
|
+
LIMIT ?2
|
|
390
|
+
OFFSET ?3
|
|
391
|
+
`).all(escapedPhrase, limit, offset).map(mapInvoiceRow);
|
|
392
|
+
}
|
|
393
|
+
// src/db/agents.ts
|
|
394
|
+
import { randomUUID as randomUUID2 } from "crypto";
|
|
395
|
+
function mapAgent(row) {
|
|
396
|
+
return {
|
|
397
|
+
id: row.id,
|
|
398
|
+
name: row.name,
|
|
399
|
+
description: row.description ?? undefined,
|
|
400
|
+
focus: row.focus ?? undefined,
|
|
401
|
+
createdAt: row.created_at,
|
|
402
|
+
lastSeenAt: row.last_seen_at
|
|
403
|
+
};
|
|
404
|
+
}
|
|
405
|
+
function registerAgent(db, input) {
|
|
406
|
+
const existing = db.query("SELECT * FROM agents WHERE name = ?1").get(input.name);
|
|
407
|
+
if (existing) {
|
|
408
|
+
db.query("UPDATE agents SET description = COALESCE(?2, description), last_seen_at = datetime('now') WHERE name = ?1").run(input.name, input.description ?? null);
|
|
409
|
+
return getAgentByName(db, input.name);
|
|
410
|
+
}
|
|
411
|
+
const id = randomUUID2();
|
|
412
|
+
db.query("INSERT INTO agents (id, name, description) VALUES (?1, ?2, ?3)").run(id, input.name, input.description ?? null);
|
|
413
|
+
return getAgentById(db, id);
|
|
414
|
+
}
|
|
415
|
+
function getAgentById(db, id) {
|
|
416
|
+
const row = db.query("SELECT * FROM agents WHERE id = ?1").get(id);
|
|
417
|
+
return row ? mapAgent(row) : null;
|
|
418
|
+
}
|
|
419
|
+
function getAgentByName(db, name) {
|
|
420
|
+
const row = db.query("SELECT * FROM agents WHERE name = ?1").get(name);
|
|
421
|
+
return row ? mapAgent(row) : null;
|
|
422
|
+
}
|
|
423
|
+
function heartbeatAgent(db, agentId) {
|
|
424
|
+
db.query("UPDATE agents SET last_seen_at = datetime('now') WHERE id = ?1").run(agentId);
|
|
425
|
+
return getAgentById(db, agentId);
|
|
426
|
+
}
|
|
427
|
+
function setAgentFocus(db, agentId, focus) {
|
|
428
|
+
db.query("UPDATE agents SET focus = ?2, last_seen_at = datetime('now') WHERE id = ?1").run(agentId, focus ?? null);
|
|
429
|
+
return getAgentById(db, agentId);
|
|
430
|
+
}
|
|
431
|
+
function listAgents(db) {
|
|
432
|
+
return db.query("SELECT * FROM agents ORDER BY last_seen_at DESC").all().map(mapAgent);
|
|
433
|
+
}
|
|
434
|
+
export {
|
|
435
|
+
updateParty,
|
|
436
|
+
updateInvoiceStatus,
|
|
437
|
+
setAgentFocus,
|
|
438
|
+
searchInvoices,
|
|
439
|
+
registerAgent,
|
|
440
|
+
rebuildInvoiceSearchIndex,
|
|
441
|
+
openInvoiceDatabase,
|
|
442
|
+
migrateDatabase,
|
|
443
|
+
listParties,
|
|
444
|
+
listInvoices,
|
|
445
|
+
listAgents,
|
|
446
|
+
heartbeatAgent,
|
|
447
|
+
getPartyById,
|
|
448
|
+
getInvoiceById,
|
|
449
|
+
getAgentByName,
|
|
450
|
+
getAgentById,
|
|
451
|
+
deleteInvoice,
|
|
452
|
+
defaultDatabasePath,
|
|
453
|
+
createParty,
|
|
454
|
+
createInvoice,
|
|
455
|
+
applyMigrations,
|
|
456
|
+
VERSION
|
|
457
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/lib/version.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/mcp/index.ts"],"names":[],"mappings":""}
|