@agentlensai/server 0.10.0 → 0.11.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/cloud/auth/api-key-middleware.d.ts +66 -0
- package/dist/cloud/auth/api-key-middleware.d.ts.map +1 -0
- package/dist/cloud/auth/api-key-middleware.js +147 -0
- package/dist/cloud/auth/api-key-middleware.js.map +1 -0
- package/dist/cloud/auth/api-keys.d.ts +90 -0
- package/dist/cloud/auth/api-keys.d.ts.map +1 -0
- package/dist/cloud/auth/api-keys.js +162 -0
- package/dist/cloud/auth/api-keys.js.map +1 -0
- package/dist/cloud/auth/audit-log.d.ts +66 -0
- package/dist/cloud/auth/audit-log.d.ts.map +1 -0
- package/dist/cloud/auth/audit-log.js +92 -0
- package/dist/cloud/auth/audit-log.js.map +1 -0
- package/dist/cloud/auth/auth-service.d.ts +77 -0
- package/dist/cloud/auth/auth-service.d.ts.map +1 -0
- package/dist/cloud/auth/auth-service.js +229 -0
- package/dist/cloud/auth/auth-service.js.map +1 -0
- package/dist/cloud/auth/brute-force.d.ts +36 -0
- package/dist/cloud/auth/brute-force.d.ts.map +1 -0
- package/dist/cloud/auth/brute-force.js +67 -0
- package/dist/cloud/auth/brute-force.js.map +1 -0
- package/dist/cloud/auth/index.d.ts +11 -0
- package/dist/cloud/auth/index.d.ts.map +1 -0
- package/dist/cloud/auth/index.js +11 -0
- package/dist/cloud/auth/index.js.map +1 -0
- package/dist/cloud/auth/jwt.d.ts +34 -0
- package/dist/cloud/auth/jwt.d.ts.map +1 -0
- package/dist/cloud/auth/jwt.js +68 -0
- package/dist/cloud/auth/jwt.js.map +1 -0
- package/dist/cloud/auth/oauth.d.ts +37 -0
- package/dist/cloud/auth/oauth.d.ts.map +1 -0
- package/dist/cloud/auth/oauth.js +120 -0
- package/dist/cloud/auth/oauth.js.map +1 -0
- package/dist/cloud/auth/passwords.d.ts +25 -0
- package/dist/cloud/auth/passwords.d.ts.map +1 -0
- package/dist/cloud/auth/passwords.js +50 -0
- package/dist/cloud/auth/passwords.js.map +1 -0
- package/dist/cloud/auth/rbac.d.ts +51 -0
- package/dist/cloud/auth/rbac.d.ts.map +1 -0
- package/dist/cloud/auth/rbac.js +89 -0
- package/dist/cloud/auth/rbac.js.map +1 -0
- package/dist/cloud/auth/tokens.d.ts +18 -0
- package/dist/cloud/auth/tokens.d.ts.map +1 -0
- package/dist/cloud/auth/tokens.js +29 -0
- package/dist/cloud/auth/tokens.js.map +1 -0
- package/dist/cloud/billing/billing-service.d.ts +44 -0
- package/dist/cloud/billing/billing-service.d.ts.map +1 -0
- package/dist/cloud/billing/billing-service.js +153 -0
- package/dist/cloud/billing/billing-service.js.map +1 -0
- package/dist/cloud/billing/index.d.ts +11 -0
- package/dist/cloud/billing/index.d.ts.map +1 -0
- package/dist/cloud/billing/index.js +11 -0
- package/dist/cloud/billing/index.js.map +1 -0
- package/dist/cloud/billing/invoice-service.d.ts +57 -0
- package/dist/cloud/billing/invoice-service.d.ts.map +1 -0
- package/dist/cloud/billing/invoice-service.js +123 -0
- package/dist/cloud/billing/invoice-service.js.map +1 -0
- package/dist/cloud/billing/plan-management.d.ts +46 -0
- package/dist/cloud/billing/plan-management.d.ts.map +1 -0
- package/dist/cloud/billing/plan-management.js +157 -0
- package/dist/cloud/billing/plan-management.js.map +1 -0
- package/dist/cloud/billing/quota-enforcement.d.ts +53 -0
- package/dist/cloud/billing/quota-enforcement.d.ts.map +1 -0
- package/dist/cloud/billing/quota-enforcement.js +143 -0
- package/dist/cloud/billing/quota-enforcement.js.map +1 -0
- package/dist/cloud/billing/stripe-client.d.ts +142 -0
- package/dist/cloud/billing/stripe-client.d.ts.map +1 -0
- package/dist/cloud/billing/stripe-client.js +169 -0
- package/dist/cloud/billing/stripe-client.js.map +1 -0
- package/dist/cloud/billing/trial-service.d.ts +47 -0
- package/dist/cloud/billing/trial-service.d.ts.map +1 -0
- package/dist/cloud/billing/trial-service.js +104 -0
- package/dist/cloud/billing/trial-service.js.map +1 -0
- package/dist/cloud/billing/usage-metering.d.ts +83 -0
- package/dist/cloud/billing/usage-metering.d.ts.map +1 -0
- package/dist/cloud/billing/usage-metering.js +174 -0
- package/dist/cloud/billing/usage-metering.js.map +1 -0
- package/dist/cloud/ingestion/backpressure.d.ts +107 -0
- package/dist/cloud/ingestion/backpressure.d.ts.map +1 -0
- package/dist/cloud/ingestion/backpressure.js +134 -0
- package/dist/cloud/ingestion/backpressure.js.map +1 -0
- package/dist/cloud/ingestion/batch-writer.d.ts +115 -0
- package/dist/cloud/ingestion/batch-writer.d.ts.map +1 -0
- package/dist/cloud/ingestion/batch-writer.js +319 -0
- package/dist/cloud/ingestion/batch-writer.js.map +1 -0
- package/dist/cloud/ingestion/dlq-manager.d.ts +116 -0
- package/dist/cloud/ingestion/dlq-manager.d.ts.map +1 -0
- package/dist/cloud/ingestion/dlq-manager.js +244 -0
- package/dist/cloud/ingestion/dlq-manager.js.map +1 -0
- package/dist/cloud/ingestion/event-queue.d.ts +105 -0
- package/dist/cloud/ingestion/event-queue.d.ts.map +1 -0
- package/dist/cloud/ingestion/event-queue.js +185 -0
- package/dist/cloud/ingestion/event-queue.js.map +1 -0
- package/dist/cloud/ingestion/gateway.d.ts +68 -0
- package/dist/cloud/ingestion/gateway.d.ts.map +1 -0
- package/dist/cloud/ingestion/gateway.js +198 -0
- package/dist/cloud/ingestion/gateway.js.map +1 -0
- package/dist/cloud/ingestion/index.d.ts +7 -0
- package/dist/cloud/ingestion/index.d.ts.map +1 -0
- package/dist/cloud/ingestion/index.js +7 -0
- package/dist/cloud/ingestion/index.js.map +1 -0
- package/dist/cloud/ingestion/rate-limiter.d.ts +73 -0
- package/dist/cloud/ingestion/rate-limiter.d.ts.map +1 -0
- package/dist/cloud/ingestion/rate-limiter.js +153 -0
- package/dist/cloud/ingestion/rate-limiter.js.map +1 -0
- package/dist/cloud/migrate.d.ts +45 -0
- package/dist/cloud/migrate.d.ts.map +1 -0
- package/dist/cloud/migrate.js +147 -0
- package/dist/cloud/migrate.js.map +1 -0
- package/dist/cloud/migration/export-import.d.ts +56 -0
- package/dist/cloud/migration/export-import.d.ts.map +1 -0
- package/dist/cloud/migration/export-import.js +289 -0
- package/dist/cloud/migration/export-import.js.map +1 -0
- package/dist/cloud/migration/index.d.ts +5 -0
- package/dist/cloud/migration/index.d.ts.map +1 -0
- package/dist/cloud/migration/index.js +5 -0
- package/dist/cloud/migration/index.js.map +1 -0
- package/dist/cloud/org-service.d.ts +68 -0
- package/dist/cloud/org-service.d.ts.map +1 -0
- package/dist/cloud/org-service.js +169 -0
- package/dist/cloud/org-service.js.map +1 -0
- package/dist/cloud/partition-maintenance.d.ts +29 -0
- package/dist/cloud/partition-maintenance.d.ts.map +1 -0
- package/dist/cloud/partition-maintenance.js +96 -0
- package/dist/cloud/partition-maintenance.js.map +1 -0
- package/dist/cloud/retention/index.d.ts +7 -0
- package/dist/cloud/retention/index.d.ts.map +1 -0
- package/dist/cloud/retention/index.js +7 -0
- package/dist/cloud/retention/index.js.map +1 -0
- package/dist/cloud/retention/partition-management.d.ts +61 -0
- package/dist/cloud/retention/partition-management.d.ts.map +1 -0
- package/dist/cloud/retention/partition-management.js +167 -0
- package/dist/cloud/retention/partition-management.js.map +1 -0
- package/dist/cloud/retention/retention-job.d.ts +70 -0
- package/dist/cloud/retention/retention-job.d.ts.map +1 -0
- package/dist/cloud/retention/retention-job.js +160 -0
- package/dist/cloud/retention/retention-job.js.map +1 -0
- package/dist/cloud/retention/retention-policy.d.ts +27 -0
- package/dist/cloud/retention/retention-policy.d.ts.map +1 -0
- package/dist/cloud/retention/retention-policy.js +36 -0
- package/dist/cloud/retention/retention-policy.js.map +1 -0
- package/dist/cloud/routes/api-key-routes.d.ts +38 -0
- package/dist/cloud/routes/api-key-routes.d.ts.map +1 -0
- package/dist/cloud/routes/api-key-routes.js +84 -0
- package/dist/cloud/routes/api-key-routes.js.map +1 -0
- package/dist/cloud/routes/audit-routes.d.ts +36 -0
- package/dist/cloud/routes/audit-routes.d.ts.map +1 -0
- package/dist/cloud/routes/audit-routes.js +47 -0
- package/dist/cloud/routes/audit-routes.js.map +1 -0
- package/dist/cloud/routes/billing-routes.d.ts +51 -0
- package/dist/cloud/routes/billing-routes.d.ts.map +1 -0
- package/dist/cloud/routes/billing-routes.js +114 -0
- package/dist/cloud/routes/billing-routes.js.map +1 -0
- package/dist/cloud/routes/onboarding-routes.d.ts +34 -0
- package/dist/cloud/routes/onboarding-routes.d.ts.map +1 -0
- package/dist/cloud/routes/onboarding-routes.js +58 -0
- package/dist/cloud/routes/onboarding-routes.js.map +1 -0
- package/dist/cloud/routes/org-routes.d.ts +80 -0
- package/dist/cloud/routes/org-routes.d.ts.map +1 -0
- package/dist/cloud/routes/org-routes.js +153 -0
- package/dist/cloud/routes/org-routes.js.map +1 -0
- package/dist/cloud/routes/usage-routes.d.ts +18 -0
- package/dist/cloud/routes/usage-routes.d.ts.map +1 -0
- package/dist/cloud/routes/usage-routes.js +66 -0
- package/dist/cloud/routes/usage-routes.js.map +1 -0
- package/dist/cloud/storage/adapter.d.ts +102 -0
- package/dist/cloud/storage/adapter.d.ts.map +1 -0
- package/dist/cloud/storage/adapter.js +21 -0
- package/dist/cloud/storage/adapter.js.map +1 -0
- package/dist/cloud/storage/index.d.ts +8 -0
- package/dist/cloud/storage/index.d.ts.map +1 -0
- package/dist/cloud/storage/index.js +7 -0
- package/dist/cloud/storage/index.js.map +1 -0
- package/dist/cloud/storage/postgres-adapter.d.ts +34 -0
- package/dist/cloud/storage/postgres-adapter.d.ts.map +1 -0
- package/dist/cloud/storage/postgres-adapter.js +544 -0
- package/dist/cloud/storage/postgres-adapter.js.map +1 -0
- package/dist/cloud/storage/sqlite-adapter.d.ts +29 -0
- package/dist/cloud/storage/sqlite-adapter.d.ts.map +1 -0
- package/dist/cloud/storage/sqlite-adapter.js +176 -0
- package/dist/cloud/storage/sqlite-adapter.js.map +1 -0
- package/dist/cloud/tenant-pool.d.ts +49 -0
- package/dist/cloud/tenant-pool.d.ts.map +1 -0
- package/dist/cloud/tenant-pool.js +61 -0
- package/dist/cloud/tenant-pool.js.map +1 -0
- package/package.json +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SQLite Storage Adapter (S-4.1, S-4.3, S-4.4)
|
|
3
|
+
*
|
|
4
|
+
* Wraps the existing SqliteEventStore to implement the StorageAdapter interface.
|
|
5
|
+
* orgId is mapped to tenantId for multi-tenant SQLite (self-hosted).
|
|
6
|
+
*
|
|
7
|
+
* S-4.3: Analytics use SQLite strftime for time bucketing.
|
|
8
|
+
* S-4.4: Full-text search uses LIKE (SQLite lacks tsvector; FTS5 optional).
|
|
9
|
+
*/
|
|
10
|
+
export class SqliteStorageAdapter {
|
|
11
|
+
store;
|
|
12
|
+
constructor(store) {
|
|
13
|
+
this.store = store;
|
|
14
|
+
}
|
|
15
|
+
async queryEvents(orgId, query) {
|
|
16
|
+
return this.store.queryEvents({ ...query, tenantId: orgId });
|
|
17
|
+
}
|
|
18
|
+
async getEventsBySession(orgId, sessionId) {
|
|
19
|
+
return this.store.getSessionTimeline(sessionId, orgId);
|
|
20
|
+
}
|
|
21
|
+
async getSessions(orgId, query) {
|
|
22
|
+
const result = await this.store.querySessions({ ...query, tenantId: orgId });
|
|
23
|
+
const limit = Math.min(query.limit ?? 50, 500);
|
|
24
|
+
const offset = query.offset ?? 0;
|
|
25
|
+
return {
|
|
26
|
+
items: result.sessions,
|
|
27
|
+
total: result.total,
|
|
28
|
+
hasMore: offset + result.sessions.length < result.total,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
async getSession(orgId, sessionId) {
|
|
32
|
+
return this.store.getSession(sessionId, orgId);
|
|
33
|
+
}
|
|
34
|
+
async getAgents(orgId) {
|
|
35
|
+
return this.store.listAgents(orgId);
|
|
36
|
+
}
|
|
37
|
+
async getStats(orgId) {
|
|
38
|
+
return this.store.getStats(orgId);
|
|
39
|
+
}
|
|
40
|
+
// ═══════════════════════════════════════════════════════════
|
|
41
|
+
// S-4.3: Analytics Queries (SQLite)
|
|
42
|
+
// ═══════════════════════════════════════════════════════════
|
|
43
|
+
async getCostAnalytics(orgId, query) {
|
|
44
|
+
const analyticsResult = await this.store.getAnalytics({
|
|
45
|
+
from: query.from,
|
|
46
|
+
to: query.to,
|
|
47
|
+
agentId: query.agentId,
|
|
48
|
+
granularity: query.granularity,
|
|
49
|
+
tenantId: orgId,
|
|
50
|
+
});
|
|
51
|
+
const buckets = analyticsResult.buckets.map((b) => ({
|
|
52
|
+
timestamp: b.timestamp,
|
|
53
|
+
totalCostUsd: b.totalCostUsd,
|
|
54
|
+
eventCount: b.eventCount,
|
|
55
|
+
}));
|
|
56
|
+
return {
|
|
57
|
+
buckets,
|
|
58
|
+
totalCostUsd: analyticsResult.totals.totalCostUsd,
|
|
59
|
+
totalEvents: analyticsResult.totals.eventCount,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
async getHealthAnalytics(_orgId, _query) {
|
|
63
|
+
// SQLite self-hosted: health_snapshots not yet implemented in the base store.
|
|
64
|
+
// Return empty results — feature parity is maintained by running the same
|
|
65
|
+
// test interface; the Postgres adapter provides the full implementation.
|
|
66
|
+
return { snapshots: [] };
|
|
67
|
+
}
|
|
68
|
+
async getTokenUsage(orgId, query) {
|
|
69
|
+
// Delegate to getAnalytics and extract token-relevant data
|
|
70
|
+
// The SQLite store tracks tokens via llm_response events in payload
|
|
71
|
+
const result = await this.store.getAnalytics({
|
|
72
|
+
from: query.from,
|
|
73
|
+
to: query.to,
|
|
74
|
+
agentId: query.agentId,
|
|
75
|
+
granularity: query.granularity,
|
|
76
|
+
tenantId: orgId,
|
|
77
|
+
});
|
|
78
|
+
// The standard analytics doesn't break out tokens, so we return
|
|
79
|
+
// what we can from the event counts. For full token data, the
|
|
80
|
+
// store would need a dedicated query.
|
|
81
|
+
const buckets = result.buckets.map((b) => ({
|
|
82
|
+
timestamp: b.timestamp,
|
|
83
|
+
inputTokens: 0,
|
|
84
|
+
outputTokens: 0,
|
|
85
|
+
totalTokens: 0,
|
|
86
|
+
llmCallCount: 0,
|
|
87
|
+
}));
|
|
88
|
+
return {
|
|
89
|
+
buckets,
|
|
90
|
+
totals: { inputTokens: 0, outputTokens: 0, totalTokens: 0, llmCallCount: 0 },
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
async getAnalytics(orgId, query) {
|
|
94
|
+
return this.store.getAnalytics({
|
|
95
|
+
from: query.from,
|
|
96
|
+
to: query.to,
|
|
97
|
+
agentId: query.agentId,
|
|
98
|
+
granularity: query.granularity,
|
|
99
|
+
tenantId: orgId,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
// ═══════════════════════════════════════════════════════════
|
|
103
|
+
// S-4.4: Full-Text Search (SQLite — LIKE fallback)
|
|
104
|
+
// ═══════════════════════════════════════════════════════════
|
|
105
|
+
async search(orgId, query) {
|
|
106
|
+
const limit = Math.min(query.limit ?? 20, 100);
|
|
107
|
+
const offset = query.offset ?? 0;
|
|
108
|
+
const scope = query.scope ?? 'all';
|
|
109
|
+
const searchTerm = query.query.trim();
|
|
110
|
+
if (!searchTerm) {
|
|
111
|
+
return { items: [], total: 0, hasMore: false };
|
|
112
|
+
}
|
|
113
|
+
const items = [];
|
|
114
|
+
let total = 0;
|
|
115
|
+
// Search events via existing queryEvents with search parameter
|
|
116
|
+
if (scope === 'events' || scope === 'all') {
|
|
117
|
+
const eventResult = await this.store.queryEvents({
|
|
118
|
+
tenantId: orgId,
|
|
119
|
+
search: searchTerm,
|
|
120
|
+
from: query.from,
|
|
121
|
+
to: query.to,
|
|
122
|
+
limit,
|
|
123
|
+
offset,
|
|
124
|
+
});
|
|
125
|
+
for (const event of eventResult.events) {
|
|
126
|
+
const payloadStr = typeof event.payload === 'string'
|
|
127
|
+
? event.payload
|
|
128
|
+
: JSON.stringify(event.payload);
|
|
129
|
+
// Create a simple headline: first 60 chars of payload containing match
|
|
130
|
+
const idx = payloadStr.toLowerCase().indexOf(searchTerm.toLowerCase());
|
|
131
|
+
const start = Math.max(0, idx - 20);
|
|
132
|
+
const headline = payloadStr.substring(start, start + 80);
|
|
133
|
+
items.push({
|
|
134
|
+
type: 'event',
|
|
135
|
+
id: event.id,
|
|
136
|
+
score: 1.0, // SQLite LIKE doesn't give relevance scores
|
|
137
|
+
headline,
|
|
138
|
+
timestamp: event.timestamp,
|
|
139
|
+
sessionId: event.sessionId,
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
total += eventResult.total;
|
|
143
|
+
}
|
|
144
|
+
// Search sessions via querySessions (by tags/agent name match)
|
|
145
|
+
if (scope === 'sessions' || scope === 'all') {
|
|
146
|
+
const sessionResult = await this.store.querySessions({
|
|
147
|
+
tenantId: orgId,
|
|
148
|
+
from: query.from,
|
|
149
|
+
to: query.to,
|
|
150
|
+
limit,
|
|
151
|
+
offset,
|
|
152
|
+
});
|
|
153
|
+
// Filter sessions that match the search term in agent name or tags
|
|
154
|
+
const matching = sessionResult.sessions.filter((s) => {
|
|
155
|
+
const text = `${s.agentName ?? ''} ${(s.tags ?? []).join(' ')}`.toLowerCase();
|
|
156
|
+
return text.includes(searchTerm.toLowerCase());
|
|
157
|
+
});
|
|
158
|
+
for (const session of matching) {
|
|
159
|
+
items.push({
|
|
160
|
+
type: 'session',
|
|
161
|
+
id: session.id,
|
|
162
|
+
score: 1.0,
|
|
163
|
+
headline: `${session.agentName ?? 'Unknown'} — ${(session.tags ?? []).join(', ')}`,
|
|
164
|
+
timestamp: session.startedAt,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
total += matching.length;
|
|
168
|
+
}
|
|
169
|
+
return {
|
|
170
|
+
items: items.slice(0, limit),
|
|
171
|
+
total,
|
|
172
|
+
hasMore: offset + Math.min(items.length, limit) < total,
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
//# sourceMappingURL=sqlite-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sqlite-adapter.js","sourceRoot":"","sources":["../../../src/cloud/storage/sqlite-adapter.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant-Aware Connection Pool (S-1.5)
|
|
3
|
+
*
|
|
4
|
+
* Wraps a PostgreSQL pool to automatically set `app.current_org`
|
|
5
|
+
* via SET LOCAL within a transaction. SET LOCAL is scoped to the
|
|
6
|
+
* transaction and auto-resets on commit/rollback, making it safe
|
|
7
|
+
* for connection reuse and compatible with PgBouncer transaction mode.
|
|
8
|
+
*/
|
|
9
|
+
export interface PoolClient {
|
|
10
|
+
query(sql: string, params?: unknown[]): Promise<{
|
|
11
|
+
rows: unknown[];
|
|
12
|
+
rowCount: number;
|
|
13
|
+
}>;
|
|
14
|
+
release(): void;
|
|
15
|
+
}
|
|
16
|
+
export interface Pool {
|
|
17
|
+
connect(): Promise<PoolClient>;
|
|
18
|
+
query(sql: string, params?: unknown[]): Promise<{
|
|
19
|
+
rows: unknown[];
|
|
20
|
+
rowCount: number;
|
|
21
|
+
}>;
|
|
22
|
+
end(): Promise<void>;
|
|
23
|
+
}
|
|
24
|
+
export interface TenantQueryResult {
|
|
25
|
+
rows: unknown[];
|
|
26
|
+
rowCount: number;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Execute a function within a tenant-scoped transaction.
|
|
30
|
+
*
|
|
31
|
+
* 1. Acquires connection from pool
|
|
32
|
+
* 2. BEGIN transaction
|
|
33
|
+
* 3. SET LOCAL app.current_org = orgId (scoped to transaction)
|
|
34
|
+
* 4. Execute the callback
|
|
35
|
+
* 5. COMMIT (or ROLLBACK on error)
|
|
36
|
+
* 6. Return connection to pool (app.current_org is auto-cleared)
|
|
37
|
+
*/
|
|
38
|
+
export declare function withTenantTransaction<T>(pool: Pool, orgId: string, fn: (client: PoolClient) => Promise<T>): Promise<T>;
|
|
39
|
+
/**
|
|
40
|
+
* Execute a single query within a tenant-scoped transaction.
|
|
41
|
+
* Convenience wrapper around withTenantTransaction for simple queries.
|
|
42
|
+
*/
|
|
43
|
+
export declare function tenantQuery(pool: Pool, orgId: string, sql: string, params?: unknown[]): Promise<TenantQueryResult>;
|
|
44
|
+
/**
|
|
45
|
+
* Execute a query WITHOUT tenant context.
|
|
46
|
+
* Use only for cross-tenant operations (e.g., admin queries, migrations).
|
|
47
|
+
*/
|
|
48
|
+
export declare function adminQuery(pool: Pool, sql: string, params?: unknown[]): Promise<TenantQueryResult>;
|
|
49
|
+
//# sourceMappingURL=tenant-pool.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-pool.d.ts","sourceRoot":"","sources":["../../src/cloud/tenant-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,MAAM,WAAW,UAAU;IACzB,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvF,OAAO,IAAI,IAAI,CAAC;CACjB;AAED,MAAM,WAAW,IAAI;IACnB,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,GAAG,OAAO,CAAC;QAAE,IAAI,EAAE,OAAO,EAAE,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC,CAAC;IACvF,GAAG,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACtB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,OAAO,EAAE,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;GASG;AACH,wBAAsB,qBAAqB,CAAC,CAAC,EAC3C,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,EAAE,EAAE,CAAC,MAAM,EAAE,UAAU,KAAK,OAAO,CAAC,CAAC,CAAC,GACrC,OAAO,CAAC,CAAC,CAAC,CAyBZ;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,IAAI,EAAE,IAAI,EACV,KAAK,EAAE,MAAM,EACb,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAI5B;AAED;;;GAGG;AACH,wBAAsB,UAAU,CAC9B,IAAI,EAAE,IAAI,EACV,GAAG,EAAE,MAAM,EACX,MAAM,CAAC,EAAE,OAAO,EAAE,GACjB,OAAO,CAAC,iBAAiB,CAAC,CAE5B"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tenant-Aware Connection Pool (S-1.5)
|
|
3
|
+
*
|
|
4
|
+
* Wraps a PostgreSQL pool to automatically set `app.current_org`
|
|
5
|
+
* via SET LOCAL within a transaction. SET LOCAL is scoped to the
|
|
6
|
+
* transaction and auto-resets on commit/rollback, making it safe
|
|
7
|
+
* for connection reuse and compatible with PgBouncer transaction mode.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* Execute a function within a tenant-scoped transaction.
|
|
11
|
+
*
|
|
12
|
+
* 1. Acquires connection from pool
|
|
13
|
+
* 2. BEGIN transaction
|
|
14
|
+
* 3. SET LOCAL app.current_org = orgId (scoped to transaction)
|
|
15
|
+
* 4. Execute the callback
|
|
16
|
+
* 5. COMMIT (or ROLLBACK on error)
|
|
17
|
+
* 6. Return connection to pool (app.current_org is auto-cleared)
|
|
18
|
+
*/
|
|
19
|
+
export async function withTenantTransaction(pool, orgId, fn) {
|
|
20
|
+
if (!orgId || typeof orgId !== 'string') {
|
|
21
|
+
throw new Error('orgId is required for tenant-scoped transactions');
|
|
22
|
+
}
|
|
23
|
+
// Basic UUID format validation
|
|
24
|
+
if (!/^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(orgId)) {
|
|
25
|
+
throw new Error('orgId must be a valid UUID');
|
|
26
|
+
}
|
|
27
|
+
const client = await pool.connect();
|
|
28
|
+
try {
|
|
29
|
+
await client.query('BEGIN');
|
|
30
|
+
// SET LOCAL is transaction-scoped: auto-clears on COMMIT/ROLLBACK
|
|
31
|
+
// Safe for PgBouncer transaction mode
|
|
32
|
+
await client.query(`SET LOCAL app.current_org = $1`, [orgId]);
|
|
33
|
+
const result = await fn(client);
|
|
34
|
+
await client.query('COMMIT');
|
|
35
|
+
return result;
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
await client.query('ROLLBACK');
|
|
39
|
+
throw err;
|
|
40
|
+
}
|
|
41
|
+
finally {
|
|
42
|
+
client.release();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Execute a single query within a tenant-scoped transaction.
|
|
47
|
+
* Convenience wrapper around withTenantTransaction for simple queries.
|
|
48
|
+
*/
|
|
49
|
+
export async function tenantQuery(pool, orgId, sql, params) {
|
|
50
|
+
return withTenantTransaction(pool, orgId, async (client) => {
|
|
51
|
+
return client.query(sql, params);
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Execute a query WITHOUT tenant context.
|
|
56
|
+
* Use only for cross-tenant operations (e.g., admin queries, migrations).
|
|
57
|
+
*/
|
|
58
|
+
export async function adminQuery(pool, sql, params) {
|
|
59
|
+
return pool.query(sql, params);
|
|
60
|
+
}
|
|
61
|
+
//# sourceMappingURL=tenant-pool.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tenant-pool.js","sourceRoot":"","sources":["../../src/cloud/tenant-pool.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAkBH;;;;;;;;;GASG;AACH,MAAM,CAAC,KAAK,UAAU,qBAAqB,CACzC,IAAU,EACV,KAAa,EACb,EAAsC;IAEtC,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;IACtE,CAAC;IAED,+BAA+B;IAC/B,IAAI,CAAC,iEAAiE,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACnF,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;IAChD,CAAC;IAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,OAAO,EAAE,CAAC;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QAC5B,kEAAkE;QAClE,sCAAsC;QACtC,MAAM,MAAM,CAAC,KAAK,CAAC,gCAAgC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC;QAChC,MAAM,MAAM,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QAC7B,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,MAAM,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;YAAS,CAAC;QACT,MAAM,CAAC,OAAO,EAAE,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAU,EACV,KAAa,EACb,GAAW,EACX,MAAkB;IAElB,OAAO,qBAAqB,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE;QACzD,OAAO,MAAM,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;IACnC,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,IAAU,EACV,GAAW,EACX,MAAkB;IAElB,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC;AACjC,CAAC"}
|