multivendor-wallet 0.0.4 → 0.0.6

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/index.d.mts CHANGED
@@ -1,8 +1,8 @@
1
- import { e as WalletPluginConfig, f as WalletPlugin, I as IWalletPaymentProvider } from './types-D46FcrKZ.mjs';
2
- export { D as DeliveredContext, O as OrderPaidContext, P as PaymentProviderWallet, R as RefundContext, S as SettlementDebitContext, g as WALLET_PLUGIN_TOKEN, h as WalletAdminMutationEvent, i as WalletConfig, C as WalletCreatePaymentInput, j as WalletFeatureFlags, k as WalletHttpConfig, l as WalletLedgerClient, W as WalletLifecycleHooks, b as WalletOrderPaidLine, m as WalletReconciliationConfig } from './types-D46FcrKZ.mjs';
3
- import { W as WalletAccountType } from './store-By30oqos.mjs';
4
- export { B as BalanceDeltas, d as CancelHoldParams, C as CreditParams, D as DebitParams, G as GetTransactionsParams, H as HoldParams, f as HoldStatus, I as IWalletStore, g as IWalletStoreTx, h as LedgerEntryType, L as LedgerMutationResult, R as ReleaseParams, T as TransferParams, b as WalletAccount, c as WalletBalance, i as WalletHold, e as WalletLedgerEntry, j as WalletReference, a as WalletStoreContext } from './store-By30oqos.mjs';
5
- export { CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata } from './typeorm/index.mjs';
1
+ import { e as WalletPluginConfig, f as WalletPlugin, I as IWalletPaymentProvider } from './types-D1Q4XCwx.mjs';
2
+ export { D as DeliveredContext, O as OrderPaidContext, P as PaymentProviderWallet, R as RefundContext, S as SettlementDebitContext, g as WALLET_PLUGIN_TOKEN, h as WalletAdminMutationEvent, i as WalletConfig, C as WalletCreatePaymentInput, j as WalletDuplicateOrderDebitInfo, k as WalletDuplicateOrderDebitKind, l as WalletFeatureFlags, m as WalletHttpConfig, n as WalletLedgerClient, W as WalletLifecycleHooks, b as WalletOrderPaidLine, o as WalletReconciliationConfig } from './types-D1Q4XCwx.mjs';
3
+ import { W as WalletAccountType } from './store-nWCfzvwf.mjs';
4
+ export { B as BalanceDeltas, d as CancelHoldParams, C as CreditParams, D as DebitParams, G as GetTransactionsParams, H as HoldParams, f as HoldStatus, I as IWalletStore, g as IWalletStoreTx, h as LedgerEntryType, L as LedgerMutationResult, R as ReleaseParams, T as TransferParams, b as WalletAccount, c as WalletBalance, i as WalletHold, e as WalletLedgerEntry, j as WalletReference, a as WalletStoreContext } from './store-nWCfzvwf.mjs';
5
+ export { AddOrderCustomerDebitUnique1790000001000, CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata } from './typeorm/index.mjs';
6
6
  import { Router } from 'express';
7
7
  import 'typeorm';
8
8
 
@@ -39,6 +39,41 @@ declare function registerWalletPlugin(config: WalletPluginConfig): WalletPlugin;
39
39
 
40
40
  declare function createWalletPaymentAdapter(plugin: WalletPlugin): IWalletPaymentProvider;
41
41
 
42
+ /** Server-local wall clock `YYYY-MM-DD HH:mm:ss` (matches host order paidDate, not UTC ISO). */
43
+ declare function nowTimestamp(date?: Date): string;
44
+ /** Parse naive datetime as local wall clock (do not treat as UTC). */
45
+ declare function parseLedgerDate(value: string | Date): Date;
46
+
47
+ declare const CUSTOMER_CHECKOUT_DEBIT_PURPOSE = "customer_checkout_debit";
48
+ declare const CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE = "customer_checkout_debit_reversal";
49
+ declare const BACKFILL_SENTINEL_KEY = "customer_checkout_debit_backfill";
50
+ declare const WALLET_OPS_TABLE = "wallet_ops";
51
+ declare function orderCustomerDebitIdempotencyKey(orderId: number | string): string;
52
+ declare function paymentReversalIdempotencyKey(paymentNumber: string): string;
53
+ declare function paymentNumberFromWalletPaymentKey(idempotencyKey: string): string | null;
54
+ /**
55
+ * True when this debit is a customer checkout (product-amount) debit for an order.
56
+ * Settlement/vendor/affiliate debits must not use these keys or purpose.
57
+ */
58
+ declare function isCustomerCheckoutDebit(params: {
59
+ idempotencyKey: string;
60
+ referenceType?: string;
61
+ purpose?: unknown;
62
+ }): boolean;
63
+ /**
64
+ * Legacy keys accepted during rollout only.
65
+ * Sunset: `npm run wallet:legacy-order-debit-sunset` — drop this helper when LEGACY_ORDER_DEBIT_SUNSET_SQL returns 0 on prod.
66
+ */
67
+ declare function isLegacyCustomerCheckoutDebitKey(key: string): boolean;
68
+ /** Unreimbursed full/split + wallet:payment twins (duplicate customer checkout debits). */
69
+ declare const UNREIMBURSED_TWIN_COUNT_SQL = "\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n";
70
+ declare const UNREIMBURSED_TWIN_DETAIL_SQL = "\nSELECT\n f.reference_id AS order_id,\n f.account_id,\n f.amount AS first_paise,\n p.amount AS second_paise,\n f.idempotency_key AS kept_key,\n p.idempotency_key AS duplicate_key,\n f.created_date AS first_at,\n p.created_date AS duplicate_at,\n f.id AS kept_id,\n p.id AS duplicate_id\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n";
71
+ /**
72
+ * Exit condition for removing isLegacyCustomerCheckoutDebitKey from debit lookup.
73
+ * File the sunset PR the same week this count hits 0 on prod.
74
+ */
75
+ declare const LEGACY_ORDER_DEBIT_SUNSET_SQL = "\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry\nWHERE entry_type = 'debit'\n AND reference_type = 'order'\n AND (\n idempotency_key LIKE 'wallet:full:%'\n OR idempotency_key LIKE 'wallet:split:%'\n OR idempotency_key LIKE 'wallet:payment:%'\n )\n";
76
+
42
77
  declare class WalletCreditDebitRequest {
43
78
  ownerType: WalletAccountType;
44
79
  ownerId: number;
@@ -128,4 +163,4 @@ declare class VendorWalletController {
128
163
 
129
164
  declare function createExpressWalletRouter(plugin: WalletPlugin, _basePath?: string): Router;
130
165
 
131
- export { AdminWalletController, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, IWalletPaymentProvider, InsufficientBalanceError, InvalidAmountError, VendorWalletController, WalletAccountType, WalletConfigError, WalletError, WalletPlugin, WalletPluginConfig, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, registerWalletPlugin, toMinorUnit };
166
+ export { AdminWalletController, BACKFILL_SENTINEL_KEY, CUSTOMER_CHECKOUT_DEBIT_PURPOSE, CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, IWalletPaymentProvider, InsufficientBalanceError, InvalidAmountError, LEGACY_ORDER_DEBIT_SUNSET_SQL, UNREIMBURSED_TWIN_COUNT_SQL, UNREIMBURSED_TWIN_DETAIL_SQL, VendorWalletController, WALLET_OPS_TABLE, WalletAccountType, WalletConfigError, WalletError, WalletPlugin, WalletPluginConfig, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, isCustomerCheckoutDebit, isLegacyCustomerCheckoutDebitKey, nowTimestamp, orderCustomerDebitIdempotencyKey, parseLedgerDate, paymentNumberFromWalletPaymentKey, paymentReversalIdempotencyKey, registerWalletPlugin, toMinorUnit };
package/dist/index.d.ts CHANGED
@@ -1,8 +1,8 @@
1
- import { e as WalletPluginConfig, f as WalletPlugin, I as IWalletPaymentProvider } from './types-BzaT7Aqh.js';
2
- export { D as DeliveredContext, O as OrderPaidContext, P as PaymentProviderWallet, R as RefundContext, S as SettlementDebitContext, g as WALLET_PLUGIN_TOKEN, h as WalletAdminMutationEvent, i as WalletConfig, C as WalletCreatePaymentInput, j as WalletFeatureFlags, k as WalletHttpConfig, l as WalletLedgerClient, W as WalletLifecycleHooks, b as WalletOrderPaidLine, m as WalletReconciliationConfig } from './types-BzaT7Aqh.js';
3
- import { W as WalletAccountType } from './store-By30oqos.js';
4
- export { B as BalanceDeltas, d as CancelHoldParams, C as CreditParams, D as DebitParams, G as GetTransactionsParams, H as HoldParams, f as HoldStatus, I as IWalletStore, g as IWalletStoreTx, h as LedgerEntryType, L as LedgerMutationResult, R as ReleaseParams, T as TransferParams, b as WalletAccount, c as WalletBalance, i as WalletHold, e as WalletLedgerEntry, j as WalletReference, a as WalletStoreContext } from './store-By30oqos.js';
5
- export { CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata } from './typeorm/index.js';
1
+ import { e as WalletPluginConfig, f as WalletPlugin, I as IWalletPaymentProvider } from './types-B4R1zaTK.js';
2
+ export { D as DeliveredContext, O as OrderPaidContext, P as PaymentProviderWallet, R as RefundContext, S as SettlementDebitContext, g as WALLET_PLUGIN_TOKEN, h as WalletAdminMutationEvent, i as WalletConfig, C as WalletCreatePaymentInput, j as WalletDuplicateOrderDebitInfo, k as WalletDuplicateOrderDebitKind, l as WalletFeatureFlags, m as WalletHttpConfig, n as WalletLedgerClient, W as WalletLifecycleHooks, b as WalletOrderPaidLine, o as WalletReconciliationConfig } from './types-B4R1zaTK.js';
3
+ import { W as WalletAccountType } from './store-nWCfzvwf.js';
4
+ export { B as BalanceDeltas, d as CancelHoldParams, C as CreditParams, D as DebitParams, G as GetTransactionsParams, H as HoldParams, f as HoldStatus, I as IWalletStore, g as IWalletStoreTx, h as LedgerEntryType, L as LedgerMutationResult, R as ReleaseParams, T as TransferParams, b as WalletAccount, c as WalletBalance, i as WalletHold, e as WalletLedgerEntry, j as WalletReference, a as WalletStoreContext } from './store-nWCfzvwf.js';
5
+ export { AddOrderCustomerDebitUnique1790000001000, CreateWalletTables1790000000000, TypeOrmWalletStore, WalletAccountEntity, WalletHoldEntity, WalletLedgerEntryEntity, getWalletOrmMetadata } from './typeorm/index.js';
6
6
  import { Router } from 'express';
7
7
  import 'typeorm';
8
8
 
@@ -39,6 +39,41 @@ declare function registerWalletPlugin(config: WalletPluginConfig): WalletPlugin;
39
39
 
40
40
  declare function createWalletPaymentAdapter(plugin: WalletPlugin): IWalletPaymentProvider;
41
41
 
42
+ /** Server-local wall clock `YYYY-MM-DD HH:mm:ss` (matches host order paidDate, not UTC ISO). */
43
+ declare function nowTimestamp(date?: Date): string;
44
+ /** Parse naive datetime as local wall clock (do not treat as UTC). */
45
+ declare function parseLedgerDate(value: string | Date): Date;
46
+
47
+ declare const CUSTOMER_CHECKOUT_DEBIT_PURPOSE = "customer_checkout_debit";
48
+ declare const CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE = "customer_checkout_debit_reversal";
49
+ declare const BACKFILL_SENTINEL_KEY = "customer_checkout_debit_backfill";
50
+ declare const WALLET_OPS_TABLE = "wallet_ops";
51
+ declare function orderCustomerDebitIdempotencyKey(orderId: number | string): string;
52
+ declare function paymentReversalIdempotencyKey(paymentNumber: string): string;
53
+ declare function paymentNumberFromWalletPaymentKey(idempotencyKey: string): string | null;
54
+ /**
55
+ * True when this debit is a customer checkout (product-amount) debit for an order.
56
+ * Settlement/vendor/affiliate debits must not use these keys or purpose.
57
+ */
58
+ declare function isCustomerCheckoutDebit(params: {
59
+ idempotencyKey: string;
60
+ referenceType?: string;
61
+ purpose?: unknown;
62
+ }): boolean;
63
+ /**
64
+ * Legacy keys accepted during rollout only.
65
+ * Sunset: `npm run wallet:legacy-order-debit-sunset` — drop this helper when LEGACY_ORDER_DEBIT_SUNSET_SQL returns 0 on prod.
66
+ */
67
+ declare function isLegacyCustomerCheckoutDebitKey(key: string): boolean;
68
+ /** Unreimbursed full/split + wallet:payment twins (duplicate customer checkout debits). */
69
+ declare const UNREIMBURSED_TWIN_COUNT_SQL = "\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n";
70
+ declare const UNREIMBURSED_TWIN_DETAIL_SQL = "\nSELECT\n f.reference_id AS order_id,\n f.account_id,\n f.amount AS first_paise,\n p.amount AS second_paise,\n f.idempotency_key AS kept_key,\n p.idempotency_key AS duplicate_key,\n f.created_date AS first_at,\n p.created_date AS duplicate_at,\n f.id AS kept_id,\n p.id AS duplicate_id\nFROM wallet_ledger_entry f\nJOIN wallet_ledger_entry p\n ON p.account_id = f.account_id\n AND p.reference_type = 'order'\n AND p.reference_id = f.reference_id\n AND p.entry_type = 'debit'\n AND p.idempotency_key LIKE 'wallet:payment:%'\nWHERE f.entry_type = 'debit'\n AND f.reference_type = 'order'\n AND (\n f.idempotency_key LIKE 'wallet:full:%'\n OR f.idempotency_key LIKE 'wallet:split:%'\n )\n AND NOT EXISTS (\n SELECT 1 FROM wallet_ledger_entry r\n WHERE r.entry_type = 'credit'\n AND r.account_id = p.account_id\n AND r.reference_type = 'order'\n AND r.reference_id = p.reference_id\n AND (\n r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))\n OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'\n )\n )\n";
71
+ /**
72
+ * Exit condition for removing isLegacyCustomerCheckoutDebitKey from debit lookup.
73
+ * File the sunset PR the same week this count hits 0 on prod.
74
+ */
75
+ declare const LEGACY_ORDER_DEBIT_SUNSET_SQL = "\nSELECT COUNT(*) AS c\nFROM wallet_ledger_entry\nWHERE entry_type = 'debit'\n AND reference_type = 'order'\n AND (\n idempotency_key LIKE 'wallet:full:%'\n OR idempotency_key LIKE 'wallet:split:%'\n OR idempotency_key LIKE 'wallet:payment:%'\n )\n";
76
+
42
77
  declare class WalletCreditDebitRequest {
43
78
  ownerType: WalletAccountType;
44
79
  ownerId: number;
@@ -128,4 +163,4 @@ declare class VendorWalletController {
128
163
 
129
164
  declare function createExpressWalletRouter(plugin: WalletPlugin, _basePath?: string): Router;
130
165
 
131
- export { AdminWalletController, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, IWalletPaymentProvider, InsufficientBalanceError, InvalidAmountError, VendorWalletController, WalletAccountType, WalletConfigError, WalletError, WalletPlugin, WalletPluginConfig, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, registerWalletPlugin, toMinorUnit };
166
+ export { AdminWalletController, BACKFILL_SENTINEL_KEY, CUSTOMER_CHECKOUT_DEBIT_PURPOSE, CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, IWalletPaymentProvider, InsufficientBalanceError, InvalidAmountError, LEGACY_ORDER_DEBIT_SUNSET_SQL, UNREIMBURSED_TWIN_COUNT_SQL, UNREIMBURSED_TWIN_DETAIL_SQL, VendorWalletController, WALLET_OPS_TABLE, WalletAccountType, WalletConfigError, WalletError, WalletPlugin, WalletPluginConfig, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, isCustomerCheckoutDebit, isLegacyCustomerCheckoutDebitKey, nowTimestamp, orderCustomerDebitIdempotencyKey, parseLedgerDate, paymentNumberFromWalletPaymentKey, paymentReversalIdempotencyKey, registerWalletPlugin, toMinorUnit };
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { PrimaryGeneratedColumn, Column, BeforeInsert, BeforeUpdate, Entity } from 'typeorm';
1
+ import { PrimaryGeneratedColumn, Column, BeforeInsert, BeforeUpdate, Entity, Brackets } from 'typeorm';
2
2
  import 'reflect-metadata';
3
3
  import { Get, Authorized, QueryParam, Res, Param, Post, Body, Req, JsonController } from 'routing-controllers';
4
4
  import { IsString, IsNotEmpty, IsInt, Min, IsNumber, IsOptional } from 'class-validator';
@@ -67,6 +67,121 @@ var _InvalidAmountError = class _InvalidAmountError extends WalletError {
67
67
  __name(_InvalidAmountError, "InvalidAmountError");
68
68
  var InvalidAmountError = _InvalidAmountError;
69
69
 
70
+ // src/orderCustomerDebit.ts
71
+ var CUSTOMER_CHECKOUT_DEBIT_PURPOSE = "customer_checkout_debit";
72
+ var CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE = "customer_checkout_debit_reversal";
73
+ var BACKFILL_SENTINEL_KEY = "customer_checkout_debit_backfill";
74
+ var WALLET_OPS_TABLE = "wallet_ops";
75
+ function orderCustomerDebitIdempotencyKey(orderId) {
76
+ return `wallet:order:${orderId}:customer_debit`;
77
+ }
78
+ __name(orderCustomerDebitIdempotencyKey, "orderCustomerDebitIdempotencyKey");
79
+ function paymentReversalIdempotencyKey(paymentNumber) {
80
+ return `wallet:payment-reversal:${paymentNumber}`;
81
+ }
82
+ __name(paymentReversalIdempotencyKey, "paymentReversalIdempotencyKey");
83
+ function paymentNumberFromWalletPaymentKey(idempotencyKey) {
84
+ const prefix = "wallet:payment:";
85
+ if (!idempotencyKey.startsWith(prefix)) {
86
+ return null;
87
+ }
88
+ return idempotencyKey.slice(prefix.length);
89
+ }
90
+ __name(paymentNumberFromWalletPaymentKey, "paymentNumberFromWalletPaymentKey");
91
+ function isCustomerCheckoutDebit(params) {
92
+ if (params.purpose === CUSTOMER_CHECKOUT_DEBIT_PURPOSE) {
93
+ return true;
94
+ }
95
+ const key = params.idempotencyKey;
96
+ if (key.startsWith("wallet:order:") && key.endsWith(":customer_debit")) {
97
+ return true;
98
+ }
99
+ if (params.referenceType !== "order") {
100
+ return false;
101
+ }
102
+ return isLegacyCustomerCheckoutDebitKey(key);
103
+ }
104
+ __name(isCustomerCheckoutDebit, "isCustomerCheckoutDebit");
105
+ function isLegacyCustomerCheckoutDebitKey(key) {
106
+ return key.startsWith("wallet:full:") || key.startsWith("wallet:split:") || key.startsWith("wallet:payment:");
107
+ }
108
+ __name(isLegacyCustomerCheckoutDebitKey, "isLegacyCustomerCheckoutDebitKey");
109
+ var UNREIMBURSED_TWIN_COUNT_SQL = `
110
+ SELECT COUNT(*) AS c
111
+ FROM wallet_ledger_entry f
112
+ JOIN wallet_ledger_entry p
113
+ ON p.account_id = f.account_id
114
+ AND p.reference_type = 'order'
115
+ AND p.reference_id = f.reference_id
116
+ AND p.entry_type = 'debit'
117
+ AND p.idempotency_key LIKE 'wallet:payment:%'
118
+ WHERE f.entry_type = 'debit'
119
+ AND f.reference_type = 'order'
120
+ AND (
121
+ f.idempotency_key LIKE 'wallet:full:%'
122
+ OR f.idempotency_key LIKE 'wallet:split:%'
123
+ )
124
+ AND NOT EXISTS (
125
+ SELECT 1 FROM wallet_ledger_entry r
126
+ WHERE r.entry_type = 'credit'
127
+ AND r.account_id = p.account_id
128
+ AND r.reference_type = 'order'
129
+ AND r.reference_id = p.reference_id
130
+ AND (
131
+ r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))
132
+ OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'
133
+ )
134
+ )
135
+ `;
136
+ var UNREIMBURSED_TWIN_DETAIL_SQL = `
137
+ SELECT
138
+ f.reference_id AS order_id,
139
+ f.account_id,
140
+ f.amount AS first_paise,
141
+ p.amount AS second_paise,
142
+ f.idempotency_key AS kept_key,
143
+ p.idempotency_key AS duplicate_key,
144
+ f.created_date AS first_at,
145
+ p.created_date AS duplicate_at,
146
+ f.id AS kept_id,
147
+ p.id AS duplicate_id
148
+ FROM wallet_ledger_entry f
149
+ JOIN wallet_ledger_entry p
150
+ ON p.account_id = f.account_id
151
+ AND p.reference_type = 'order'
152
+ AND p.reference_id = f.reference_id
153
+ AND p.entry_type = 'debit'
154
+ AND p.idempotency_key LIKE 'wallet:payment:%'
155
+ WHERE f.entry_type = 'debit'
156
+ AND f.reference_type = 'order'
157
+ AND (
158
+ f.idempotency_key LIKE 'wallet:full:%'
159
+ OR f.idempotency_key LIKE 'wallet:split:%'
160
+ )
161
+ AND NOT EXISTS (
162
+ SELECT 1 FROM wallet_ledger_entry r
163
+ WHERE r.entry_type = 'credit'
164
+ AND r.account_id = p.account_id
165
+ AND r.reference_type = 'order'
166
+ AND r.reference_id = p.reference_id
167
+ AND (
168
+ r.idempotency_key = CONCAT('wallet:payment-reversal:', SUBSTRING(p.idempotency_key, 17))
169
+ OR JSON_UNQUOTE(JSON_EXTRACT(r.metadata, '$.purpose')) = 'customer_checkout_debit_reversal'
170
+ )
171
+ )
172
+ `;
173
+ var LEGACY_ORDER_DEBIT_SUNSET_SQL = `
174
+ SELECT COUNT(*) AS c
175
+ FROM wallet_ledger_entry
176
+ WHERE entry_type = 'debit'
177
+ AND reference_type = 'order'
178
+ AND (
179
+ idempotency_key LIKE 'wallet:full:%'
180
+ OR idempotency_key LIKE 'wallet:split:%'
181
+ OR idempotency_key LIKE 'wallet:payment:%'
182
+ )
183
+ `;
184
+
70
185
  // src/types.ts
71
186
  var WalletAccountType = /* @__PURE__ */ (function(WalletAccountType2) {
72
187
  WalletAccountType2["CUSTOMER"] = "customer";
@@ -194,6 +309,7 @@ var _WalletLedgerClient = class _WalletLedgerClient {
194
309
  async debitInTx(tx, params) {
195
310
  const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
196
311
  if (existing) {
312
+ this.notifyDuplicateOrderDebit(params, existing, "idempotent_retry");
197
313
  const account = await tx.getAccountById(existing.accountId);
198
314
  if (!account) {
199
315
  throw new Error(`Wallet account ${existing.accountId} not found`);
@@ -204,27 +320,85 @@ var _WalletLedgerClient = class _WalletLedgerClient {
204
320
  };
205
321
  }
206
322
  const locked = await tx.lockAccount(params.accountId);
323
+ const orderId = params.reference?.referenceId;
324
+ const checkoutDebit = isCustomerCheckoutDebit({
325
+ idempotencyKey: params.idempotencyKey,
326
+ referenceType: params.reference?.referenceType,
327
+ purpose: params.metadata?.purpose
328
+ });
329
+ if (checkoutDebit && orderId) {
330
+ const existingPurpose = await tx.findOrderCustomerCheckoutDebit(params.accountId, orderId);
331
+ if (existingPurpose) {
332
+ const kind = existingPurpose.idempotencyKey === params.idempotencyKey ? "idempotent_retry" : "cross_key_collision";
333
+ this.notifyDuplicateOrderDebit(params, existingPurpose, kind);
334
+ return {
335
+ entry: existingPurpose,
336
+ account: locked
337
+ };
338
+ }
339
+ }
207
340
  if (locked.availableBalance < params.amount) {
208
341
  throw new InsufficientBalanceError();
209
342
  }
210
343
  const updated = await tx.updateBalances(params.accountId, {
211
344
  availableDelta: -params.amount
212
345
  });
213
- const entry = await tx.appendLedgerEntry({
214
- accountId: params.accountId,
215
- entryType: LedgerEntryType.DEBIT,
216
- amount: params.amount,
217
- balanceAfterAvailable: updated.availableBalance,
218
- balanceAfterHeld: updated.heldBalance,
346
+ try {
347
+ const entry = await tx.appendLedgerEntry({
348
+ accountId: params.accountId,
349
+ entryType: LedgerEntryType.DEBIT,
350
+ amount: params.amount,
351
+ balanceAfterAvailable: updated.availableBalance,
352
+ balanceAfterHeld: updated.heldBalance,
353
+ idempotencyKey: params.idempotencyKey,
354
+ referenceType: params.reference?.referenceType,
355
+ referenceId: params.reference?.referenceId,
356
+ metadata: params.metadata
357
+ });
358
+ return {
359
+ entry,
360
+ account: updated
361
+ };
362
+ } catch (error) {
363
+ if (error instanceof DuplicateOperationError && checkoutDebit && orderId) {
364
+ const dup = await tx.findOrderCustomerCheckoutDebit(params.accountId, orderId);
365
+ if (dup) {
366
+ const restored = await tx.updateBalances(params.accountId, {
367
+ availableDelta: params.amount
368
+ });
369
+ this.notifyDuplicateOrderDebit(params, dup, "cross_key_collision");
370
+ return {
371
+ entry: dup,
372
+ account: restored
373
+ };
374
+ }
375
+ }
376
+ throw error;
377
+ }
378
+ }
379
+ notifyDuplicateOrderDebit(params, existing, kind) {
380
+ const orderId = params.reference?.referenceId ?? existing.referenceId;
381
+ if (!orderId) {
382
+ return;
383
+ }
384
+ const checkoutDebit = isCustomerCheckoutDebit({
219
385
  idempotencyKey: params.idempotencyKey,
220
- referenceType: params.reference?.referenceType,
221
- referenceId: params.reference?.referenceId,
222
- metadata: params.metadata
386
+ referenceType: params.reference?.referenceType ?? existing.referenceType,
387
+ purpose: params.metadata?.purpose ?? existing.metadata?.purpose
223
388
  });
224
- return {
225
- entry,
226
- account: updated
227
- };
389
+ if (!checkoutDebit) {
390
+ return;
391
+ }
392
+ try {
393
+ this.config.onDuplicateOrderDebit?.({
394
+ orderId,
395
+ accountId: params.accountId,
396
+ requestedKey: params.idempotencyKey,
397
+ existingKey: existing.idempotencyKey,
398
+ kind
399
+ });
400
+ } catch {
401
+ }
228
402
  }
229
403
  async holdInTx(tx, params) {
230
404
  const existing = await tx.findLedgerByIdempotencyKey(params.idempotencyKey);
@@ -448,10 +622,14 @@ function createOrderHooks(runtime) {
448
622
  await client.debit({
449
623
  accountId: customer.id,
450
624
  amount: toMinorUnit(debitRupees),
451
- idempotencyKey: `wallet:payment:${ctx.paymentNumber}`,
625
+ idempotencyKey: orderCustomerDebitIdempotencyKey(ctx.orderId),
452
626
  reference: {
453
627
  referenceType: "order",
454
628
  referenceId: String(ctx.orderId)
629
+ },
630
+ metadata: {
631
+ purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE,
632
+ paymentNumber: ctx.paymentNumber
455
633
  }
456
634
  }, txCtx);
457
635
  }
@@ -465,7 +643,7 @@ function createOrderHooks(runtime) {
465
643
  }
466
644
  }, txCtx);
467
645
  for (const line of ctx.lines) {
468
- const vendorNetRupees = line.commissionBaseRupees - line.commissionRupees;
646
+ const vendorNetRupees = line.sellerNetRupees != null && Number.isFinite(Number(line.sellerNetRupees)) ? Number(line.sellerNetRupees) : line.commissionBaseRupees - line.commissionRupees;
469
647
  if (vendorNetRupees <= 0) {
470
648
  continue;
471
649
  }
@@ -606,6 +784,29 @@ function resolveWalletConnection() {
606
784
  return activeConnection;
607
785
  }
608
786
  __name(resolveWalletConnection, "resolveWalletConnection");
787
+
788
+ // src/timestamps.ts
789
+ function pad2(value) {
790
+ return String(value).padStart(2, "0");
791
+ }
792
+ __name(pad2, "pad2");
793
+ function nowTimestamp(date = /* @__PURE__ */ new Date()) {
794
+ return `${date.getFullYear()}-${pad2(date.getMonth() + 1)}-${pad2(date.getDate())} ${pad2(date.getHours())}:${pad2(date.getMinutes())}:${pad2(date.getSeconds())}`;
795
+ }
796
+ __name(nowTimestamp, "nowTimestamp");
797
+ function parseLedgerDate(value) {
798
+ if (value instanceof Date) {
799
+ return value;
800
+ }
801
+ const match = /^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})/.exec(String(value));
802
+ if (!match) {
803
+ return new Date(value);
804
+ }
805
+ return new Date(Number(match[1]), Number(match[2]) - 1, Number(match[3]), Number(match[4]), Number(match[5]), Number(match[6]));
806
+ }
807
+ __name(parseLedgerDate, "parseLedgerDate");
808
+
809
+ // src/typeorm/entities.ts
609
810
  function _ts_decorate(decorators, target, key, desc) {
610
811
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
611
812
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
@@ -617,10 +818,6 @@ function _ts_metadata(k, v) {
617
818
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
618
819
  }
619
820
  __name(_ts_metadata, "_ts_metadata");
620
- function nowTimestamp() {
621
- return (/* @__PURE__ */ new Date()).toISOString().slice(0, 19).replace("T", " ");
622
- }
623
- __name(nowTimestamp, "nowTimestamp");
624
821
  var _WalletAccountEntity = class _WalletAccountEntity {
625
822
  constructor() {
626
823
  __publicField(this, "id");
@@ -1702,8 +1899,6 @@ function createWalletPaymentAdapter(plugin) {
1702
1899
  };
1703
1900
  }
1704
1901
  __name(createWalletPaymentAdapter, "createWalletPaymentAdapter");
1705
-
1706
- // src/typeorm/store.ts
1707
1902
  function toNumber(value) {
1708
1903
  if (value == null) {
1709
1904
  return 0;
@@ -1732,7 +1927,7 @@ function toLedgerHold(row) {
1732
1927
  referenceType: row.referenceType,
1733
1928
  referenceId: row.referenceId,
1734
1929
  idempotencyKey: row.idempotencyKey,
1735
- createdAt: new Date(row.createdDate)
1930
+ createdAt: parseLedgerDate(row.createdDate)
1736
1931
  };
1737
1932
  }
1738
1933
  __name(toLedgerHold, "toLedgerHold");
@@ -1748,7 +1943,7 @@ function toLedgerEntry(row) {
1748
1943
  referenceType: row.referenceType,
1749
1944
  referenceId: row.referenceId,
1750
1945
  metadata: row.metadata,
1751
- createdAt: new Date(row.createdDate)
1946
+ createdAt: parseLedgerDate(row.createdDate)
1752
1947
  };
1753
1948
  }
1754
1949
  __name(toLedgerEntry, "toLedgerEntry");
@@ -1886,7 +2081,7 @@ var TypeOrmWalletStoreTx = (_a2 = class {
1886
2081
  where: {
1887
2082
  id: hold.id
1888
2083
  }
1889
- });
2084
+ }) ?? void 0;
1890
2085
  }
1891
2086
  if (!row) {
1892
2087
  row = await repo.findOne({
@@ -1894,7 +2089,7 @@ var TypeOrmWalletStoreTx = (_a2 = class {
1894
2089
  referenceType: hold.referenceType,
1895
2090
  referenceId: hold.referenceId
1896
2091
  }
1897
- });
2092
+ }) ?? void 0;
1898
2093
  }
1899
2094
  if (!row) {
1900
2095
  row = repo.create({
@@ -1924,6 +2119,36 @@ var TypeOrmWalletStoreTx = (_a2 = class {
1924
2119
  });
1925
2120
  return row ? toLedgerEntry(row) : null;
1926
2121
  }
2122
+ async findOrderCustomerCheckoutDebit(accountId, orderId) {
2123
+ const canonical = orderCustomerDebitIdempotencyKey(orderId);
2124
+ const row = await this.em.getRepository(WalletLedgerEntryEntity).createQueryBuilder("e").where("e.account_id = :accountId", {
2125
+ accountId
2126
+ }).andWhere("e.entry_type = :entryType", {
2127
+ entryType: "debit"
2128
+ }).andWhere("e.reference_type = :referenceType", {
2129
+ referenceType: "order"
2130
+ }).andWhere("e.reference_id = :orderId", {
2131
+ orderId
2132
+ }).andWhere(new Brackets((qb) => {
2133
+ qb.where(`JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose`, {
2134
+ purpose: CUSTOMER_CHECKOUT_DEBIT_PURPOSE
2135
+ }).orWhere("e.idempotency_key = :canonical", {
2136
+ canonical
2137
+ }).orWhere("e.idempotency_key LIKE :fullPrefix", {
2138
+ fullPrefix: "wallet:full:%"
2139
+ }).orWhere("e.idempotency_key LIKE :splitPrefix", {
2140
+ splitPrefix: "wallet:split:%"
2141
+ }).orWhere("e.idempotency_key LIKE :paymentPrefix", {
2142
+ paymentPrefix: "wallet:payment:%"
2143
+ });
2144
+ })).orderBy(`CASE
2145
+ WHEN JSON_UNQUOTE(JSON_EXTRACT(e.metadata, '$.purpose')) = :purpose THEN 0
2146
+ WHEN e.idempotency_key = :canonical THEN 1
2147
+ WHEN e.idempotency_key LIKE 'wallet:full:%' OR e.idempotency_key LIKE 'wallet:split:%' THEN 2
2148
+ ELSE 3
2149
+ END`, "ASC").addOrderBy("e.id", "ASC").setParameter("purpose", CUSTOMER_CHECKOUT_DEBIT_PURPOSE).setParameter("canonical", canonical).getOne();
2150
+ return row ? toLedgerEntry(row) : null;
2151
+ }
1927
2152
  async listLedgerEntries(accountId, limit, offset) {
1928
2153
  const rows = await this.em.getRepository(WalletLedgerEntryEntity).find({
1929
2154
  where: {
@@ -2060,6 +2285,84 @@ var _CreateWalletTables1790000000000 = class _CreateWalletTables1790000000000 {
2060
2285
  __name(_CreateWalletTables1790000000000, "CreateWalletTables1790000000000");
2061
2286
  var CreateWalletTables1790000000000 = _CreateWalletTables1790000000000;
2062
2287
 
2288
+ // src/typeorm/migrations/AddOrderCustomerDebitUnique.ts
2289
+ var _AddOrderCustomerDebitUnique1790000001000 = class _AddOrderCustomerDebitUnique1790000001000 {
2290
+ async up(queryRunner) {
2291
+ const opsTables = await queryRunner.query(`SELECT COUNT(*) AS c
2292
+ FROM information_schema.tables
2293
+ WHERE table_schema = DATABASE()
2294
+ AND table_name = ?`, [
2295
+ WALLET_OPS_TABLE
2296
+ ]);
2297
+ if (Number(opsTables[0]?.c ?? 0) === 0) {
2298
+ throw new Error(`Wallet unique-index gate: ${WALLET_OPS_TABLE} is missing. Run npm run wallet:credit-duplicate-order-debits`);
2299
+ }
2300
+ const sentinel = await queryRunner.query(`SELECT status FROM \`${WALLET_OPS_TABLE}\` WHERE ops_key = ? LIMIT 1`, [
2301
+ BACKFILL_SENTINEL_KEY
2302
+ ]);
2303
+ if (!sentinel[0] || sentinel[0].status !== "complete") {
2304
+ throw new Error(`Wallet unique-index gate: sentinel ${BACKFILL_SENTINEL_KEY} is missing. Run npm run wallet:credit-duplicate-order-debits`);
2305
+ }
2306
+ const twins = await queryRunner.query(UNREIMBURSED_TWIN_COUNT_SQL);
2307
+ const twinCount = Number(twins[0]?.c ?? 0);
2308
+ if (twinCount > 0) {
2309
+ throw new Error(`Wallet unique-index gate: unreimbursed twin COUNT is ${twinCount}. Run npm run wallet:credit-duplicate-order-debits`);
2310
+ }
2311
+ const columns = await queryRunner.query(`SELECT COUNT(*) AS c
2312
+ FROM information_schema.columns
2313
+ WHERE table_schema = DATABASE()
2314
+ AND table_name = 'wallet_ledger_entry'
2315
+ AND column_name = 'order_customer_debit_key'`);
2316
+ if (Number(columns[0]?.c ?? 0) === 0) {
2317
+ await queryRunner.query(`
2318
+ ALTER TABLE \`wallet_ledger_entry\`
2319
+ ADD COLUMN \`order_customer_debit_key\` VARCHAR(191)
2320
+ GENERATED ALWAYS AS (
2321
+ CASE
2322
+ WHEN \`entry_type\` = 'debit'
2323
+ AND \`reference_type\` = 'order'
2324
+ AND \`reference_id\` IS NOT NULL
2325
+ AND JSON_UNQUOTE(JSON_EXTRACT(\`metadata\`, '$.purpose')) = 'customer_checkout_debit'
2326
+ THEN CONCAT(\`account_id\`, ':', \`reference_id\`)
2327
+ ELSE NULL
2328
+ END
2329
+ ) STORED
2330
+ `);
2331
+ }
2332
+ const indexes = await queryRunner.query(`SELECT COUNT(*) AS c
2333
+ FROM information_schema.statistics
2334
+ WHERE table_schema = DATABASE()
2335
+ AND table_name = 'wallet_ledger_entry'
2336
+ AND index_name = 'UQ_wallet_order_customer_debit'`);
2337
+ if (Number(indexes[0]?.c ?? 0) === 0) {
2338
+ await queryRunner.query(`
2339
+ CREATE UNIQUE INDEX \`UQ_wallet_order_customer_debit\`
2340
+ ON \`wallet_ledger_entry\` (\`order_customer_debit_key\`)
2341
+ `);
2342
+ }
2343
+ }
2344
+ async down(queryRunner) {
2345
+ const indexes = await queryRunner.query(`SELECT COUNT(*) AS c
2346
+ FROM information_schema.statistics
2347
+ WHERE table_schema = DATABASE()
2348
+ AND table_name = 'wallet_ledger_entry'
2349
+ AND index_name = 'UQ_wallet_order_customer_debit'`);
2350
+ if (Number(indexes[0]?.c ?? 0) > 0) {
2351
+ await queryRunner.query(`DROP INDEX \`UQ_wallet_order_customer_debit\` ON \`wallet_ledger_entry\``);
2352
+ }
2353
+ const columns = await queryRunner.query(`SELECT COUNT(*) AS c
2354
+ FROM information_schema.columns
2355
+ WHERE table_schema = DATABASE()
2356
+ AND table_name = 'wallet_ledger_entry'
2357
+ AND column_name = 'order_customer_debit_key'`);
2358
+ if (Number(columns[0]?.c ?? 0) > 0) {
2359
+ await queryRunner.query(`ALTER TABLE \`wallet_ledger_entry\` DROP COLUMN \`order_customer_debit_key\``);
2360
+ }
2361
+ }
2362
+ };
2363
+ __name(_AddOrderCustomerDebitUnique1790000001000, "AddOrderCustomerDebitUnique1790000001000");
2364
+ var AddOrderCustomerDebitUnique1790000001000 = _AddOrderCustomerDebitUnique1790000001000;
2365
+
2063
2366
  // src/typeorm/metadata.ts
2064
2367
  function getWalletOrmMetadata() {
2065
2368
  return {
@@ -2069,7 +2372,8 @@ function getWalletOrmMetadata() {
2069
2372
  WalletHoldEntity
2070
2373
  ],
2071
2374
  migrations: [
2072
- CreateWalletTables1790000000000
2375
+ CreateWalletTables1790000000000,
2376
+ AddOrderCustomerDebitUnique1790000001000
2073
2377
  ]
2074
2378
  };
2075
2379
  }
@@ -2116,7 +2420,8 @@ var WalletPluginImpl = (_a3 = class {
2116
2420
  this.resolveOrderCustomerId = config.resolveOrderCustomerId;
2117
2421
  this.client = new WalletLedgerClient(store, {
2118
2422
  defaultCurrency: config.defaultCurrency ?? "INR",
2119
- platformOwnerId: config.platformOwnerId
2423
+ platformOwnerId: config.platformOwnerId,
2424
+ onDuplicateOrderDebit: config.onDuplicateOrderDebit
2120
2425
  });
2121
2426
  this.hooks = createLifecycleHooks({
2122
2427
  client: this.client,
@@ -2168,6 +2473,6 @@ function registerWalletPlugin(config) {
2168
2473
  }
2169
2474
  __name(registerWalletPlugin, "registerWalletPlugin");
2170
2475
 
2171
- export { AdminWalletController, CreateWalletTables1790000000000, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, HoldStatus, InsufficientBalanceError, InvalidAmountError, LedgerEntryType, PaymentProviderWallet, TypeOrmWalletStore, VendorWalletController, WALLET_PLUGIN_TOKEN, WalletAccountEntity, WalletAccountType, WalletConfigError, WalletError, WalletHoldEntity, WalletLedgerClient, WalletLedgerEntryEntity, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, getWalletOrmMetadata, registerWalletPlugin, toMinorUnit };
2476
+ export { AddOrderCustomerDebitUnique1790000001000, AdminWalletController, BACKFILL_SENTINEL_KEY, CUSTOMER_CHECKOUT_DEBIT_PURPOSE, CUSTOMER_CHECKOUT_DEBIT_REVERSAL_PURPOSE, CreateWalletTables1790000000000, CustomerWalletController, DuplicateOperationError, HoldNotFoundError, HoldStatus, InsufficientBalanceError, InvalidAmountError, LEGACY_ORDER_DEBIT_SUNSET_SQL, LedgerEntryType, PaymentProviderWallet, TypeOrmWalletStore, UNREIMBURSED_TWIN_COUNT_SQL, UNREIMBURSED_TWIN_DETAIL_SQL, VendorWalletController, WALLET_OPS_TABLE, WALLET_PLUGIN_TOKEN, WalletAccountEntity, WalletAccountType, WalletConfigError, WalletError, WalletHoldEntity, WalletLedgerClient, WalletLedgerEntryEntity, createExpressWalletRouter, createWalletPaymentAdapter, fromMinorUnit, getWalletOrmMetadata, isCustomerCheckoutDebit, isLegacyCustomerCheckoutDebitKey, nowTimestamp, orderCustomerDebitIdempotencyKey, parseLedgerDate, paymentNumberFromWalletPaymentKey, paymentReversalIdempotencyKey, registerWalletPlugin, toMinorUnit };
2172
2477
  //# sourceMappingURL=index.js.map
2173
2478
  //# sourceMappingURL=index.js.map