@nestjs-dash/wallet 0.1.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.
Files changed (81) hide show
  1. package/dist/cli.d.ts +3 -0
  2. package/dist/cli.d.ts.map +1 -0
  3. package/dist/cli.js +95 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/entities/transaction.entity.d.ts +18 -0
  6. package/dist/entities/transaction.entity.d.ts.map +1 -0
  7. package/dist/entities/transaction.entity.js +68 -0
  8. package/dist/entities/transaction.entity.js.map +1 -0
  9. package/dist/entities/transfer.entity.d.ts +23 -0
  10. package/dist/entities/transfer.entity.d.ts.map +1 -0
  11. package/dist/entities/transfer.entity.js +97 -0
  12. package/dist/entities/transfer.entity.js.map +1 -0
  13. package/dist/entities/wallet.entity.d.ts +16 -0
  14. package/dist/entities/wallet.entity.d.ts.map +1 -0
  15. package/dist/entities/wallet.entity.js +67 -0
  16. package/dist/entities/wallet.entity.js.map +1 -0
  17. package/dist/errors.d.ts +13 -0
  18. package/dist/errors.d.ts.map +1 -0
  19. package/dist/errors.js +25 -0
  20. package/dist/errors.js.map +1 -0
  21. package/dist/events/wallet-event.publisher.d.ts +12 -0
  22. package/dist/events/wallet-event.publisher.d.ts.map +1 -0
  23. package/dist/events/wallet-event.publisher.js +44 -0
  24. package/dist/events/wallet-event.publisher.js.map +1 -0
  25. package/dist/events/wallet.events.d.ts +22 -0
  26. package/dist/events/wallet.events.d.ts.map +1 -0
  27. package/dist/events/wallet.events.js +2 -0
  28. package/dist/events/wallet.events.js.map +1 -0
  29. package/dist/exchange.service.d.ts +17 -0
  30. package/dist/exchange.service.d.ts.map +1 -0
  31. package/dist/exchange.service.js +70 -0
  32. package/dist/exchange.service.js.map +1 -0
  33. package/dist/float-wallet.service.d.ts +11 -0
  34. package/dist/float-wallet.service.d.ts.map +1 -0
  35. package/dist/float-wallet.service.js +33 -0
  36. package/dist/float-wallet.service.js.map +1 -0
  37. package/dist/index.d.ts +20 -0
  38. package/dist/index.d.ts.map +1 -0
  39. package/dist/index.js +18 -0
  40. package/dist/index.js.map +1 -0
  41. package/dist/lock/array-lock.service.d.ts +8 -0
  42. package/dist/lock/array-lock.service.d.ts.map +1 -0
  43. package/dist/lock/array-lock.service.js +60 -0
  44. package/dist/lock/array-lock.service.js.map +1 -0
  45. package/dist/lock/lock.service.d.ts +5 -0
  46. package/dist/lock/lock.service.d.ts.map +1 -0
  47. package/dist/lock/lock.service.js +4 -0
  48. package/dist/lock/lock.service.js.map +1 -0
  49. package/dist/lock/memcached-lock.service.d.ts +21 -0
  50. package/dist/lock/memcached-lock.service.d.ts.map +1 -0
  51. package/dist/lock/memcached-lock.service.js +45 -0
  52. package/dist/lock/memcached-lock.service.js.map +1 -0
  53. package/dist/lock/redis-lock.service.d.ts +13 -0
  54. package/dist/lock/redis-lock.service.d.ts.map +1 -0
  55. package/dist/lock/redis-lock.service.js +43 -0
  56. package/dist/lock/redis-lock.service.js.map +1 -0
  57. package/dist/migrations/generate.d.ts +22 -0
  58. package/dist/migrations/generate.d.ts.map +1 -0
  59. package/dist/migrations/generate.js +226 -0
  60. package/dist/migrations/generate.js.map +1 -0
  61. package/dist/tokens.d.ts +56 -0
  62. package/dist/tokens.d.ts.map +1 -0
  63. package/dist/tokens.js +13 -0
  64. package/dist/tokens.js.map +1 -0
  65. package/dist/transfer.service.d.ts +29 -0
  66. package/dist/transfer.service.d.ts.map +1 -0
  67. package/dist/transfer.service.js +154 -0
  68. package/dist/transfer.service.js.map +1 -0
  69. package/dist/wallet.module.d.ts +12 -0
  70. package/dist/wallet.module.d.ts.map +1 -0
  71. package/dist/wallet.module.js +150 -0
  72. package/dist/wallet.module.js.map +1 -0
  73. package/dist/wallet.service.d.ts +39 -0
  74. package/dist/wallet.service.d.ts.map +1 -0
  75. package/dist/wallet.service.js +230 -0
  76. package/dist/wallet.service.js.map +1 -0
  77. package/dist/warmup.service.d.ts +13 -0
  78. package/dist/warmup.service.d.ts.map +1 -0
  79. package/dist/warmup.service.js +76 -0
  80. package/dist/warmup.service.js.map +1 -0
  81. package/package.json +69 -0
@@ -0,0 +1,70 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
11
+ return function (target, key) { decorator(target, key, paramIndex); }
12
+ };
13
+ import { Inject, Injectable } from '@nestjs/common';
14
+ import { ExchangeRateNotFoundError } from './errors.js';
15
+ import { WALLET_OPTIONS } from './tokens.js';
16
+ import { TransferService } from './transfer.service.js';
17
+ import { WalletService } from './wallet.service.js';
18
+ let ExchangeService = class ExchangeService {
19
+ constructor(transfers, wallets, options) {
20
+ this.transfers = transfers;
21
+ this.wallets = wallets;
22
+ this.rates = structuredClone(options.exchange?.rates ?? {});
23
+ }
24
+ setExchangeRate(fromCurrency, toCurrency, rate) {
25
+ if (!this.rates[fromCurrency])
26
+ this.rates[fromCurrency] = {};
27
+ this.rates[fromCurrency][toCurrency] = rate;
28
+ }
29
+ getExchangeRate(fromCurrency, toCurrency) {
30
+ if (fromCurrency === toCurrency)
31
+ return 1;
32
+ const rate = this.rates[fromCurrency]?.[toCurrency];
33
+ if (rate == null) {
34
+ throw new ExchangeRateNotFoundError(`No rate for ${fromCurrency} → ${toCurrency}`);
35
+ }
36
+ return rate;
37
+ }
38
+ currencyOf(wallet) {
39
+ const meta = wallet.meta ?? {};
40
+ const currency = meta.currency;
41
+ if (typeof currency !== 'string' || !currency) {
42
+ throw new ExchangeRateNotFoundError(`Wallet ${wallet.id} has no meta.currency`);
43
+ }
44
+ return currency;
45
+ }
46
+ async exchange(from, to, amount, explicitRate) {
47
+ const fromCurrency = this.currencyOf(from);
48
+ const toCurrency = this.currencyOf(to);
49
+ const rate = explicitRate ?? this.getExchangeRate(fromCurrency, toCurrency);
50
+ const withdrawAmount = this.wallets.normalizeAmount(amount);
51
+ const depositAmount = BigInt(Math.round(Number(withdrawAmount) * rate));
52
+ return this.transfers.transfer(from, to, withdrawAmount.toString(), {
53
+ depositAmount: depositAmount.toString(),
54
+ status: 'exchange',
55
+ extra: { rate, fromCurrency, toCurrency },
56
+ });
57
+ }
58
+ async exchangeFloat(from, to, amount, explicitRate) {
59
+ const intAmount = this.wallets.floatToInt(amount, from.decimalPlaces);
60
+ return this.exchange(from, to, intAmount.toString(), explicitRate);
61
+ }
62
+ };
63
+ ExchangeService = __decorate([
64
+ Injectable(),
65
+ __param(2, Inject(WALLET_OPTIONS)),
66
+ __metadata("design:paramtypes", [TransferService,
67
+ WalletService, Object])
68
+ ], ExchangeService);
69
+ export { ExchangeService };
70
+ //# sourceMappingURL=exchange.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"exchange.service.js","sourceRoot":"","sources":["../src/exchange.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { TransactionEntity } from './entities/transaction.entity.js';
2
+ import type { WalletEntity } from './entities/wallet.entity.js';
3
+ import { WalletService } from './wallet.service.js';
4
+ export declare class FloatWalletService {
5
+ private readonly wallets;
6
+ constructor(wallets: WalletService);
7
+ balanceFloat(wallet: WalletEntity): number;
8
+ depositFloat(wallet: WalletEntity, amount: number, meta?: Record<string, unknown> | null): Promise<TransactionEntity>;
9
+ withdrawFloat(wallet: WalletEntity, amount: number, meta?: Record<string, unknown> | null): Promise<TransactionEntity>;
10
+ }
11
+ //# sourceMappingURL=float-wallet.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"float-wallet.service.d.ts","sourceRoot":"","sources":["../src/float-wallet.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,kCAAkC,CAAC;AAC1E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEpD,qBACa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,OAAO;gBAAP,OAAO,EAAE,aAAa;IAEnD,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM;IAIpC,YAAY,CAChB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAC1C,OAAO,CAAC,iBAAiB,CAAC;IAKvB,aAAa,CACjB,MAAM,EAAE,YAAY,EACpB,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAW,GAC1C,OAAO,CAAC,iBAAiB,CAAC;CAI9B"}
@@ -0,0 +1,33 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ var __metadata = (this && this.__metadata) || function (k, v) {
8
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
9
+ };
10
+ import { Injectable } from '@nestjs/common';
11
+ import { WalletService } from './wallet.service.js';
12
+ let FloatWalletService = class FloatWalletService {
13
+ constructor(wallets) {
14
+ this.wallets = wallets;
15
+ }
16
+ balanceFloat(wallet) {
17
+ return this.wallets.intToFloat(wallet.balance, wallet.decimalPlaces);
18
+ }
19
+ async depositFloat(wallet, amount, meta = null) {
20
+ const intAmount = this.wallets.floatToInt(amount, wallet.decimalPlaces);
21
+ return this.wallets.deposit(wallet, intAmount.toString(), meta);
22
+ }
23
+ async withdrawFloat(wallet, amount, meta = null) {
24
+ const intAmount = this.wallets.floatToInt(amount, wallet.decimalPlaces);
25
+ return this.wallets.withdraw(wallet, intAmount.toString(), meta);
26
+ }
27
+ };
28
+ FloatWalletService = __decorate([
29
+ Injectable(),
30
+ __metadata("design:paramtypes", [WalletService])
31
+ ], FloatWalletService);
32
+ export { FloatWalletService };
33
+ //# sourceMappingURL=float-wallet.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"float-wallet.service.js","sourceRoot":"","sources":["../src/float-wallet.service.ts"],"names":[],"mappings":";;;;;;;;;AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAG5C,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAG7C,IAAM,kBAAkB,GAAxB,MAAM,kBAAkB;IAC7B,YAA6B,OAAsB;QAAtB,YAAO,GAAP,OAAO,CAAe;IAAG,CAAC;IAEvD,YAAY,CAAC,MAAoB;QAC/B,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;IACvE,CAAC;IAED,KAAK,CAAC,YAAY,CAChB,MAAoB,EACpB,MAAc,EACd,OAAuC,IAAI;QAE3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;IAClE,CAAC;IAED,KAAK,CAAC,aAAa,CACjB,MAAoB,EACpB,MAAc,EACd,OAAuC,IAAI;QAE3C,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,MAAM,EAAE,MAAM,CAAC,aAAa,CAAC,CAAC;QACxE,OAAO,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,MAAM,EAAE,SAAS,CAAC,QAAQ,EAAE,EAAE,IAAI,CAAC,CAAC;IACnE,CAAC;CACF,CAAA;AAxBY,kBAAkB;IAD9B,UAAU,EAAE;qCAE2B,aAAa;GADxC,kBAAkB,CAwB9B"}
@@ -0,0 +1,20 @@
1
+ export { WalletModule, type WalletModuleAsyncOptions } from './wallet.module.js';
2
+ export { WalletService, type CreateWalletInput } from './wallet.service.js';
3
+ export { FloatWalletService } from './float-wallet.service.js';
4
+ export { TransferService, type TransferOptions } from './transfer.service.js';
5
+ export { ExchangeService } from './exchange.service.js';
6
+ export { WarmupService } from './warmup.service.js';
7
+ export { WalletEntity } from './entities/wallet.entity.js';
8
+ export { TransactionEntity, type TransactionType } from './entities/transaction.entity.js';
9
+ export { TransferEntity, type TransferStatus } from './entities/transfer.entity.js';
10
+ export { WalletEventPublisher } from './events/wallet-event.publisher.js';
11
+ export type { WalletCreatedEventPayload, TransactionCreatedEventPayload, BalanceUpdatedEventPayload, } from './events/wallet.events.js';
12
+ export { ArrayLockService } from './lock/array-lock.service.js';
13
+ export { RedisLockService } from './lock/redis-lock.service.js';
14
+ export { MemcachedLockService } from './lock/memcached-lock.service.js';
15
+ export type { WalletLockService } from './lock/lock.service.js';
16
+ export { walletLockKey } from './lock/lock.service.js';
17
+ export { InsufficientFundsError, WalletNotFoundError, WalletLockTimeoutError, ExchangeRateNotFoundError, } from './errors.js';
18
+ export { WALLET_OPTIONS, WALLET_LOCK, WALLET_DATA_SOURCE, WALLET_EVENT, DEFAULT_WALLET_SLUG, DEFAULT_WALLET_NAME, DEFAULT_LOCK_TTL_MS, type WalletModuleOptions, type WalletDataSourceLike, type WalletTableNames, type WalletLockOptions, type HolderId, type HolderIdType, type LockDriver, } from './tokens.js';
19
+ export { generateMigrationFiles, listMigrationSpecs, resolveTables, DEFAULT_TABLES, type MigrationTableNames, } from './migrations/generate.js';
20
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAE,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAE,KAAK,cAAc,EAAE,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAC1E,YAAY,EACV,yBAAyB,EACzB,8BAA8B,EAC9B,0BAA0B,GAC3B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AACxE,YAAY,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,EACnB,KAAK,mBAAmB,EACxB,KAAK,oBAAoB,EACzB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,QAAQ,EACb,KAAK,YAAY,EACjB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,cAAc,EACd,KAAK,mBAAmB,GACzB,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,18 @@
1
+ export { WalletModule } from './wallet.module.js';
2
+ export { WalletService } from './wallet.service.js';
3
+ export { FloatWalletService } from './float-wallet.service.js';
4
+ export { TransferService } from './transfer.service.js';
5
+ export { ExchangeService } from './exchange.service.js';
6
+ export { WarmupService } from './warmup.service.js';
7
+ export { WalletEntity } from './entities/wallet.entity.js';
8
+ export { TransactionEntity } from './entities/transaction.entity.js';
9
+ export { TransferEntity } from './entities/transfer.entity.js';
10
+ export { WalletEventPublisher } from './events/wallet-event.publisher.js';
11
+ export { ArrayLockService } from './lock/array-lock.service.js';
12
+ export { RedisLockService } from './lock/redis-lock.service.js';
13
+ export { MemcachedLockService } from './lock/memcached-lock.service.js';
14
+ export { walletLockKey } from './lock/lock.service.js';
15
+ export { InsufficientFundsError, WalletNotFoundError, WalletLockTimeoutError, ExchangeRateNotFoundError, } from './errors.js';
16
+ export { WALLET_OPTIONS, WALLET_LOCK, WALLET_DATA_SOURCE, WALLET_EVENT, DEFAULT_WALLET_SLUG, DEFAULT_WALLET_NAME, DEFAULT_LOCK_TTL_MS, } from './tokens.js';
17
+ export { generateMigrationFiles, listMigrationSpecs, resolveTables, DEFAULT_TABLES, } from './migrations/generate.js';
18
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAiC,MAAM,oBAAoB,CAAC;AACjF,OAAO,EAAE,aAAa,EAA0B,MAAM,qBAAqB,CAAC;AAC5E,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,eAAe,EAAwB,MAAM,uBAAuB,CAAC;AAC9E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAwB,MAAM,kCAAkC,CAAC;AAC3F,OAAO,EAAE,cAAc,EAAuB,MAAM,+BAA+B,CAAC;AACpF,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAM1E,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8BAA8B,CAAC;AAChE,OAAO,EAAE,oBAAoB,EAAE,MAAM,kCAAkC,CAAC;AAExE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACL,sBAAsB,EACtB,mBAAmB,EACnB,sBAAsB,EACtB,yBAAyB,GAC1B,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,cAAc,EACd,WAAW,EACX,kBAAkB,EAClB,YAAY,EACZ,mBAAmB,EACnB,mBAAmB,EACnB,mBAAmB,GAQpB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,sBAAsB,EACtB,kBAAkB,EAClB,aAAa,EACb,cAAc,GAEf,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,8 @@
1
+ import type { WalletLockService } from './lock.service.js';
2
+ export declare class ArrayLockService implements WalletLockService {
3
+ private readonly locks;
4
+ lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
5
+ private acquire;
6
+ private release;
7
+ }
8
+ //# sourceMappingURL=array-lock.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/array-lock.service.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAM3D,qBAAa,gBAAiB,YAAW,iBAAiB;IACxD,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAmC;IAEnD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;IAY3E,OAAO,CAAC,OAAO;IA+Bf,OAAO,CAAC,OAAO;CAUhB"}
@@ -0,0 +1,60 @@
1
+ import { WalletLockTimeoutError } from '../errors.js';
2
+ export class ArrayLockService {
3
+ constructor() {
4
+ this.locks = new Map();
5
+ }
6
+ async lock(key, ttlMs, fn) {
7
+ const acquired = await this.acquire(key, ttlMs);
8
+ if (!acquired) {
9
+ throw new WalletLockTimeoutError(`Timed out acquiring lock for ${key}`);
10
+ }
11
+ try {
12
+ return await fn();
13
+ }
14
+ finally {
15
+ this.release(key);
16
+ }
17
+ }
18
+ acquire(key, ttlMs) {
19
+ return new Promise((resolve) => {
20
+ const queue = this.locks.get(key);
21
+ if (!queue) {
22
+ this.locks.set(key, []);
23
+ resolve(true);
24
+ return;
25
+ }
26
+ const timer = setTimeout(() => {
27
+ const q = this.locks.get(key);
28
+ if (!q) {
29
+ resolve(false);
30
+ return;
31
+ }
32
+ const idx = q.indexOf(entry);
33
+ if (idx >= 0)
34
+ q.splice(idx, 1);
35
+ if (q.length === 0)
36
+ this.locks.delete(key);
37
+ resolve(false);
38
+ }, ttlMs);
39
+ const entry = {
40
+ resolve: () => {
41
+ clearTimeout(timer);
42
+ resolve(true);
43
+ },
44
+ };
45
+ queue.push(entry);
46
+ });
47
+ }
48
+ release(key) {
49
+ const queue = this.locks.get(key);
50
+ if (!queue)
51
+ return;
52
+ const next = queue.shift();
53
+ if (next) {
54
+ next.resolve();
55
+ return;
56
+ }
57
+ this.locks.delete(key);
58
+ }
59
+ }
60
+ //# sourceMappingURL=array-lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"array-lock.service.js","sourceRoot":"","sources":["../../src/lock/array-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAOtD,MAAM,OAAO,gBAAgB;IAA7B;QACmB,UAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAuD3D,CAAC;IArDC,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAChD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,gCAAgC,GAAG,EAAE,CAAC,CAAC;QAC1E,CAAC;QACD,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;QACpB,CAAC;IACH,CAAC;IAEO,OAAO,CAAC,GAAW,EAAE,KAAa;QACxC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE;YAC7B,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;gBACxB,OAAO,CAAC,IAAI,CAAC,CAAC;gBACd,OAAO;YACT,CAAC;YAED,MAAM,KAAK,GAAG,UAAU,CAAC,GAAG,EAAE;gBAC5B,MAAM,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;gBAC9B,IAAI,CAAC,CAAC,EAAE,CAAC;oBACP,OAAO,CAAC,KAAK,CAAC,CAAC;oBACf,OAAO;gBACT,CAAC;gBACD,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;gBAC7B,IAAI,GAAG,IAAI,CAAC;oBAAE,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBAC/B,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC;oBAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;gBAC3C,OAAO,CAAC,KAAK,CAAC,CAAC;YACjB,CAAC,EAAE,KAAK,CAAC,CAAC;YAEV,MAAM,KAAK,GAAe;gBACxB,OAAO,EAAE,GAAG,EAAE;oBACZ,YAAY,CAAC,KAAK,CAAC,CAAC;oBACpB,OAAO,CAAC,IAAI,CAAC,CAAC;gBAChB,CAAC;aACF,CAAC;YACF,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACpB,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,OAAO,CAAC,GAAW;QACzB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,IAAI,EAAE,CAAC;YACT,IAAI,CAAC,OAAO,EAAE,CAAC;YACf,OAAO;QACT,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;CACF"}
@@ -0,0 +1,5 @@
1
+ export interface WalletLockService {
2
+ lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
3
+ }
4
+ export declare function walletLockKey(walletId: number | string): string;
5
+ //# sourceMappingURL=lock.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/lock.service.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;CACvE;AAED,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,CAE/D"}
@@ -0,0 +1,4 @@
1
+ export function walletLockKey(walletId) {
2
+ return `wallet:lock:${walletId}`;
3
+ }
4
+ //# sourceMappingURL=lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"lock.service.js","sourceRoot":"","sources":["../../src/lock/lock.service.ts"],"names":[],"mappings":"AAIA,MAAM,UAAU,aAAa,CAAC,QAAyB;IACrD,OAAO,eAAe,QAAQ,EAAE,CAAC;AACnC,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { WalletLockService } from './lock.service.js';
2
+ type MemjsClient = {
3
+ add(key: string, value: Buffer | string, options: {
4
+ expires: number;
5
+ }): Promise<{
6
+ status?: string;
7
+ success?: boolean;
8
+ }>;
9
+ delete(key: string): Promise<unknown>;
10
+ get(key: string): Promise<{
11
+ value: Buffer | null;
12
+ }>;
13
+ };
14
+ export declare class MemcachedLockService implements WalletLockService {
15
+ private readonly client;
16
+ constructor(client: MemjsClient);
17
+ static create(servers?: string[]): Promise<MemcachedLockService>;
18
+ lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
19
+ }
20
+ export {};
21
+ //# sourceMappingURL=memcached-lock.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memcached-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/memcached-lock.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,KAAK,WAAW,GAAG;IACjB,GAAG,CACD,GAAG,EAAE,MAAM,EACX,KAAK,EAAE,MAAM,GAAG,MAAM,EACtB,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAA;KAAE,GAC3B,OAAO,CAAC;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,OAAO,CAAC,EAAE,OAAO,CAAA;KAAE,CAAC,CAAC;IACnD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACtC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;KAAE,CAAC,CAAC;CACrD,CAAC;AAEF,qBAAa,oBAAqB,YAAW,iBAAiB;IAChD,OAAO,CAAC,QAAQ,CAAC,MAAM;gBAAN,MAAM,EAAE,WAAW;WAEnC,MAAM,CAAC,OAAO,GAAE,MAAM,EAAwB,GAAG,OAAO,CAAC,oBAAoB,CAAC;IASrF,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAgC5E"}
@@ -0,0 +1,45 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { WalletLockTimeoutError } from '../errors.js';
3
+ export class MemcachedLockService {
4
+ constructor(client) {
5
+ this.client = client;
6
+ }
7
+ static async create(servers = ['127.0.0.1:11211']) {
8
+ // Optional peer — loaded dynamically; typed loosely to avoid requiring @types/memjs
9
+ const memjs = (await import('memjs'));
10
+ const client = memjs.Client.create(servers.join(','));
11
+ return new MemcachedLockService(client);
12
+ }
13
+ async lock(key, ttlMs, fn) {
14
+ const token = randomUUID();
15
+ const expires = Math.max(1, Math.ceil(ttlMs / 1000));
16
+ const deadline = Date.now() + ttlMs;
17
+ let acquired = false;
18
+ while (Date.now() < deadline) {
19
+ try {
20
+ const result = await this.client.add(key, token, { expires });
21
+ if (result.status === 'STORED' || result.success) {
22
+ acquired = true;
23
+ break;
24
+ }
25
+ }
26
+ catch {
27
+ // retry until timeout
28
+ }
29
+ await new Promise((r) => setTimeout(r, 25));
30
+ }
31
+ if (!acquired) {
32
+ throw new WalletLockTimeoutError(`Timed out acquiring memcached lock for ${key}`);
33
+ }
34
+ try {
35
+ return await fn();
36
+ }
37
+ finally {
38
+ const current = await this.client.get(key);
39
+ if (current.value?.toString() === token) {
40
+ await this.client.delete(key);
41
+ }
42
+ }
43
+ }
44
+ }
45
+ //# sourceMappingURL=memcached-lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"memcached-lock.service.js","sourceRoot":"","sources":["../../src/lock/memcached-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAatD,MAAM,OAAO,oBAAoB;IAC/B,YAA6B,MAAmB;QAAnB,WAAM,GAAN,MAAM,CAAa;IAAG,CAAC;IAEpD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,UAAoB,CAAC,iBAAiB,CAAC;QACzD,oFAAoF;QACpF,MAAM,KAAK,GAAG,CAAC,MAAM,MAAM,CAAC,OAAiB,CAAC,CAE7C,CAAC;QACF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QACtD,OAAO,IAAI,oBAAoB,CAAC,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,OAAO,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC,CAAC;QACrD,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,OAAO,EAAE,CAAC,CAAC;gBAC9D,IAAI,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;oBACjD,QAAQ,GAAG,IAAI,CAAC;oBAChB,MAAM;gBACR,CAAC;YACH,CAAC;YAAC,MAAM,CAAC;gBACP,sBAAsB;YACxB,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,0CAA0C,GAAG,EAAE,CAAC,CAAC;QACpF,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;YAC3C,IAAI,OAAO,CAAC,KAAK,EAAE,QAAQ,EAAE,KAAK,KAAK,EAAE,CAAC;gBACxC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,13 @@
1
+ import type { WalletLockService } from './lock.service.js';
2
+ type RedisClient = {
3
+ set(key: string, value: string, ...args: Array<string | number>): Promise<string | null>;
4
+ eval(script: string, numKeys: number, ...args: string[]): Promise<unknown>;
5
+ };
6
+ export declare class RedisLockService implements WalletLockService {
7
+ private readonly redis;
8
+ constructor(redis: RedisClient);
9
+ static create(url?: string): Promise<RedisLockService>;
10
+ lock<T>(key: string, ttlMs: number, fn: () => Promise<T>): Promise<T>;
11
+ }
12
+ export {};
13
+ //# sourceMappingURL=redis-lock.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-lock.service.d.ts","sourceRoot":"","sources":["../../src/lock/redis-lock.service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,KAAK,WAAW,GAAG;IACjB,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC;IACzF,IAAI,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;CAC5E,CAAC;AAUF,qBAAa,gBAAiB,YAAW,iBAAiB;IAC5C,OAAO,CAAC,QAAQ,CAAC,KAAK;gBAAL,KAAK,EAAE,WAAW;WAElC,MAAM,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAStD,IAAI,CAAC,CAAC,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC;CAwB5E"}
@@ -0,0 +1,43 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { WalletLockTimeoutError } from '../errors.js';
3
+ const RELEASE_SCRIPT = `
4
+ if redis.call("get", KEYS[1]) == ARGV[1] then
5
+ return redis.call("del", KEYS[1])
6
+ else
7
+ return 0
8
+ end
9
+ `;
10
+ export class RedisLockService {
11
+ constructor(redis) {
12
+ this.redis = redis;
13
+ }
14
+ static async create(url) {
15
+ const mod = (await import('ioredis'));
16
+ const RedisCtor = mod.default;
17
+ const client = url ? new RedisCtor(url) : new RedisCtor();
18
+ return new RedisLockService(client);
19
+ }
20
+ async lock(key, ttlMs, fn) {
21
+ const token = randomUUID();
22
+ const deadline = Date.now() + ttlMs;
23
+ let acquired = false;
24
+ while (Date.now() < deadline) {
25
+ const result = await this.redis.set(key, token, 'PX', ttlMs, 'NX');
26
+ if (result === 'OK') {
27
+ acquired = true;
28
+ break;
29
+ }
30
+ await new Promise((r) => setTimeout(r, 25));
31
+ }
32
+ if (!acquired) {
33
+ throw new WalletLockTimeoutError(`Timed out acquiring redis lock for ${key}`);
34
+ }
35
+ try {
36
+ return await fn();
37
+ }
38
+ finally {
39
+ await this.redis.eval(RELEASE_SCRIPT, 1, key, token);
40
+ }
41
+ }
42
+ }
43
+ //# sourceMappingURL=redis-lock.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"redis-lock.service.js","sourceRoot":"","sources":["../../src/lock/redis-lock.service.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AAQtD,MAAM,cAAc,GAAG;;;;;;CAMtB,CAAC;AAEF,MAAM,OAAO,gBAAgB;IAC3B,YAA6B,KAAkB;QAAlB,UAAK,GAAL,KAAK,CAAa;IAAG,CAAC;IAEnD,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAY;QAC9B,MAAM,GAAG,GAAG,CAAC,MAAM,MAAM,CAAC,SAAS,CAAC,CAEnC,CAAC;QACF,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,CAAC;QAC9B,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1D,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,IAAI,CAAI,GAAW,EAAE,KAAa,EAAE,EAAoB;QAC5D,MAAM,KAAK,GAAG,UAAU,EAAE,CAAC;QAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;QACpC,IAAI,QAAQ,GAAG,KAAK,CAAC;QAErB,OAAO,IAAI,CAAC,GAAG,EAAE,GAAG,QAAQ,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,CAAC;YACnE,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;gBACpB,QAAQ,GAAG,IAAI,CAAC;gBAChB,MAAM;YACR,CAAC;YACD,MAAM,IAAI,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,UAAU,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC;QAED,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,MAAM,IAAI,sBAAsB,CAAC,sCAAsC,GAAG,EAAE,CAAC,CAAC;QAChF,CAAC;QAED,IAAI,CAAC;YACH,OAAO,MAAM,EAAE,EAAE,CAAC;QACpB,CAAC;gBAAS,CAAC;YACT,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;CACF"}
@@ -0,0 +1,22 @@
1
+ export interface MigrationTableNames {
2
+ wallets: string;
3
+ transactions: string;
4
+ transfers: string;
5
+ }
6
+ export declare const DEFAULT_TABLES: MigrationTableNames;
7
+ export interface PublishMigrationSpec {
8
+ key: string;
9
+ fileSuffix: string;
10
+ contents: (tables: MigrationTableNames, className: string) => string;
11
+ }
12
+ export declare function buildMigrationClassName(suffix: string, stampValue: string): string;
13
+ export declare const MIGRATION_SPECS: PublishMigrationSpec[];
14
+ export declare const UUID_MIGRATION_SPEC: PublishMigrationSpec;
15
+ export declare function resolveTables(overrides?: Partial<MigrationTableNames>): MigrationTableNames;
16
+ export declare function listMigrationSpecs(withUuid?: boolean): PublishMigrationSpec[];
17
+ export declare function generateMigrationFiles(tables: MigrationTableNames, withUuid?: boolean, baseStamp?: number): Array<{
18
+ key: string;
19
+ fileName: string;
20
+ contents: string;
21
+ }>;
22
+ //# sourceMappingURL=generate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate.d.ts","sourceRoot":"","sources":["../../src/migrations/generate.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,MAAM,CAAC;IAChB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,eAAO,MAAM,cAAc,EAAE,mBAI5B,CAAC;AAEF,MAAM,WAAW,oBAAoB;IACnC,GAAG,EAAE,MAAM,CAAC;IACZ,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,CAAC,MAAM,EAAE,mBAAmB,EAAE,SAAS,EAAE,MAAM,KAAK,MAAM,CAAC;CACtE;AAMD,wBAAgB,uBAAuB,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,MAAM,CAMlF;AAED,eAAO,MAAM,eAAe,EAAE,oBAAoB,EA8KjD,CAAC;AAEF,eAAO,MAAM,mBAAmB,EAAE,oBA6BjC,CAAC;AAEF,wBAAgB,aAAa,CAAC,SAAS,CAAC,EAAE,OAAO,CAAC,mBAAmB,CAAC,GAAG,mBAAmB,CAE3F;AAED,wBAAgB,kBAAkB,CAAC,QAAQ,UAAQ,GAAG,oBAAoB,EAAE,CAE3E;AAED,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,mBAAmB,EAC3B,QAAQ,UAAQ,EAChB,SAAS,SAAa,GACrB,KAAK,CAAC;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAW5D"}