@resvary/sqlite 0.5.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/LICENSE +13 -13
- package/README.md +19 -15
- package/dist/credit.d.ts +12 -3
- package/dist/credit.d.ts.map +1 -1
- package/dist/credit.js +501 -197
- package/dist/credit.js.map +1 -1
- package/dist/filesystem.d.ts +3 -0
- package/dist/filesystem.d.ts.map +1 -0
- package/dist/filesystem.js +31 -0
- package/dist/filesystem.js.map +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +128 -130
- package/dist/index.js.map +1 -1
- package/package.json +46 -40
package/dist/credit.js
CHANGED
|
@@ -1,16 +1,15 @@
|
|
|
1
|
-
import { mkdirSync } from 'node:fs';
|
|
2
|
-
import { dirname } from 'node:path';
|
|
3
1
|
import { DatabaseSync } from 'node:sqlite';
|
|
2
|
+
import { creditUnitsToString, parseCreditUnits } from '@resvary/sdk/credits';
|
|
4
3
|
import { parseReceiptStoreValue, serializeReceiptStoreValue } from '@resvary/sdk/receipts';
|
|
4
|
+
import { hardenSqliteDatabaseFiles, prepareSqliteDatabasePath } from './filesystem.js';
|
|
5
5
|
export class SqliteCreditStore {
|
|
6
6
|
db;
|
|
7
7
|
transactionTail = Promise.resolve();
|
|
8
8
|
constructor(config) {
|
|
9
|
-
|
|
10
|
-
mkdirSync(dirname(config.path), { recursive: true });
|
|
11
|
-
}
|
|
9
|
+
prepareSqliteDatabasePath(config.path, config.createDirectory !== false);
|
|
12
10
|
this.db = new DatabaseSync(config.path);
|
|
13
11
|
this.migrate();
|
|
12
|
+
hardenSqliteDatabaseFiles(config.path);
|
|
14
13
|
}
|
|
15
14
|
async transaction(handler) {
|
|
16
15
|
let release;
|
|
@@ -106,6 +105,30 @@ export class SqliteCreditStore {
|
|
|
106
105
|
listFundingTransactions(fundingIntentId) {
|
|
107
106
|
return reader(this.db).listFundingTransactions(fundingIntentId);
|
|
108
107
|
}
|
|
108
|
+
getGrantPolicy(id) {
|
|
109
|
+
return reader(this.db).getGrantPolicy(id);
|
|
110
|
+
}
|
|
111
|
+
listGrantPolicies(projectId) {
|
|
112
|
+
return reader(this.db).listGrantPolicies(projectId);
|
|
113
|
+
}
|
|
114
|
+
getCreditLot(id) {
|
|
115
|
+
return reader(this.db).getCreditLot(id);
|
|
116
|
+
}
|
|
117
|
+
listCreditLots(filter) {
|
|
118
|
+
return reader(this.db).listCreditLots(filter);
|
|
119
|
+
}
|
|
120
|
+
listCreditLotAllocations(reservationId) {
|
|
121
|
+
return reader(this.db).listCreditLotAllocations(reservationId);
|
|
122
|
+
}
|
|
123
|
+
getGrantPolicyApplication(id) {
|
|
124
|
+
return reader(this.db).getGrantPolicyApplication(id);
|
|
125
|
+
}
|
|
126
|
+
getGrantPolicyApplicationByIdentity(policyId, accountId, periodKey) {
|
|
127
|
+
return reader(this.db).getGrantPolicyApplicationByIdentity(policyId, accountId, periodKey);
|
|
128
|
+
}
|
|
129
|
+
listGrantPolicyApplications(filter) {
|
|
130
|
+
return reader(this.db).listGrantPolicyApplications(filter);
|
|
131
|
+
}
|
|
109
132
|
claimOutboxEvents(input) {
|
|
110
133
|
return this.transaction(async (tx) => {
|
|
111
134
|
const events = (await tx.listOutboxEvents({ projectId: input.projectId }))
|
|
@@ -182,132 +205,133 @@ export class SqliteCreditStore {
|
|
|
182
205
|
this.db.close();
|
|
183
206
|
}
|
|
184
207
|
migrate() {
|
|
185
|
-
this.db.exec(`
|
|
186
|
-
PRAGMA journal_mode = WAL;
|
|
187
|
-
PRAGMA busy_timeout = 5000;
|
|
188
|
-
PRAGMA foreign_keys = ON;
|
|
189
|
-
|
|
190
|
-
CREATE TABLE IF NOT EXISTS resvary_schema_migrations (
|
|
191
|
-
version INTEGER PRIMARY KEY,
|
|
192
|
-
applied_at INTEGER NOT NULL
|
|
193
|
-
);
|
|
194
|
-
|
|
195
|
-
CREATE TABLE IF NOT EXISTS resvary_credit_accounts (
|
|
196
|
-
id TEXT PRIMARY KEY,
|
|
197
|
-
project_id TEXT NOT NULL,
|
|
198
|
-
customer_id TEXT NOT NULL,
|
|
199
|
-
updated_at INTEGER NOT NULL,
|
|
200
|
-
payload TEXT NOT NULL,
|
|
201
|
-
UNIQUE(project_id, customer_id)
|
|
202
|
-
);
|
|
203
|
-
|
|
204
|
-
CREATE TABLE IF NOT EXISTS resvary_credit_grants (
|
|
205
|
-
id TEXT PRIMARY KEY,
|
|
206
|
-
account_id TEXT NOT NULL,
|
|
207
|
-
created_at INTEGER NOT NULL,
|
|
208
|
-
payload TEXT NOT NULL
|
|
209
|
-
);
|
|
210
|
-
CREATE INDEX IF NOT EXISTS resvary_credit_grants_account ON resvary_credit_grants(account_id);
|
|
211
|
-
|
|
212
|
-
CREATE TABLE IF NOT EXISTS resvary_meters (
|
|
213
|
-
id TEXT PRIMARY KEY,
|
|
214
|
-
project_id TEXT NOT NULL,
|
|
215
|
-
meter_key TEXT NOT NULL,
|
|
216
|
-
payload TEXT NOT NULL,
|
|
217
|
-
UNIQUE(project_id, meter_key)
|
|
218
|
-
);
|
|
219
|
-
|
|
220
|
-
CREATE TABLE IF NOT EXISTS resvary_price_versions (
|
|
221
|
-
id TEXT PRIMARY KEY,
|
|
222
|
-
meter_id TEXT NOT NULL,
|
|
223
|
-
version INTEGER NOT NULL,
|
|
224
|
-
created_at INTEGER NOT NULL,
|
|
225
|
-
payload TEXT NOT NULL,
|
|
226
|
-
UNIQUE(meter_id, version)
|
|
227
|
-
);
|
|
228
|
-
|
|
229
|
-
CREATE TABLE IF NOT EXISTS resvary_credit_reservations (
|
|
230
|
-
id TEXT PRIMARY KEY,
|
|
231
|
-
account_id TEXT NOT NULL,
|
|
232
|
-
project_id TEXT NOT NULL,
|
|
233
|
-
customer_id TEXT NOT NULL,
|
|
234
|
-
status TEXT NOT NULL,
|
|
235
|
-
expires_at INTEGER NOT NULL,
|
|
236
|
-
created_at INTEGER NOT NULL,
|
|
237
|
-
payload TEXT NOT NULL
|
|
238
|
-
);
|
|
239
|
-
CREATE INDEX IF NOT EXISTS resvary_credit_reservations_open
|
|
240
|
-
ON resvary_credit_reservations(project_id, customer_id, status, expires_at);
|
|
241
|
-
|
|
242
|
-
CREATE TABLE IF NOT EXISTS resvary_usage_events (
|
|
243
|
-
id TEXT PRIMARY KEY,
|
|
244
|
-
account_id TEXT NOT NULL,
|
|
245
|
-
received_at INTEGER NOT NULL,
|
|
246
|
-
payload TEXT NOT NULL
|
|
247
|
-
);
|
|
248
|
-
|
|
249
|
-
CREATE TABLE IF NOT EXISTS resvary_usage_receipts (
|
|
250
|
-
id TEXT PRIMARY KEY,
|
|
251
|
-
account_id TEXT NOT NULL,
|
|
252
|
-
reservation_id TEXT NOT NULL UNIQUE,
|
|
253
|
-
usage_event_id TEXT NOT NULL UNIQUE,
|
|
254
|
-
created_at INTEGER NOT NULL,
|
|
255
|
-
payload TEXT NOT NULL
|
|
256
|
-
);
|
|
257
|
-
CREATE INDEX IF NOT EXISTS resvary_usage_receipts_account ON resvary_usage_receipts(account_id, created_at);
|
|
258
|
-
|
|
259
|
-
CREATE TABLE IF NOT EXISTS resvary_ledger_entries (
|
|
260
|
-
id TEXT PRIMARY KEY,
|
|
261
|
-
account_id TEXT NOT NULL,
|
|
262
|
-
created_at INTEGER NOT NULL,
|
|
263
|
-
payload TEXT NOT NULL
|
|
264
|
-
);
|
|
265
|
-
CREATE INDEX IF NOT EXISTS resvary_ledger_entries_account ON resvary_ledger_entries(account_id, created_at);
|
|
266
|
-
|
|
267
|
-
CREATE TABLE IF NOT EXISTS resvary_funding_intents (
|
|
268
|
-
id TEXT PRIMARY KEY,
|
|
269
|
-
project_id TEXT NOT NULL,
|
|
270
|
-
customer_id TEXT NOT NULL,
|
|
271
|
-
status TEXT NOT NULL,
|
|
272
|
-
created_at INTEGER NOT NULL,
|
|
273
|
-
payload TEXT NOT NULL
|
|
274
|
-
);
|
|
275
|
-
|
|
276
|
-
CREATE TABLE IF NOT EXISTS resvary_funding_transactions (
|
|
277
|
-
id TEXT PRIMARY KEY,
|
|
278
|
-
funding_intent_id TEXT NOT NULL,
|
|
279
|
-
network TEXT NOT NULL,
|
|
280
|
-
tx_hash_norm TEXT NOT NULL,
|
|
281
|
-
created_at INTEGER NOT NULL,
|
|
282
|
-
payload TEXT NOT NULL,
|
|
283
|
-
UNIQUE(network, tx_hash_norm)
|
|
284
|
-
);
|
|
285
|
-
|
|
286
|
-
CREATE TABLE IF NOT EXISTS resvary_idempotency_keys (
|
|
287
|
-
scope TEXT NOT NULL,
|
|
288
|
-
key TEXT NOT NULL,
|
|
289
|
-
created_at INTEGER NOT NULL,
|
|
290
|
-
payload TEXT NOT NULL,
|
|
291
|
-
PRIMARY KEY(scope, key)
|
|
292
|
-
);
|
|
293
|
-
|
|
294
|
-
CREATE TABLE IF NOT EXISTS resvary_outbox_events (
|
|
295
|
-
id TEXT PRIMARY KEY,
|
|
296
|
-
project_id TEXT NOT NULL,
|
|
297
|
-
type TEXT NOT NULL,
|
|
298
|
-
status TEXT NOT NULL,
|
|
299
|
-
created_at INTEGER NOT NULL,
|
|
300
|
-
payload TEXT NOT NULL
|
|
301
|
-
);
|
|
302
|
-
CREATE INDEX IF NOT EXISTS resvary_outbox_events_pending
|
|
303
|
-
ON resvary_outbox_events(project_id, status, created_at);
|
|
304
|
-
|
|
305
|
-
INSERT OR IGNORE INTO resvary_schema_migrations(version, applied_at)
|
|
306
|
-
VALUES (1, CAST(strftime('%s', 'now') AS INTEGER) * 1000);
|
|
208
|
+
this.db.exec(`
|
|
209
|
+
PRAGMA journal_mode = WAL;
|
|
210
|
+
PRAGMA busy_timeout = 5000;
|
|
211
|
+
PRAGMA foreign_keys = ON;
|
|
212
|
+
|
|
213
|
+
CREATE TABLE IF NOT EXISTS resvary_schema_migrations (
|
|
214
|
+
version INTEGER PRIMARY KEY,
|
|
215
|
+
applied_at INTEGER NOT NULL
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
CREATE TABLE IF NOT EXISTS resvary_credit_accounts (
|
|
219
|
+
id TEXT PRIMARY KEY,
|
|
220
|
+
project_id TEXT NOT NULL,
|
|
221
|
+
customer_id TEXT NOT NULL,
|
|
222
|
+
updated_at INTEGER NOT NULL,
|
|
223
|
+
payload TEXT NOT NULL,
|
|
224
|
+
UNIQUE(project_id, customer_id)
|
|
225
|
+
);
|
|
226
|
+
|
|
227
|
+
CREATE TABLE IF NOT EXISTS resvary_credit_grants (
|
|
228
|
+
id TEXT PRIMARY KEY,
|
|
229
|
+
account_id TEXT NOT NULL,
|
|
230
|
+
created_at INTEGER NOT NULL,
|
|
231
|
+
payload TEXT NOT NULL
|
|
232
|
+
);
|
|
233
|
+
CREATE INDEX IF NOT EXISTS resvary_credit_grants_account ON resvary_credit_grants(account_id);
|
|
234
|
+
|
|
235
|
+
CREATE TABLE IF NOT EXISTS resvary_meters (
|
|
236
|
+
id TEXT PRIMARY KEY,
|
|
237
|
+
project_id TEXT NOT NULL,
|
|
238
|
+
meter_key TEXT NOT NULL,
|
|
239
|
+
payload TEXT NOT NULL,
|
|
240
|
+
UNIQUE(project_id, meter_key)
|
|
241
|
+
);
|
|
242
|
+
|
|
243
|
+
CREATE TABLE IF NOT EXISTS resvary_price_versions (
|
|
244
|
+
id TEXT PRIMARY KEY,
|
|
245
|
+
meter_id TEXT NOT NULL,
|
|
246
|
+
version INTEGER NOT NULL,
|
|
247
|
+
created_at INTEGER NOT NULL,
|
|
248
|
+
payload TEXT NOT NULL,
|
|
249
|
+
UNIQUE(meter_id, version)
|
|
250
|
+
);
|
|
251
|
+
|
|
252
|
+
CREATE TABLE IF NOT EXISTS resvary_credit_reservations (
|
|
253
|
+
id TEXT PRIMARY KEY,
|
|
254
|
+
account_id TEXT NOT NULL,
|
|
255
|
+
project_id TEXT NOT NULL,
|
|
256
|
+
customer_id TEXT NOT NULL,
|
|
257
|
+
status TEXT NOT NULL,
|
|
258
|
+
expires_at INTEGER NOT NULL,
|
|
259
|
+
created_at INTEGER NOT NULL,
|
|
260
|
+
payload TEXT NOT NULL
|
|
261
|
+
);
|
|
262
|
+
CREATE INDEX IF NOT EXISTS resvary_credit_reservations_open
|
|
263
|
+
ON resvary_credit_reservations(project_id, customer_id, status, expires_at);
|
|
264
|
+
|
|
265
|
+
CREATE TABLE IF NOT EXISTS resvary_usage_events (
|
|
266
|
+
id TEXT PRIMARY KEY,
|
|
267
|
+
account_id TEXT NOT NULL,
|
|
268
|
+
received_at INTEGER NOT NULL,
|
|
269
|
+
payload TEXT NOT NULL
|
|
270
|
+
);
|
|
271
|
+
|
|
272
|
+
CREATE TABLE IF NOT EXISTS resvary_usage_receipts (
|
|
273
|
+
id TEXT PRIMARY KEY,
|
|
274
|
+
account_id TEXT NOT NULL,
|
|
275
|
+
reservation_id TEXT NOT NULL UNIQUE,
|
|
276
|
+
usage_event_id TEXT NOT NULL UNIQUE,
|
|
277
|
+
created_at INTEGER NOT NULL,
|
|
278
|
+
payload TEXT NOT NULL
|
|
279
|
+
);
|
|
280
|
+
CREATE INDEX IF NOT EXISTS resvary_usage_receipts_account ON resvary_usage_receipts(account_id, created_at);
|
|
281
|
+
|
|
282
|
+
CREATE TABLE IF NOT EXISTS resvary_ledger_entries (
|
|
283
|
+
id TEXT PRIMARY KEY,
|
|
284
|
+
account_id TEXT NOT NULL,
|
|
285
|
+
created_at INTEGER NOT NULL,
|
|
286
|
+
payload TEXT NOT NULL
|
|
287
|
+
);
|
|
288
|
+
CREATE INDEX IF NOT EXISTS resvary_ledger_entries_account ON resvary_ledger_entries(account_id, created_at);
|
|
289
|
+
|
|
290
|
+
CREATE TABLE IF NOT EXISTS resvary_funding_intents (
|
|
291
|
+
id TEXT PRIMARY KEY,
|
|
292
|
+
project_id TEXT NOT NULL,
|
|
293
|
+
customer_id TEXT NOT NULL,
|
|
294
|
+
status TEXT NOT NULL,
|
|
295
|
+
created_at INTEGER NOT NULL,
|
|
296
|
+
payload TEXT NOT NULL
|
|
297
|
+
);
|
|
298
|
+
|
|
299
|
+
CREATE TABLE IF NOT EXISTS resvary_funding_transactions (
|
|
300
|
+
id TEXT PRIMARY KEY,
|
|
301
|
+
funding_intent_id TEXT NOT NULL,
|
|
302
|
+
network TEXT NOT NULL,
|
|
303
|
+
tx_hash_norm TEXT NOT NULL,
|
|
304
|
+
created_at INTEGER NOT NULL,
|
|
305
|
+
payload TEXT NOT NULL,
|
|
306
|
+
UNIQUE(network, tx_hash_norm)
|
|
307
|
+
);
|
|
308
|
+
|
|
309
|
+
CREATE TABLE IF NOT EXISTS resvary_idempotency_keys (
|
|
310
|
+
scope TEXT NOT NULL,
|
|
311
|
+
key TEXT NOT NULL,
|
|
312
|
+
created_at INTEGER NOT NULL,
|
|
313
|
+
payload TEXT NOT NULL,
|
|
314
|
+
PRIMARY KEY(scope, key)
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
CREATE TABLE IF NOT EXISTS resvary_outbox_events (
|
|
318
|
+
id TEXT PRIMARY KEY,
|
|
319
|
+
project_id TEXT NOT NULL,
|
|
320
|
+
type TEXT NOT NULL,
|
|
321
|
+
status TEXT NOT NULL,
|
|
322
|
+
created_at INTEGER NOT NULL,
|
|
323
|
+
payload TEXT NOT NULL
|
|
324
|
+
);
|
|
325
|
+
CREATE INDEX IF NOT EXISTS resvary_outbox_events_pending
|
|
326
|
+
ON resvary_outbox_events(project_id, status, created_at);
|
|
327
|
+
|
|
328
|
+
INSERT OR IGNORE INTO resvary_schema_migrations(version, applied_at)
|
|
329
|
+
VALUES (1, CAST(strftime('%s', 'now') AS INTEGER) * 1000);
|
|
307
330
|
`);
|
|
308
331
|
this.migrateFundingV2();
|
|
309
332
|
this.migrateOutboxV3();
|
|
310
333
|
this.migrateFundingTransactionHashV4();
|
|
334
|
+
this.migrateCreditLotsV5();
|
|
311
335
|
}
|
|
312
336
|
migrateFundingV2() {
|
|
313
337
|
const row = this.db
|
|
@@ -317,51 +341,51 @@ export class SqliteCreditStore {
|
|
|
317
341
|
return;
|
|
318
342
|
this.db.exec('BEGIN IMMEDIATE;');
|
|
319
343
|
try {
|
|
320
|
-
this.db.exec(`
|
|
321
|
-
ALTER TABLE resvary_funding_transactions
|
|
322
|
-
ADD COLUMN rail TEXT NOT NULL DEFAULT 'arc_direct';
|
|
323
|
-
ALTER TABLE resvary_funding_transactions
|
|
324
|
-
ADD COLUMN external_payment_id_norm TEXT;
|
|
325
|
-
UPDATE resvary_funding_transactions
|
|
326
|
-
SET external_payment_id_norm = tx_hash_norm
|
|
327
|
-
WHERE external_payment_id_norm IS NULL;
|
|
328
|
-
|
|
329
|
-
ALTER TABLE resvary_funding_transactions
|
|
330
|
-
RENAME TO resvary_funding_transactions_v1;
|
|
331
|
-
CREATE TABLE resvary_funding_transactions (
|
|
332
|
-
id TEXT PRIMARY KEY,
|
|
333
|
-
funding_intent_id TEXT NOT NULL,
|
|
334
|
-
rail TEXT NOT NULL,
|
|
335
|
-
network TEXT NOT NULL,
|
|
336
|
-
external_payment_id_norm TEXT NOT NULL,
|
|
337
|
-
tx_hash_norm TEXT,
|
|
338
|
-
created_at INTEGER NOT NULL,
|
|
339
|
-
payload TEXT NOT NULL,
|
|
340
|
-
UNIQUE(rail, network, external_payment_id_norm)
|
|
341
|
-
);
|
|
342
|
-
INSERT INTO resvary_funding_transactions(
|
|
343
|
-
id,
|
|
344
|
-
funding_intent_id,
|
|
345
|
-
rail,
|
|
346
|
-
network,
|
|
347
|
-
external_payment_id_norm,
|
|
348
|
-
tx_hash_norm,
|
|
349
|
-
created_at,
|
|
350
|
-
payload
|
|
351
|
-
)
|
|
352
|
-
SELECT
|
|
353
|
-
id,
|
|
354
|
-
funding_intent_id,
|
|
355
|
-
rail,
|
|
356
|
-
network,
|
|
357
|
-
external_payment_id_norm,
|
|
358
|
-
tx_hash_norm,
|
|
359
|
-
created_at,
|
|
360
|
-
payload
|
|
361
|
-
FROM resvary_funding_transactions_v1;
|
|
362
|
-
DROP TABLE resvary_funding_transactions_v1;
|
|
363
|
-
CREATE INDEX resvary_funding_transactions_tx_hash
|
|
364
|
-
ON resvary_funding_transactions(network, tx_hash_norm);
|
|
344
|
+
this.db.exec(`
|
|
345
|
+
ALTER TABLE resvary_funding_transactions
|
|
346
|
+
ADD COLUMN rail TEXT NOT NULL DEFAULT 'arc_direct';
|
|
347
|
+
ALTER TABLE resvary_funding_transactions
|
|
348
|
+
ADD COLUMN external_payment_id_norm TEXT;
|
|
349
|
+
UPDATE resvary_funding_transactions
|
|
350
|
+
SET external_payment_id_norm = tx_hash_norm
|
|
351
|
+
WHERE external_payment_id_norm IS NULL;
|
|
352
|
+
|
|
353
|
+
ALTER TABLE resvary_funding_transactions
|
|
354
|
+
RENAME TO resvary_funding_transactions_v1;
|
|
355
|
+
CREATE TABLE resvary_funding_transactions (
|
|
356
|
+
id TEXT PRIMARY KEY,
|
|
357
|
+
funding_intent_id TEXT NOT NULL,
|
|
358
|
+
rail TEXT NOT NULL,
|
|
359
|
+
network TEXT NOT NULL,
|
|
360
|
+
external_payment_id_norm TEXT NOT NULL,
|
|
361
|
+
tx_hash_norm TEXT,
|
|
362
|
+
created_at INTEGER NOT NULL,
|
|
363
|
+
payload TEXT NOT NULL,
|
|
364
|
+
UNIQUE(rail, network, external_payment_id_norm)
|
|
365
|
+
);
|
|
366
|
+
INSERT INTO resvary_funding_transactions(
|
|
367
|
+
id,
|
|
368
|
+
funding_intent_id,
|
|
369
|
+
rail,
|
|
370
|
+
network,
|
|
371
|
+
external_payment_id_norm,
|
|
372
|
+
tx_hash_norm,
|
|
373
|
+
created_at,
|
|
374
|
+
payload
|
|
375
|
+
)
|
|
376
|
+
SELECT
|
|
377
|
+
id,
|
|
378
|
+
funding_intent_id,
|
|
379
|
+
rail,
|
|
380
|
+
network,
|
|
381
|
+
external_payment_id_norm,
|
|
382
|
+
tx_hash_norm,
|
|
383
|
+
created_at,
|
|
384
|
+
payload
|
|
385
|
+
FROM resvary_funding_transactions_v1;
|
|
386
|
+
DROP TABLE resvary_funding_transactions_v1;
|
|
387
|
+
CREATE INDEX resvary_funding_transactions_tx_hash
|
|
388
|
+
ON resvary_funding_transactions(network, tx_hash_norm);
|
|
365
389
|
`);
|
|
366
390
|
const intents = this.db
|
|
367
391
|
.prepare('SELECT id, payload FROM resvary_funding_intents')
|
|
@@ -391,10 +415,10 @@ export class SqliteCreditStore {
|
|
|
391
415
|
},
|
|
392
416
|
};
|
|
393
417
|
this.db
|
|
394
|
-
.prepare(`
|
|
395
|
-
UPDATE resvary_funding_transactions
|
|
396
|
-
SET rail = ?, external_payment_id_norm = ?, payload = ?
|
|
397
|
-
WHERE id = ?
|
|
418
|
+
.prepare(`
|
|
419
|
+
UPDATE resvary_funding_transactions
|
|
420
|
+
SET rail = ?, external_payment_id_norm = ?, payload = ?
|
|
421
|
+
WHERE id = ?
|
|
398
422
|
`)
|
|
399
423
|
.run(migrated.rail, migrated.externalPaymentId.toLowerCase(), serializeReceiptStoreValue(migrated), transactionRow.id);
|
|
400
424
|
}
|
|
@@ -416,14 +440,14 @@ export class SqliteCreditStore {
|
|
|
416
440
|
return;
|
|
417
441
|
this.db.exec('BEGIN IMMEDIATE;');
|
|
418
442
|
try {
|
|
419
|
-
this.db.exec(`
|
|
420
|
-
ALTER TABLE resvary_outbox_events ADD COLUMN attempt_count INTEGER NOT NULL DEFAULT 0;
|
|
421
|
-
ALTER TABLE resvary_outbox_events ADD COLUMN next_attempt_at INTEGER NOT NULL DEFAULT 0;
|
|
422
|
-
ALTER TABLE resvary_outbox_events ADD COLUMN lease_owner TEXT;
|
|
423
|
-
ALTER TABLE resvary_outbox_events ADD COLUMN lease_expires_at INTEGER;
|
|
424
|
-
DROP INDEX IF EXISTS resvary_outbox_events_pending;
|
|
425
|
-
CREATE INDEX resvary_outbox_events_due
|
|
426
|
-
ON resvary_outbox_events(project_id, status, next_attempt_at, created_at);
|
|
443
|
+
this.db.exec(`
|
|
444
|
+
ALTER TABLE resvary_outbox_events ADD COLUMN attempt_count INTEGER NOT NULL DEFAULT 0;
|
|
445
|
+
ALTER TABLE resvary_outbox_events ADD COLUMN next_attempt_at INTEGER NOT NULL DEFAULT 0;
|
|
446
|
+
ALTER TABLE resvary_outbox_events ADD COLUMN lease_owner TEXT;
|
|
447
|
+
ALTER TABLE resvary_outbox_events ADD COLUMN lease_expires_at INTEGER;
|
|
448
|
+
DROP INDEX IF EXISTS resvary_outbox_events_pending;
|
|
449
|
+
CREATE INDEX resvary_outbox_events_due
|
|
450
|
+
ON resvary_outbox_events(project_id, status, next_attempt_at, created_at);
|
|
427
451
|
`);
|
|
428
452
|
const rows = this.db
|
|
429
453
|
.prepare('SELECT id, created_at, payload FROM resvary_outbox_events')
|
|
@@ -436,8 +460,8 @@ export class SqliteCreditStore {
|
|
|
436
460
|
nextAttemptAt: event.nextAttemptAt ?? item.created_at,
|
|
437
461
|
};
|
|
438
462
|
this.db
|
|
439
|
-
.prepare(`UPDATE resvary_outbox_events
|
|
440
|
-
SET attempt_count = ?, next_attempt_at = ?, lease_owner = ?, lease_expires_at = ?, payload = ?
|
|
463
|
+
.prepare(`UPDATE resvary_outbox_events
|
|
464
|
+
SET attempt_count = ?, next_attempt_at = ?, lease_owner = ?, lease_expires_at = ?, payload = ?
|
|
441
465
|
WHERE id = ?`)
|
|
442
466
|
.run(migrated.attemptCount, migrated.nextAttemptAt, migrated.leaseOwner ?? null, migrated.leaseExpiresAt ?? null, serializeReceiptStoreValue(migrated), item.id);
|
|
443
467
|
}
|
|
@@ -460,21 +484,21 @@ export class SqliteCreditStore {
|
|
|
460
484
|
this.db.exec('BEGIN IMMEDIATE;');
|
|
461
485
|
try {
|
|
462
486
|
const duplicate = this.db
|
|
463
|
-
.prepare(`SELECT network, tx_hash_norm, COUNT(*) AS count
|
|
464
|
-
FROM resvary_funding_transactions
|
|
465
|
-
WHERE tx_hash_norm IS NOT NULL
|
|
466
|
-
GROUP BY network, tx_hash_norm
|
|
467
|
-
HAVING COUNT(*) > 1
|
|
487
|
+
.prepare(`SELECT network, tx_hash_norm, COUNT(*) AS count
|
|
488
|
+
FROM resvary_funding_transactions
|
|
489
|
+
WHERE tx_hash_norm IS NOT NULL
|
|
490
|
+
GROUP BY network, tx_hash_norm
|
|
491
|
+
HAVING COUNT(*) > 1
|
|
468
492
|
LIMIT 1`)
|
|
469
493
|
.get();
|
|
470
494
|
if (duplicate) {
|
|
471
495
|
throw new Error(`Cannot migrate SQLite funding transaction uniqueness: ${duplicate.count} records use ${duplicate.network}:${duplicate.tx_hash_norm}`);
|
|
472
496
|
}
|
|
473
|
-
this.db.exec(`
|
|
474
|
-
DROP INDEX IF EXISTS resvary_funding_transactions_tx_hash;
|
|
475
|
-
CREATE UNIQUE INDEX resvary_funding_transactions_tx_hash
|
|
476
|
-
ON resvary_funding_transactions(network, tx_hash_norm)
|
|
477
|
-
WHERE tx_hash_norm IS NOT NULL;
|
|
497
|
+
this.db.exec(`
|
|
498
|
+
DROP INDEX IF EXISTS resvary_funding_transactions_tx_hash;
|
|
499
|
+
CREATE UNIQUE INDEX resvary_funding_transactions_tx_hash
|
|
500
|
+
ON resvary_funding_transactions(network, tx_hash_norm)
|
|
501
|
+
WHERE tx_hash_norm IS NOT NULL;
|
|
478
502
|
`);
|
|
479
503
|
this.db
|
|
480
504
|
.prepare('INSERT INTO resvary_schema_migrations(version, applied_at) VALUES (4, ?)')
|
|
@@ -486,6 +510,176 @@ export class SqliteCreditStore {
|
|
|
486
510
|
throw error;
|
|
487
511
|
}
|
|
488
512
|
}
|
|
513
|
+
migrateCreditLotsV5() {
|
|
514
|
+
const row = this.db
|
|
515
|
+
.prepare('SELECT MAX(version) AS version FROM resvary_schema_migrations')
|
|
516
|
+
.get();
|
|
517
|
+
if ((row?.version ?? 0) >= 5)
|
|
518
|
+
return;
|
|
519
|
+
this.db.exec('BEGIN IMMEDIATE;');
|
|
520
|
+
try {
|
|
521
|
+
this.db.exec(`
|
|
522
|
+
CREATE TABLE resvary_grant_policies (
|
|
523
|
+
id TEXT PRIMARY KEY,
|
|
524
|
+
project_id TEXT NOT NULL,
|
|
525
|
+
policy_key TEXT NOT NULL,
|
|
526
|
+
version INTEGER NOT NULL,
|
|
527
|
+
created_at INTEGER NOT NULL,
|
|
528
|
+
payload TEXT NOT NULL,
|
|
529
|
+
UNIQUE(project_id, policy_key, version)
|
|
530
|
+
);
|
|
531
|
+
CREATE INDEX resvary_grant_policies_project
|
|
532
|
+
ON resvary_grant_policies(project_id, created_at);
|
|
533
|
+
|
|
534
|
+
CREATE TABLE resvary_credit_lots (
|
|
535
|
+
id TEXT PRIMARY KEY,
|
|
536
|
+
account_id TEXT NOT NULL,
|
|
537
|
+
project_id TEXT NOT NULL,
|
|
538
|
+
customer_id TEXT NOT NULL,
|
|
539
|
+
kind TEXT NOT NULL,
|
|
540
|
+
policy_id TEXT,
|
|
541
|
+
expires_at INTEGER,
|
|
542
|
+
created_at INTEGER NOT NULL,
|
|
543
|
+
payload TEXT NOT NULL
|
|
544
|
+
);
|
|
545
|
+
CREATE INDEX resvary_credit_lots_account
|
|
546
|
+
ON resvary_credit_lots(account_id, created_at);
|
|
547
|
+
CREATE INDEX resvary_credit_lots_expiry
|
|
548
|
+
ON resvary_credit_lots(project_id, expires_at)
|
|
549
|
+
WHERE expires_at IS NOT NULL;
|
|
550
|
+
|
|
551
|
+
CREATE TABLE resvary_credit_lot_allocations (
|
|
552
|
+
id TEXT PRIMARY KEY,
|
|
553
|
+
reservation_id TEXT NOT NULL,
|
|
554
|
+
lot_id TEXT NOT NULL,
|
|
555
|
+
account_id TEXT NOT NULL,
|
|
556
|
+
created_at INTEGER NOT NULL,
|
|
557
|
+
payload TEXT NOT NULL,
|
|
558
|
+
UNIQUE(reservation_id, lot_id)
|
|
559
|
+
);
|
|
560
|
+
CREATE INDEX resvary_credit_lot_allocations_reservation
|
|
561
|
+
ON resvary_credit_lot_allocations(reservation_id, created_at);
|
|
562
|
+
|
|
563
|
+
CREATE TABLE resvary_grant_policy_applications (
|
|
564
|
+
id TEXT PRIMARY KEY,
|
|
565
|
+
policy_id TEXT NOT NULL,
|
|
566
|
+
account_id TEXT NOT NULL,
|
|
567
|
+
project_id TEXT NOT NULL,
|
|
568
|
+
customer_id TEXT NOT NULL,
|
|
569
|
+
policy_type TEXT NOT NULL,
|
|
570
|
+
period_key TEXT NOT NULL,
|
|
571
|
+
created_at INTEGER NOT NULL,
|
|
572
|
+
payload TEXT NOT NULL,
|
|
573
|
+
UNIQUE(policy_id, account_id, period_key)
|
|
574
|
+
);
|
|
575
|
+
CREATE INDEX resvary_grant_policy_applications_customer
|
|
576
|
+
ON resvary_grant_policy_applications(project_id, customer_id, created_at);
|
|
577
|
+
`);
|
|
578
|
+
const accounts = this.db
|
|
579
|
+
.prepare('SELECT payload FROM resvary_credit_accounts ORDER BY id')
|
|
580
|
+
.all();
|
|
581
|
+
for (const accountRow of accounts) {
|
|
582
|
+
const account = parseReceiptStoreValue(accountRow.payload);
|
|
583
|
+
const posted = parseCreditUnits(account.postedUnits);
|
|
584
|
+
const reserved = parseCreditUnits(account.reservedUnits);
|
|
585
|
+
if (reserved > posted) {
|
|
586
|
+
throw new Error(`Cannot migrate SQLite credit lots: account invariant failed for ${account.id}`);
|
|
587
|
+
}
|
|
588
|
+
const reservations = this.db
|
|
589
|
+
.prepare(`SELECT payload FROM resvary_credit_reservations
|
|
590
|
+
WHERE account_id = ? AND status = 'open' ORDER BY created_at, id`)
|
|
591
|
+
.all(account.id);
|
|
592
|
+
const open = reservations.map((item) => parseReceiptStoreValue(item.payload));
|
|
593
|
+
const reservationTotal = open.reduce((total, reservation) => total + parseCreditUnits(reservation.reservedUnits), 0n);
|
|
594
|
+
if (reservationTotal !== reserved) {
|
|
595
|
+
throw new Error(`Cannot migrate SQLite credit lots: open reservations do not match account ${account.id}`);
|
|
596
|
+
}
|
|
597
|
+
if (posted === 0n)
|
|
598
|
+
continue;
|
|
599
|
+
const lotId = `lot_legacy_${account.id}`;
|
|
600
|
+
const available = posted - reserved;
|
|
601
|
+
const lot = {
|
|
602
|
+
id: lotId,
|
|
603
|
+
accountId: account.id,
|
|
604
|
+
projectId: account.projectId,
|
|
605
|
+
customerId: account.customerId,
|
|
606
|
+
kind: 'legacy',
|
|
607
|
+
originalAmount: creditUnitsToString(posted),
|
|
608
|
+
originalUnits: posted.toString(),
|
|
609
|
+
availableAmount: creditUnitsToString(available),
|
|
610
|
+
availableUnits: available.toString(),
|
|
611
|
+
reservedAmount: creditUnitsToString(reserved),
|
|
612
|
+
reservedUnits: reserved.toString(),
|
|
613
|
+
consumedAmount: '0',
|
|
614
|
+
consumedUnits: '0',
|
|
615
|
+
expiredAmount: '0',
|
|
616
|
+
expiredUnits: '0',
|
|
617
|
+
createdAt: account.createdAt,
|
|
618
|
+
updatedAt: account.updatedAt,
|
|
619
|
+
metadata: { migratedFrom: 'sqlite-v4' },
|
|
620
|
+
};
|
|
621
|
+
insert(this.db, 'resvary_credit_lots', [
|
|
622
|
+
'id',
|
|
623
|
+
'account_id',
|
|
624
|
+
'project_id',
|
|
625
|
+
'customer_id',
|
|
626
|
+
'kind',
|
|
627
|
+
'policy_id',
|
|
628
|
+
'expires_at',
|
|
629
|
+
'created_at',
|
|
630
|
+
], [
|
|
631
|
+
lot.id,
|
|
632
|
+
lot.accountId,
|
|
633
|
+
lot.projectId,
|
|
634
|
+
lot.customerId,
|
|
635
|
+
lot.kind,
|
|
636
|
+
null,
|
|
637
|
+
null,
|
|
638
|
+
lot.createdAt,
|
|
639
|
+
], lot);
|
|
640
|
+
for (const reservation of open) {
|
|
641
|
+
const units = parseCreditUnits(reservation.reservedUnits);
|
|
642
|
+
if (units === 0n)
|
|
643
|
+
continue;
|
|
644
|
+
const allocation = {
|
|
645
|
+
id: `cla_legacy_${reservation.id}`,
|
|
646
|
+
reservationId: reservation.id,
|
|
647
|
+
lotId,
|
|
648
|
+
accountId: account.id,
|
|
649
|
+
projectId: account.projectId,
|
|
650
|
+
customerId: account.customerId,
|
|
651
|
+
allocatedAmount: creditUnitsToString(units),
|
|
652
|
+
allocatedUnits: units.toString(),
|
|
653
|
+
reservedAmount: creditUnitsToString(units),
|
|
654
|
+
reservedUnits: units.toString(),
|
|
655
|
+
consumedAmount: '0',
|
|
656
|
+
consumedUnits: '0',
|
|
657
|
+
releasedAmount: '0',
|
|
658
|
+
releasedUnits: '0',
|
|
659
|
+
expiredAmount: '0',
|
|
660
|
+
expiredUnits: '0',
|
|
661
|
+
createdAt: reservation.createdAt,
|
|
662
|
+
updatedAt: account.updatedAt,
|
|
663
|
+
};
|
|
664
|
+
insert(this.db, 'resvary_credit_lot_allocations', ['id', 'reservation_id', 'lot_id', 'account_id', 'created_at'], [
|
|
665
|
+
allocation.id,
|
|
666
|
+
allocation.reservationId,
|
|
667
|
+
allocation.lotId,
|
|
668
|
+
allocation.accountId,
|
|
669
|
+
allocation.createdAt,
|
|
670
|
+
], allocation);
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
this.db
|
|
674
|
+
.prepare('INSERT INTO resvary_schema_migrations(version, applied_at) VALUES (5, ?)')
|
|
675
|
+
.run(Date.now());
|
|
676
|
+
this.db.exec('COMMIT;');
|
|
677
|
+
}
|
|
678
|
+
catch (error) {
|
|
679
|
+
this.db.exec('ROLLBACK;');
|
|
680
|
+
throw error;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
489
683
|
}
|
|
490
684
|
class SqliteCreditTransaction {
|
|
491
685
|
db;
|
|
@@ -564,6 +758,30 @@ class SqliteCreditTransaction {
|
|
|
564
758
|
listFundingTransactions(fundingIntentId) {
|
|
565
759
|
return reader(this.db).listFundingTransactions(fundingIntentId);
|
|
566
760
|
}
|
|
761
|
+
getGrantPolicy(id) {
|
|
762
|
+
return reader(this.db).getGrantPolicy(id);
|
|
763
|
+
}
|
|
764
|
+
listGrantPolicies(projectId) {
|
|
765
|
+
return reader(this.db).listGrantPolicies(projectId);
|
|
766
|
+
}
|
|
767
|
+
getCreditLot(id) {
|
|
768
|
+
return reader(this.db).getCreditLot(id);
|
|
769
|
+
}
|
|
770
|
+
listCreditLots(filter) {
|
|
771
|
+
return reader(this.db).listCreditLots(filter);
|
|
772
|
+
}
|
|
773
|
+
listCreditLotAllocations(reservationId) {
|
|
774
|
+
return reader(this.db).listCreditLotAllocations(reservationId);
|
|
775
|
+
}
|
|
776
|
+
getGrantPolicyApplication(id) {
|
|
777
|
+
return reader(this.db).getGrantPolicyApplication(id);
|
|
778
|
+
}
|
|
779
|
+
getGrantPolicyApplicationByIdentity(policyId, accountId, periodKey) {
|
|
780
|
+
return reader(this.db).getGrantPolicyApplicationByIdentity(policyId, accountId, periodKey);
|
|
781
|
+
}
|
|
782
|
+
listGrantPolicyApplications(filter) {
|
|
783
|
+
return reader(this.db).listGrantPolicyApplications(filter);
|
|
784
|
+
}
|
|
567
785
|
async saveAccount(value) {
|
|
568
786
|
upsert(this.db, 'resvary_credit_accounts', ['id', 'project_id', 'customer_id', 'updated_at'], [value.id, value.projectId, value.customerId, value.updatedAt], value);
|
|
569
787
|
}
|
|
@@ -644,6 +862,54 @@ class SqliteCreditTransaction {
|
|
|
644
862
|
value.createdAt,
|
|
645
863
|
], value);
|
|
646
864
|
}
|
|
865
|
+
async saveGrantPolicy(value) {
|
|
866
|
+
insert(this.db, 'resvary_grant_policies', ['id', 'project_id', 'policy_key', 'version', 'created_at'], [value.id, value.projectId, value.key, value.version, value.createdAt], value);
|
|
867
|
+
}
|
|
868
|
+
async saveCreditLot(value) {
|
|
869
|
+
upsert(this.db, 'resvary_credit_lots', [
|
|
870
|
+
'id',
|
|
871
|
+
'account_id',
|
|
872
|
+
'project_id',
|
|
873
|
+
'customer_id',
|
|
874
|
+
'kind',
|
|
875
|
+
'policy_id',
|
|
876
|
+
'expires_at',
|
|
877
|
+
'created_at',
|
|
878
|
+
], [
|
|
879
|
+
value.id,
|
|
880
|
+
value.accountId,
|
|
881
|
+
value.projectId,
|
|
882
|
+
value.customerId,
|
|
883
|
+
value.kind,
|
|
884
|
+
value.policyId ?? null,
|
|
885
|
+
value.expiresAt ?? null,
|
|
886
|
+
value.createdAt,
|
|
887
|
+
], value);
|
|
888
|
+
}
|
|
889
|
+
async saveCreditLotAllocation(value) {
|
|
890
|
+
upsert(this.db, 'resvary_credit_lot_allocations', ['id', 'reservation_id', 'lot_id', 'account_id', 'created_at'], [value.id, value.reservationId, value.lotId, value.accountId, value.createdAt], value);
|
|
891
|
+
}
|
|
892
|
+
async saveGrantPolicyApplication(value) {
|
|
893
|
+
insert(this.db, 'resvary_grant_policy_applications', [
|
|
894
|
+
'id',
|
|
895
|
+
'policy_id',
|
|
896
|
+
'account_id',
|
|
897
|
+
'project_id',
|
|
898
|
+
'customer_id',
|
|
899
|
+
'policy_type',
|
|
900
|
+
'period_key',
|
|
901
|
+
'created_at',
|
|
902
|
+
], [
|
|
903
|
+
value.id,
|
|
904
|
+
value.policyId,
|
|
905
|
+
value.accountId,
|
|
906
|
+
value.projectId,
|
|
907
|
+
value.customerId,
|
|
908
|
+
value.policyType,
|
|
909
|
+
value.periodKey,
|
|
910
|
+
value.createdAt,
|
|
911
|
+
], value);
|
|
912
|
+
}
|
|
647
913
|
}
|
|
648
914
|
function reader(db) {
|
|
649
915
|
return {
|
|
@@ -729,7 +995,7 @@ function reader(db) {
|
|
|
729
995
|
return one(db, 'SELECT payload FROM resvary_funding_transactions WHERE id = ?', [id]);
|
|
730
996
|
},
|
|
731
997
|
async getFundingTransactionByExternalPayment(rail, network, externalPaymentId) {
|
|
732
|
-
return one(db, `SELECT payload FROM resvary_funding_transactions
|
|
998
|
+
return one(db, `SELECT payload FROM resvary_funding_transactions
|
|
733
999
|
WHERE rail = ? AND network = ? AND external_payment_id_norm = ?`, [rail, network, externalPaymentId.toLowerCase()]);
|
|
734
1000
|
},
|
|
735
1001
|
async getFundingTransactionByTxHash(network, txHash) {
|
|
@@ -740,6 +1006,44 @@ function reader(db) {
|
|
|
740
1006
|
? all(db, 'SELECT payload FROM resvary_funding_transactions WHERE funding_intent_id = ? ORDER BY created_at ASC', [fundingIntentId])
|
|
741
1007
|
: all(db, 'SELECT payload FROM resvary_funding_transactions ORDER BY created_at ASC');
|
|
742
1008
|
},
|
|
1009
|
+
async getGrantPolicy(id) {
|
|
1010
|
+
return one(db, 'SELECT payload FROM resvary_grant_policies WHERE id = ?', [
|
|
1011
|
+
id,
|
|
1012
|
+
]);
|
|
1013
|
+
},
|
|
1014
|
+
async listGrantPolicies(projectId) {
|
|
1015
|
+
return projectId
|
|
1016
|
+
? all(db, 'SELECT payload FROM resvary_grant_policies WHERE project_id = ? ORDER BY created_at, version', [projectId])
|
|
1017
|
+
: all(db, 'SELECT payload FROM resvary_grant_policies ORDER BY created_at, version');
|
|
1018
|
+
},
|
|
1019
|
+
async getCreditLot(id) {
|
|
1020
|
+
return one(db, 'SELECT payload FROM resvary_credit_lots WHERE id = ?', [id]);
|
|
1021
|
+
},
|
|
1022
|
+
async listCreditLots(filter = {}) {
|
|
1023
|
+
return all(db, 'SELECT payload FROM resvary_credit_lots ORDER BY created_at, id').filter((item) => matchesBalanceFilter(item, filter) &&
|
|
1024
|
+
(!filter.policyId || item.policyId === filter.policyId) &&
|
|
1025
|
+
(!filter.kind || item.kind === filter.kind) &&
|
|
1026
|
+
(filter.expiresBefore === undefined ||
|
|
1027
|
+
(item.expiresAt !== undefined && item.expiresAt <= filter.expiresBefore)));
|
|
1028
|
+
},
|
|
1029
|
+
async listCreditLotAllocations(reservationId) {
|
|
1030
|
+
return reservationId
|
|
1031
|
+
? all(db, 'SELECT payload FROM resvary_credit_lot_allocations WHERE reservation_id = ? ORDER BY created_at, id', [reservationId])
|
|
1032
|
+
: all(db, 'SELECT payload FROM resvary_credit_lot_allocations ORDER BY created_at, id');
|
|
1033
|
+
},
|
|
1034
|
+
async getGrantPolicyApplication(id) {
|
|
1035
|
+
return one(db, 'SELECT payload FROM resvary_grant_policy_applications WHERE id = ?', [id]);
|
|
1036
|
+
},
|
|
1037
|
+
async getGrantPolicyApplicationByIdentity(policyId, accountId, periodKey) {
|
|
1038
|
+
return one(db, `SELECT payload FROM resvary_grant_policy_applications
|
|
1039
|
+
WHERE policy_id = ? AND account_id = ? AND period_key = ?`, [policyId, accountId, periodKey]);
|
|
1040
|
+
},
|
|
1041
|
+
async listGrantPolicyApplications(filter = {}) {
|
|
1042
|
+
return all(db, 'SELECT payload FROM resvary_grant_policy_applications ORDER BY created_at, id').filter((item) => matchesBalanceFilter(item, filter) &&
|
|
1043
|
+
(!filter.policyId || item.policyId === filter.policyId) &&
|
|
1044
|
+
(!filter.policyType || item.policyType === filter.policyType) &&
|
|
1045
|
+
(!filter.periodKey || item.periodKey === filter.periodKey));
|
|
1046
|
+
},
|
|
743
1047
|
};
|
|
744
1048
|
}
|
|
745
1049
|
function insert(db, table, columns, values, payload, conflictColumns = ['id']) {
|