@hasna/todos 0.6.0 → 0.7.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/cli/index.js +6140 -124
- package/dist/index.js +89 -0
- package/dist/mcp/index.js +27 -0
- package/package.json +2 -1
package/dist/index.js
CHANGED
|
@@ -207,6 +207,33 @@ var MIGRATIONS = [
|
|
|
207
207
|
);
|
|
208
208
|
|
|
209
209
|
INSERT OR IGNORE INTO _migrations (id) VALUES (6);
|
|
210
|
+
`,
|
|
211
|
+
`
|
|
212
|
+
CREATE TABLE IF NOT EXISTS billing_customers (
|
|
213
|
+
id TEXT PRIMARY KEY,
|
|
214
|
+
stripe_customer_id TEXT UNIQUE,
|
|
215
|
+
email TEXT,
|
|
216
|
+
name TEXT,
|
|
217
|
+
plan TEXT NOT NULL DEFAULT 'free' CHECK(plan IN ('free', 'pro', 'team', 'enterprise')),
|
|
218
|
+
stripe_subscription_id TEXT,
|
|
219
|
+
subscription_status TEXT DEFAULT 'active' CHECK(subscription_status IN ('active', 'past_due', 'canceled', 'trialing', 'incomplete')),
|
|
220
|
+
current_period_end TEXT,
|
|
221
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
222
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
223
|
+
);
|
|
224
|
+
CREATE INDEX IF NOT EXISTS idx_billing_stripe ON billing_customers(stripe_customer_id);
|
|
225
|
+
|
|
226
|
+
CREATE TABLE IF NOT EXISTS usage_records (
|
|
227
|
+
id TEXT PRIMARY KEY,
|
|
228
|
+
customer_id TEXT REFERENCES billing_customers(id),
|
|
229
|
+
metric TEXT NOT NULL,
|
|
230
|
+
count INTEGER NOT NULL DEFAULT 0,
|
|
231
|
+
period TEXT NOT NULL,
|
|
232
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
233
|
+
);
|
|
234
|
+
CREATE INDEX IF NOT EXISTS idx_usage_customer ON usage_records(customer_id, period);
|
|
235
|
+
|
|
236
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (7);
|
|
210
237
|
`
|
|
211
238
|
];
|
|
212
239
|
var _db = null;
|
|
@@ -1648,13 +1675,70 @@ async function dispatchWebhooks(event, payload, db) {
|
|
|
1648
1675
|
} catch {}
|
|
1649
1676
|
}
|
|
1650
1677
|
}
|
|
1678
|
+
// src/db/billing.ts
|
|
1679
|
+
function getOrCreateCustomer(db) {
|
|
1680
|
+
const d = db || getDatabase();
|
|
1681
|
+
const existing = d.query("SELECT * FROM billing_customers LIMIT 1").get();
|
|
1682
|
+
if (existing)
|
|
1683
|
+
return existing;
|
|
1684
|
+
const id = uuid();
|
|
1685
|
+
const timestamp = now();
|
|
1686
|
+
d.run(`INSERT INTO billing_customers (id, plan, created_at, updated_at) VALUES (?, 'free', ?, ?)`, [id, timestamp, timestamp]);
|
|
1687
|
+
return d.query("SELECT * FROM billing_customers WHERE id = ?").get(id);
|
|
1688
|
+
}
|
|
1689
|
+
function updateCustomer(id, input, db) {
|
|
1690
|
+
const d = db || getDatabase();
|
|
1691
|
+
const sets = ["updated_at = ?"];
|
|
1692
|
+
const params = [now()];
|
|
1693
|
+
for (const [key, value] of Object.entries(input)) {
|
|
1694
|
+
if (value !== undefined) {
|
|
1695
|
+
sets.push(`${key} = ?`);
|
|
1696
|
+
params.push(value);
|
|
1697
|
+
}
|
|
1698
|
+
}
|
|
1699
|
+
params.push(id);
|
|
1700
|
+
d.run(`UPDATE billing_customers SET ${sets.join(", ")} WHERE id = ?`, params);
|
|
1701
|
+
return d.query("SELECT * FROM billing_customers WHERE id = ?").get(id);
|
|
1702
|
+
}
|
|
1703
|
+
function getCustomerByStripeId(stripeCustomerId, db) {
|
|
1704
|
+
const d = db || getDatabase();
|
|
1705
|
+
return d.query("SELECT * FROM billing_customers WHERE stripe_customer_id = ?").get(stripeCustomerId);
|
|
1706
|
+
}
|
|
1707
|
+
function getUsage(customerId, period, db) {
|
|
1708
|
+
const d = db || getDatabase();
|
|
1709
|
+
return d.query("SELECT * FROM usage_records WHERE customer_id = ? AND period = ?").all(customerId, period);
|
|
1710
|
+
}
|
|
1711
|
+
function trackUsage(customerId, metric, count = 1, db) {
|
|
1712
|
+
const d = db || getDatabase();
|
|
1713
|
+
const period = new Date().toISOString().slice(0, 7);
|
|
1714
|
+
const existing = d.query("SELECT * FROM usage_records WHERE customer_id = ? AND metric = ? AND period = ?").get(customerId, metric, period);
|
|
1715
|
+
if (existing) {
|
|
1716
|
+
d.run("UPDATE usage_records SET count = count + ? WHERE id = ?", [count, existing.id]);
|
|
1717
|
+
} else {
|
|
1718
|
+
d.run("INSERT INTO usage_records (id, customer_id, metric, count, period, created_at) VALUES (?, ?, ?, ?, ?, ?)", [uuid(), customerId, metric, count, period, now()]);
|
|
1719
|
+
}
|
|
1720
|
+
}
|
|
1721
|
+
var PLAN_LIMITS = {
|
|
1722
|
+
free: { tasks: 100, projects: 3, plans: 5, api_keys: 1, webhooks: 0 },
|
|
1723
|
+
pro: { tasks: 1e4, projects: 50, plans: 100, api_keys: 10, webhooks: 10 },
|
|
1724
|
+
team: { tasks: 1e5, projects: 500, plans: 1000, api_keys: 50, webhooks: 50 },
|
|
1725
|
+
enterprise: { tasks: -1, projects: -1, plans: -1, api_keys: -1, webhooks: -1 }
|
|
1726
|
+
};
|
|
1727
|
+
var PLAN_PRICES = {
|
|
1728
|
+
free: { monthly: 0, yearly: 0 },
|
|
1729
|
+
pro: { monthly: 9, yearly: 84 },
|
|
1730
|
+
team: { monthly: 29, yearly: 276 },
|
|
1731
|
+
enterprise: { monthly: 99, yearly: 948 }
|
|
1732
|
+
};
|
|
1651
1733
|
export {
|
|
1652
1734
|
validateApiKey,
|
|
1653
1735
|
updateTask,
|
|
1654
1736
|
updateSessionActivity,
|
|
1655
1737
|
updateProject,
|
|
1656
1738
|
updatePlan,
|
|
1739
|
+
updateCustomer,
|
|
1657
1740
|
unlockTask,
|
|
1741
|
+
trackUsage,
|
|
1658
1742
|
syncWithAgents,
|
|
1659
1743
|
syncWithAgent,
|
|
1660
1744
|
startTask,
|
|
@@ -1675,6 +1759,7 @@ export {
|
|
|
1675
1759
|
listApiKeys,
|
|
1676
1760
|
hasAnyApiKeys,
|
|
1677
1761
|
getWebhook,
|
|
1762
|
+
getUsage,
|
|
1678
1763
|
getTaskWithRelations,
|
|
1679
1764
|
getTaskDependents,
|
|
1680
1765
|
getTaskDependencies,
|
|
@@ -1683,7 +1768,9 @@ export {
|
|
|
1683
1768
|
getProjectByPath,
|
|
1684
1769
|
getProject,
|
|
1685
1770
|
getPlan,
|
|
1771
|
+
getOrCreateCustomer,
|
|
1686
1772
|
getDatabase,
|
|
1773
|
+
getCustomerByStripeId,
|
|
1687
1774
|
getComment,
|
|
1688
1775
|
getAuditLog,
|
|
1689
1776
|
ensureProject,
|
|
@@ -1713,6 +1800,8 @@ export {
|
|
|
1713
1800
|
ProjectNotFoundError,
|
|
1714
1801
|
PlanNotFoundError,
|
|
1715
1802
|
PLAN_STATUSES,
|
|
1803
|
+
PLAN_PRICES,
|
|
1804
|
+
PLAN_LIMITS,
|
|
1716
1805
|
LockError,
|
|
1717
1806
|
DependencyCycleError
|
|
1718
1807
|
};
|
package/dist/mcp/index.js
CHANGED
|
@@ -4249,6 +4249,33 @@ var MIGRATIONS = [
|
|
|
4249
4249
|
);
|
|
4250
4250
|
|
|
4251
4251
|
INSERT OR IGNORE INTO _migrations (id) VALUES (6);
|
|
4252
|
+
`,
|
|
4253
|
+
`
|
|
4254
|
+
CREATE TABLE IF NOT EXISTS billing_customers (
|
|
4255
|
+
id TEXT PRIMARY KEY,
|
|
4256
|
+
stripe_customer_id TEXT UNIQUE,
|
|
4257
|
+
email TEXT,
|
|
4258
|
+
name TEXT,
|
|
4259
|
+
plan TEXT NOT NULL DEFAULT 'free' CHECK(plan IN ('free', 'pro', 'team', 'enterprise')),
|
|
4260
|
+
stripe_subscription_id TEXT,
|
|
4261
|
+
subscription_status TEXT DEFAULT 'active' CHECK(subscription_status IN ('active', 'past_due', 'canceled', 'trialing', 'incomplete')),
|
|
4262
|
+
current_period_end TEXT,
|
|
4263
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
4264
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
4265
|
+
);
|
|
4266
|
+
CREATE INDEX IF NOT EXISTS idx_billing_stripe ON billing_customers(stripe_customer_id);
|
|
4267
|
+
|
|
4268
|
+
CREATE TABLE IF NOT EXISTS usage_records (
|
|
4269
|
+
id TEXT PRIMARY KEY,
|
|
4270
|
+
customer_id TEXT REFERENCES billing_customers(id),
|
|
4271
|
+
metric TEXT NOT NULL,
|
|
4272
|
+
count INTEGER NOT NULL DEFAULT 0,
|
|
4273
|
+
period TEXT NOT NULL,
|
|
4274
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now'))
|
|
4275
|
+
);
|
|
4276
|
+
CREATE INDEX IF NOT EXISTS idx_usage_customer ON usage_records(customer_id, period);
|
|
4277
|
+
|
|
4278
|
+
INSERT OR IGNORE INTO _migrations (id) VALUES (7);
|
|
4252
4279
|
`
|
|
4253
4280
|
];
|
|
4254
4281
|
var _db = null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hasna/todos",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Universal task management for AI coding agents - CLI + MCP server + interactive TUI",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -49,6 +49,7 @@
|
|
|
49
49
|
"commander": "^13.1.0",
|
|
50
50
|
"ink": "^5.2.0",
|
|
51
51
|
"react": "^18.3.1",
|
|
52
|
+
"stripe": "^20.3.1",
|
|
52
53
|
"zod": "^3.24.2"
|
|
53
54
|
},
|
|
54
55
|
"devDependencies": {
|