@qazuor/qzpay-drizzle 1.7.8 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +307 -17
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +103 -4
- package/dist/index.d.ts +103 -4
- package/dist/index.js +300 -18
- package/dist/index.js.map +1 -1
- package/dist/schema/index.cjs +88 -1
- package/dist/schema/index.cjs.map +1 -1
- package/dist/schema/index.d.cts +1451 -534
- package/dist/schema/index.d.ts +1451 -534
- package/dist/schema/index.js +85 -2
- package/dist/schema/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.cjs
CHANGED
|
@@ -130,13 +130,13 @@ function firstOrThrow(results, entityType, id) {
|
|
|
130
130
|
}
|
|
131
131
|
async function updateWithVersionHelper(db, table, id, expectedVersion, updateData, options) {
|
|
132
132
|
const { entityType, entityId, includeSoftDeleted = false, transform } = options;
|
|
133
|
-
const { and:
|
|
133
|
+
const { and: and20, eq: eq19, isNull: isNull13 } = await import('drizzle-orm');
|
|
134
134
|
const { generateVersion: generateVersion2 } = await Promise.resolve().then(() => (init_optimistic_locking(), optimistic_locking_exports));
|
|
135
|
-
const conditions = [
|
|
135
|
+
const conditions = [eq19(table.id, id), eq19(table.version, expectedVersion)];
|
|
136
136
|
if (!includeSoftDeleted && "deletedAt" in table) {
|
|
137
137
|
conditions.push(isNull13(table.deletedAt));
|
|
138
138
|
}
|
|
139
|
-
const whereClause =
|
|
139
|
+
const whereClause = and20(...conditions);
|
|
140
140
|
if (!whereClause) {
|
|
141
141
|
throw new Error("Failed to build WHERE clause for version update");
|
|
142
142
|
}
|
|
@@ -150,7 +150,7 @@ async function updateWithVersionHelper(db, table, id, expectedVersion, updateDat
|
|
|
150
150
|
result = await db.update(table).set(dataWithVersion).where(whereClause).returning();
|
|
151
151
|
} catch (_error) {
|
|
152
152
|
try {
|
|
153
|
-
const existsQuery = await db.select().from(table).where(includeSoftDeleted ?
|
|
153
|
+
const existsQuery = await db.select().from(table).where(includeSoftDeleted ? eq19(table.id, id) : and20(eq19(table.id, id), isNull13(table.deletedAt))).limit(1);
|
|
154
154
|
if (existsQuery.length > 0) {
|
|
155
155
|
throw new exports.QZPayOptimisticLockError(entityType, entityId);
|
|
156
156
|
}
|
|
@@ -159,7 +159,7 @@ async function updateWithVersionHelper(db, table, id, expectedVersion, updateDat
|
|
|
159
159
|
throw new exports.QZPayEntityNotFoundError(entityType, entityId);
|
|
160
160
|
}
|
|
161
161
|
if (result.length === 0) {
|
|
162
|
-
const existsQuery = await db.select().from(table).where(includeSoftDeleted ?
|
|
162
|
+
const existsQuery = await db.select().from(table).where(includeSoftDeleted ? eq19(table.id, id) : and20(eq19(table.id, id), isNull13(table.deletedAt))).limit(1);
|
|
163
163
|
if (existsQuery.length > 0) {
|
|
164
164
|
throw new exports.QZPayOptimisticLockError(entityType, entityId);
|
|
165
165
|
}
|
|
@@ -1107,6 +1107,46 @@ function mapCorePromoCodeUpdateToDrizzle(update) {
|
|
|
1107
1107
|
return result;
|
|
1108
1108
|
}
|
|
1109
1109
|
|
|
1110
|
+
// src/mappers/subscription-polling-job.mapper.ts
|
|
1111
|
+
var POLLING_JOB_DEFAULTS = {
|
|
1112
|
+
initialDelayMs: 3e4,
|
|
1113
|
+
maxAttempts: 60
|
|
1114
|
+
};
|
|
1115
|
+
function mapDrizzlePollingJobToCore(row) {
|
|
1116
|
+
return {
|
|
1117
|
+
id: row.id,
|
|
1118
|
+
subscriptionId: row.subscriptionId,
|
|
1119
|
+
provider: row.provider,
|
|
1120
|
+
providerResourceId: row.providerResourceId,
|
|
1121
|
+
status: row.status,
|
|
1122
|
+
attempts: row.attempts,
|
|
1123
|
+
maxAttempts: row.maxAttempts,
|
|
1124
|
+
nextPollAt: row.nextPollAt,
|
|
1125
|
+
lastPolledAt: row.lastPolledAt ?? null,
|
|
1126
|
+
lastProviderStatus: row.lastProviderStatus ?? null,
|
|
1127
|
+
lastError: row.lastError ?? null,
|
|
1128
|
+
metadata: row.metadata ?? {},
|
|
1129
|
+
createdAt: row.createdAt,
|
|
1130
|
+
updatedAt: row.updatedAt,
|
|
1131
|
+
completedAt: row.completedAt ?? null,
|
|
1132
|
+
version: row.version
|
|
1133
|
+
};
|
|
1134
|
+
}
|
|
1135
|
+
function mapPollingScheduleInputToDrizzleInsert(input) {
|
|
1136
|
+
const initialDelayMs = input.initialDelayMs ?? POLLING_JOB_DEFAULTS.initialDelayMs;
|
|
1137
|
+
const nextPollAt = new Date(Date.now() + initialDelayMs);
|
|
1138
|
+
return {
|
|
1139
|
+
subscriptionId: input.subscriptionId,
|
|
1140
|
+
provider: input.provider,
|
|
1141
|
+
providerResourceId: input.providerResourceId,
|
|
1142
|
+
status: "pending",
|
|
1143
|
+
attempts: 0,
|
|
1144
|
+
maxAttempts: input.maxAttempts ?? POLLING_JOB_DEFAULTS.maxAttempts,
|
|
1145
|
+
nextPollAt,
|
|
1146
|
+
metadata: input.metadata ?? {}
|
|
1147
|
+
};
|
|
1148
|
+
}
|
|
1149
|
+
|
|
1110
1150
|
// src/mappers/subscription.mapper.ts
|
|
1111
1151
|
function mapDrizzleSubscriptionToCore(drizzle3) {
|
|
1112
1152
|
const providerSubscriptionIds = {};
|
|
@@ -1890,6 +1930,80 @@ var billingPrices = pgCore.pgTable(
|
|
|
1890
1930
|
);
|
|
1891
1931
|
var billingPriceInsertSchema = drizzleZod.createInsertSchema(billingPrices);
|
|
1892
1932
|
var billingPriceSelectSchema = drizzleZod.createSelectSchema(billingPrices);
|
|
1933
|
+
var billingSubscriptionPollingJobs = pgCore.pgTable(
|
|
1934
|
+
"billing_subscription_polling_jobs",
|
|
1935
|
+
{
|
|
1936
|
+
id: pgCore.uuid("id").primaryKey().defaultRandom(),
|
|
1937
|
+
subscriptionId: pgCore.uuid("subscription_id").notNull().references(() => billingSubscriptions.id, { onDelete: "cascade" }),
|
|
1938
|
+
/**
|
|
1939
|
+
* Provider identifier, e.g. `mercadopago`. Future-proofed so
|
|
1940
|
+
* Stripe or other adapters can opt in to polling if needed.
|
|
1941
|
+
*/
|
|
1942
|
+
provider: pgCore.varchar("provider", { length: 50 }).notNull(),
|
|
1943
|
+
/**
|
|
1944
|
+
* Provider-side resource id (e.g. MP preapproval id) that the
|
|
1945
|
+
* poller uses to query the provider's REST endpoint.
|
|
1946
|
+
*/
|
|
1947
|
+
providerResourceId: pgCore.varchar("provider_resource_id", { length: 255 }).notNull(),
|
|
1948
|
+
/**
|
|
1949
|
+
* Job lifecycle status.
|
|
1950
|
+
* - `pending`: cron will pick up when due
|
|
1951
|
+
* - `succeeded`: provider returned a terminal authorized state
|
|
1952
|
+
* - `failed`: provider returned cancelled/rejected
|
|
1953
|
+
* - `timeout`: max_attempts reached without resolution
|
|
1954
|
+
* - `cancelled`: cancelled externally (e.g. user cancelled sub mid-flight)
|
|
1955
|
+
*/
|
|
1956
|
+
status: pgCore.varchar("status", { length: 20 }).notNull().default("pending"),
|
|
1957
|
+
attempts: pgCore.integer("attempts").notNull().default(0),
|
|
1958
|
+
maxAttempts: pgCore.integer("max_attempts").notNull().default(60),
|
|
1959
|
+
nextPollAt: pgCore.timestamp("next_poll_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1960
|
+
lastPolledAt: pgCore.timestamp("last_polled_at", { withTimezone: true }),
|
|
1961
|
+
/**
|
|
1962
|
+
* Raw provider status from the last poll (e.g. `pending`,
|
|
1963
|
+
* `authorized`). Useful for diagnostics without joining logs.
|
|
1964
|
+
*/
|
|
1965
|
+
lastProviderStatus: pgCore.varchar("last_provider_status", { length: 50 }),
|
|
1966
|
+
/**
|
|
1967
|
+
* Last error message (truncated server-side to avoid bloat).
|
|
1968
|
+
* Set when a poll attempt fails (network, 4xx, 5xx).
|
|
1969
|
+
*/
|
|
1970
|
+
lastError: pgCore.text("last_error"),
|
|
1971
|
+
metadata: pgCore.jsonb("metadata").notNull().default({}),
|
|
1972
|
+
createdAt: pgCore.timestamp("created_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1973
|
+
updatedAt: pgCore.timestamp("updated_at", { withTimezone: true }).notNull().defaultNow(),
|
|
1974
|
+
completedAt: pgCore.timestamp("completed_at", { withTimezone: true }),
|
|
1975
|
+
/**
|
|
1976
|
+
* Optimistic lock token. Updated on every state change. Workers
|
|
1977
|
+
* must include this in their UPDATE WHERE clause to detect
|
|
1978
|
+
* concurrent modifications.
|
|
1979
|
+
*/
|
|
1980
|
+
version: pgCore.uuid("version").notNull().defaultRandom()
|
|
1981
|
+
},
|
|
1982
|
+
(table) => ({
|
|
1983
|
+
/**
|
|
1984
|
+
* Partial index that supports the cron's "find due pending
|
|
1985
|
+
* jobs" query. Only rows still pending are scanned, so the
|
|
1986
|
+
* per-tick cost is O(k) where k = #pending jobs (NOT a full
|
|
1987
|
+
* table scan that would grow with historical job count).
|
|
1988
|
+
*/
|
|
1989
|
+
dueIdx: pgCore.index("idx_polling_jobs_due").on(table.nextPollAt).where(drizzleOrm.sql`status = 'pending'`),
|
|
1990
|
+
/**
|
|
1991
|
+
* Lookup by subscription, e.g. when a webhook arrives and we
|
|
1992
|
+
* need to mark the active polling job as `succeeded`.
|
|
1993
|
+
*/
|
|
1994
|
+
subscriptionIdx: pgCore.index("idx_polling_jobs_subscription").on(table.subscriptionId),
|
|
1995
|
+
/**
|
|
1996
|
+
* At most one ACTIVE polling job per subscription. Prevents
|
|
1997
|
+
* duplicate enqueuing if `schedulePolling()` is called twice
|
|
1998
|
+
* concurrently. Historical jobs (succeeded/failed/timeout/
|
|
1999
|
+
* cancelled) are NOT constrained — multiple terminal rows per
|
|
2000
|
+
* subscription are allowed for audit trail.
|
|
2001
|
+
*/
|
|
2002
|
+
oneActivePerSubscriptionIdx: pgCore.uniqueIndex("idx_polling_jobs_one_active_per_sub").on(table.subscriptionId).where(drizzleOrm.sql`status = 'pending'`)
|
|
2003
|
+
})
|
|
2004
|
+
);
|
|
2005
|
+
var billingSubscriptionPollingJobInsertSchema = drizzleZod.createInsertSchema(billingSubscriptionPollingJobs);
|
|
2006
|
+
var billingSubscriptionPollingJobSelectSchema = drizzleZod.createSelectSchema(billingSubscriptionPollingJobs);
|
|
1893
2007
|
var billingUsageRecords = pgCore.pgTable(
|
|
1894
2008
|
"billing_usage_records",
|
|
1895
2009
|
{
|
|
@@ -1991,7 +2105,14 @@ var billingSubscriptionsRelations = drizzleOrm.relations(billingSubscriptions, (
|
|
|
1991
2105
|
payments: many(billingPayments),
|
|
1992
2106
|
invoices: many(billingInvoices),
|
|
1993
2107
|
usageRecords: many(billingUsageRecords),
|
|
1994
|
-
addons: many(billingSubscriptionAddons)
|
|
2108
|
+
addons: many(billingSubscriptionAddons),
|
|
2109
|
+
pollingJobs: many(billingSubscriptionPollingJobs)
|
|
2110
|
+
}));
|
|
2111
|
+
var billingSubscriptionPollingJobsRelations = drizzleOrm.relations(billingSubscriptionPollingJobs, ({ one }) => ({
|
|
2112
|
+
subscription: one(billingSubscriptions, {
|
|
2113
|
+
fields: [billingSubscriptionPollingJobs.subscriptionId],
|
|
2114
|
+
references: [billingSubscriptions.id]
|
|
2115
|
+
})
|
|
1995
2116
|
}));
|
|
1996
2117
|
var billingPaymentsRelations = drizzleOrm.relations(billingPayments, ({ one, many }) => ({
|
|
1997
2118
|
customer: one(billingCustomers, {
|
|
@@ -2188,6 +2309,7 @@ var qzpaySchema = {
|
|
|
2188
2309
|
billingPromoCodes,
|
|
2189
2310
|
billingPromoCodeUsage,
|
|
2190
2311
|
billingSubscriptions,
|
|
2312
|
+
billingSubscriptionPollingJobs,
|
|
2191
2313
|
billingUsageRecords,
|
|
2192
2314
|
billingVendors,
|
|
2193
2315
|
billingVendorPayouts,
|
|
@@ -2212,6 +2334,7 @@ var qzpaySchema = {
|
|
|
2212
2334
|
billingPromoCodesRelations,
|
|
2213
2335
|
billingPromoCodeUsageRelations,
|
|
2214
2336
|
billingSubscriptionsRelations,
|
|
2337
|
+
billingSubscriptionPollingJobsRelations,
|
|
2215
2338
|
billingUsageRecordsRelations,
|
|
2216
2339
|
billingVendorsRelations,
|
|
2217
2340
|
billingVendorPayoutsRelations
|
|
@@ -4700,6 +4823,119 @@ var QZPayPromoCodesRepository = class {
|
|
|
4700
4823
|
}
|
|
4701
4824
|
};
|
|
4702
4825
|
init_base_repository();
|
|
4826
|
+
var PG_UNIQUE_VIOLATION = "23505";
|
|
4827
|
+
function isUniqueViolation(error) {
|
|
4828
|
+
if (typeof error !== "object" || error === null) {
|
|
4829
|
+
return false;
|
|
4830
|
+
}
|
|
4831
|
+
const direct = error;
|
|
4832
|
+
if (direct.code === PG_UNIQUE_VIOLATION) {
|
|
4833
|
+
return true;
|
|
4834
|
+
}
|
|
4835
|
+
const cause = error.cause;
|
|
4836
|
+
if (cause && typeof cause === "object") {
|
|
4837
|
+
const innerCode = cause.code;
|
|
4838
|
+
if (innerCode === PG_UNIQUE_VIOLATION) {
|
|
4839
|
+
return true;
|
|
4840
|
+
}
|
|
4841
|
+
}
|
|
4842
|
+
return false;
|
|
4843
|
+
}
|
|
4844
|
+
var QZPaySubscriptionPollingJobsRepository = class {
|
|
4845
|
+
constructor(db) {
|
|
4846
|
+
this.db = db;
|
|
4847
|
+
}
|
|
4848
|
+
/**
|
|
4849
|
+
* Insert a new pending polling job.
|
|
4850
|
+
*
|
|
4851
|
+
* Returns `null` if a partial-unique violation is raised — i.e.,
|
|
4852
|
+
* there is already a `pending` job for the same subscription. The
|
|
4853
|
+
* caller can then choose to read the existing job and treat it as
|
|
4854
|
+
* the source of truth.
|
|
4855
|
+
*/
|
|
4856
|
+
async create(input) {
|
|
4857
|
+
try {
|
|
4858
|
+
const result = await this.db.insert(billingSubscriptionPollingJobs).values(input).returning();
|
|
4859
|
+
return firstOrNull(result);
|
|
4860
|
+
} catch (error) {
|
|
4861
|
+
if (isUniqueViolation(error)) {
|
|
4862
|
+
return null;
|
|
4863
|
+
}
|
|
4864
|
+
throw error;
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
/**
|
|
4868
|
+
* Find a polling job by id.
|
|
4869
|
+
*/
|
|
4870
|
+
async findById(id) {
|
|
4871
|
+
const result = await this.db.select().from(billingSubscriptionPollingJobs).where(drizzleOrm.eq(billingSubscriptionPollingJobs.id, id)).limit(1);
|
|
4872
|
+
return firstOrNull(result);
|
|
4873
|
+
}
|
|
4874
|
+
/**
|
|
4875
|
+
* Find the active (`pending`) polling job for a subscription, if any.
|
|
4876
|
+
* Returns the single active job because the partial-unique index
|
|
4877
|
+
* enforces at most one.
|
|
4878
|
+
*/
|
|
4879
|
+
async findActiveBySubscriptionId(subscriptionId) {
|
|
4880
|
+
const result = await this.db.select().from(billingSubscriptionPollingJobs).where(
|
|
4881
|
+
drizzleOrm.and(drizzleOrm.eq(billingSubscriptionPollingJobs.subscriptionId, subscriptionId), drizzleOrm.eq(billingSubscriptionPollingJobs.status, "pending"))
|
|
4882
|
+
).limit(1);
|
|
4883
|
+
return firstOrNull(result);
|
|
4884
|
+
}
|
|
4885
|
+
/**
|
|
4886
|
+
* Fetch up to `limit` pending jobs whose `next_poll_at <= now`,
|
|
4887
|
+
* ordered by `next_poll_at` ascending so most-overdue jobs are
|
|
4888
|
+
* processed first.
|
|
4889
|
+
*/
|
|
4890
|
+
async findDuePending(now, limit) {
|
|
4891
|
+
const safeLimit = Math.max(1, Math.min(limit, 200));
|
|
4892
|
+
return this.db.select().from(billingSubscriptionPollingJobs).where(drizzleOrm.and(drizzleOrm.eq(billingSubscriptionPollingJobs.status, "pending"), drizzleOrm.lte(billingSubscriptionPollingJobs.nextPollAt, now))).orderBy(drizzleOrm.asc(billingSubscriptionPollingJobs.nextPollAt)).limit(safeLimit);
|
|
4893
|
+
}
|
|
4894
|
+
/**
|
|
4895
|
+
* Optimistic-locked update.
|
|
4896
|
+
*
|
|
4897
|
+
* The UPDATE only fires when both `id` AND `version` match the row
|
|
4898
|
+
* the caller previously read. On success the row's `version` is
|
|
4899
|
+
* rotated to a fresh uuid (server-side via gen_random_uuid()) and
|
|
4900
|
+
* `updated_at` is bumped. Returns `null` when another worker has
|
|
4901
|
+
* already moved the row (the version no longer matches).
|
|
4902
|
+
*/
|
|
4903
|
+
async tryLockedUpdate(params) {
|
|
4904
|
+
const updates = {
|
|
4905
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
4906
|
+
};
|
|
4907
|
+
if (params.status !== void 0) {
|
|
4908
|
+
updates.status = params.status;
|
|
4909
|
+
}
|
|
4910
|
+
if (params.lastPolledAt !== void 0) {
|
|
4911
|
+
updates.lastPolledAt = params.lastPolledAt;
|
|
4912
|
+
}
|
|
4913
|
+
if (params.lastProviderStatus !== void 0) {
|
|
4914
|
+
updates.lastProviderStatus = params.lastProviderStatus;
|
|
4915
|
+
}
|
|
4916
|
+
if (params.lastError !== void 0) {
|
|
4917
|
+
updates.lastError = params.lastError;
|
|
4918
|
+
}
|
|
4919
|
+
if (params.nextPollAt !== void 0) {
|
|
4920
|
+
updates.nextPollAt = params.nextPollAt;
|
|
4921
|
+
}
|
|
4922
|
+
if (params.completedAt !== void 0) {
|
|
4923
|
+
updates.completedAt = params.completedAt;
|
|
4924
|
+
}
|
|
4925
|
+
const attemptsExpr = params.incrementAttemptsBy && params.incrementAttemptsBy !== 0 ? drizzleOrm.sql`${billingSubscriptionPollingJobs.attempts} + ${params.incrementAttemptsBy}` : void 0;
|
|
4926
|
+
const result = await this.db.update(billingSubscriptionPollingJobs).set({
|
|
4927
|
+
...updates,
|
|
4928
|
+
// Rotate the version token on every successful update so
|
|
4929
|
+
// a subsequent UPDATE with the previous token fails.
|
|
4930
|
+
version: drizzleOrm.sql`gen_random_uuid()`,
|
|
4931
|
+
...attemptsExpr ? { attempts: attemptsExpr } : {}
|
|
4932
|
+
}).where(
|
|
4933
|
+
drizzleOrm.and(drizzleOrm.eq(billingSubscriptionPollingJobs.id, params.id), drizzleOrm.eq(billingSubscriptionPollingJobs.version, params.expectedVersion))
|
|
4934
|
+
).returning();
|
|
4935
|
+
return firstOrNull(result);
|
|
4936
|
+
}
|
|
4937
|
+
};
|
|
4938
|
+
init_base_repository();
|
|
4703
4939
|
var QZPaySubscriptionsRepository = class {
|
|
4704
4940
|
constructor(db) {
|
|
4705
4941
|
this.db = db;
|
|
@@ -5767,6 +6003,7 @@ var QZPayDrizzleStorageAdapter = class {
|
|
|
5767
6003
|
checkoutsRepo;
|
|
5768
6004
|
customersRepo;
|
|
5769
6005
|
subscriptionsRepo;
|
|
6006
|
+
subscriptionPollingJobsRepo;
|
|
5770
6007
|
paymentsRepo;
|
|
5771
6008
|
paymentMethodsRepo;
|
|
5772
6009
|
invoicesRepo;
|
|
@@ -5782,6 +6019,7 @@ var QZPayDrizzleStorageAdapter = class {
|
|
|
5782
6019
|
checkouts;
|
|
5783
6020
|
customers;
|
|
5784
6021
|
subscriptions;
|
|
6022
|
+
subscriptionPollingJobs;
|
|
5785
6023
|
payments;
|
|
5786
6024
|
paymentMethods;
|
|
5787
6025
|
invoices;
|
|
@@ -5799,6 +6037,7 @@ var QZPayDrizzleStorageAdapter = class {
|
|
|
5799
6037
|
this.checkoutsRepo = new QZPayCheckoutsRepository(this.db);
|
|
5800
6038
|
this.customersRepo = new QZPayCustomersRepository(typedDb);
|
|
5801
6039
|
this.subscriptionsRepo = new QZPaySubscriptionsRepository(typedDb);
|
|
6040
|
+
this.subscriptionPollingJobsRepo = new QZPaySubscriptionPollingJobsRepository(this.db);
|
|
5802
6041
|
this.paymentsRepo = new QZPayPaymentsRepository(this.db);
|
|
5803
6042
|
this.paymentMethodsRepo = new QZPayPaymentMethodsRepository(this.db);
|
|
5804
6043
|
this.invoicesRepo = new QZPayInvoicesRepository(typedDb);
|
|
@@ -5813,6 +6052,7 @@ var QZPayDrizzleStorageAdapter = class {
|
|
|
5813
6052
|
this.checkouts = this.createCheckoutStorage();
|
|
5814
6053
|
this.customers = this.createCustomerStorage();
|
|
5815
6054
|
this.subscriptions = this.createSubscriptionStorage();
|
|
6055
|
+
this.subscriptionPollingJobs = this.createSubscriptionPollingJobStorage();
|
|
5816
6056
|
this.payments = this.createPaymentStorage();
|
|
5817
6057
|
this.paymentMethods = this.createPaymentMethodStorage();
|
|
5818
6058
|
this.invoices = this.createInvoiceStorage();
|
|
@@ -5949,6 +6189,48 @@ var QZPayDrizzleStorageAdapter = class {
|
|
|
5949
6189
|
}
|
|
5950
6190
|
};
|
|
5951
6191
|
}
|
|
6192
|
+
// ==================== Subscription Polling Job Storage ====================
|
|
6193
|
+
createSubscriptionPollingJobStorage() {
|
|
6194
|
+
const repo = this.subscriptionPollingJobsRepo;
|
|
6195
|
+
return {
|
|
6196
|
+
async create(input) {
|
|
6197
|
+
if (!input.provider) {
|
|
6198
|
+
throw new Error(
|
|
6199
|
+
'QZPaySchedulePollingInput.provider is required when calling subscriptionPollingJobs.create. Pass the configured payment adapter provider (e.g., "mercadopago") explicitly.'
|
|
6200
|
+
);
|
|
6201
|
+
}
|
|
6202
|
+
const drizzleInput = mapPollingScheduleInputToDrizzleInsert({ ...input, provider: input.provider });
|
|
6203
|
+
const row = await repo.create(drizzleInput);
|
|
6204
|
+
return row ? mapDrizzlePollingJobToCore(row) : null;
|
|
6205
|
+
},
|
|
6206
|
+
async update(input) {
|
|
6207
|
+
const row = await repo.tryLockedUpdate({
|
|
6208
|
+
id: input.id,
|
|
6209
|
+
expectedVersion: input.expectedVersion,
|
|
6210
|
+
...input.status !== void 0 ? { status: input.status } : {},
|
|
6211
|
+
...input.incrementAttemptsBy !== void 0 ? { incrementAttemptsBy: input.incrementAttemptsBy } : {},
|
|
6212
|
+
...input.lastPolledAt !== void 0 ? { lastPolledAt: input.lastPolledAt } : {},
|
|
6213
|
+
...input.lastProviderStatus !== void 0 ? { lastProviderStatus: input.lastProviderStatus } : {},
|
|
6214
|
+
...input.lastError !== void 0 ? { lastError: input.lastError } : {},
|
|
6215
|
+
...input.nextPollAt !== void 0 ? { nextPollAt: input.nextPollAt } : {},
|
|
6216
|
+
...input.completedAt !== void 0 ? { completedAt: input.completedAt } : {}
|
|
6217
|
+
});
|
|
6218
|
+
return row ? mapDrizzlePollingJobToCore(row) : null;
|
|
6219
|
+
},
|
|
6220
|
+
async findById(id) {
|
|
6221
|
+
const row = await repo.findById(id);
|
|
6222
|
+
return row ? mapDrizzlePollingJobToCore(row) : null;
|
|
6223
|
+
},
|
|
6224
|
+
async findActiveBySubscriptionId(subscriptionId) {
|
|
6225
|
+
const row = await repo.findActiveBySubscriptionId(subscriptionId);
|
|
6226
|
+
return row ? mapDrizzlePollingJobToCore(row) : null;
|
|
6227
|
+
},
|
|
6228
|
+
async findDuePending(now, limit) {
|
|
6229
|
+
const rows = await repo.findDuePending(now, limit);
|
|
6230
|
+
return rows.map(mapDrizzlePollingJobToCore);
|
|
6231
|
+
}
|
|
6232
|
+
};
|
|
6233
|
+
}
|
|
5952
6234
|
// ==================== Payment Storage ====================
|
|
5953
6235
|
createPaymentStorage() {
|
|
5954
6236
|
const repo = this.paymentsRepo;
|
|
@@ -6504,9 +6786,9 @@ async function runMigrations(config) {
|
|
|
6504
6786
|
if (verbose) {
|
|
6505
6787
|
console.log("[QZPay] Starting database migrations...");
|
|
6506
6788
|
}
|
|
6507
|
-
const
|
|
6789
|
+
const sql22 = postgres2__default.default(connectionUrl, { max: 1 });
|
|
6508
6790
|
try {
|
|
6509
|
-
const db = postgresJs.drizzle(
|
|
6791
|
+
const db = postgresJs.drizzle(sql22);
|
|
6510
6792
|
await migrator.migrate(db, {
|
|
6511
6793
|
migrationsFolder
|
|
6512
6794
|
});
|
|
@@ -6517,14 +6799,14 @@ async function runMigrations(config) {
|
|
|
6517
6799
|
console.error("[QZPay] Migration failed:", error);
|
|
6518
6800
|
throw error;
|
|
6519
6801
|
} finally {
|
|
6520
|
-
await
|
|
6802
|
+
await sql22.end();
|
|
6521
6803
|
}
|
|
6522
6804
|
}
|
|
6523
6805
|
async function hasPendingMigrations(connectionUrl) {
|
|
6524
|
-
const
|
|
6806
|
+
const sql22 = postgres2__default.default(connectionUrl, { max: 1 });
|
|
6525
6807
|
try {
|
|
6526
|
-
postgresJs.drizzle(
|
|
6527
|
-
const result = await
|
|
6808
|
+
postgresJs.drizzle(sql22);
|
|
6809
|
+
const result = await sql22`
|
|
6528
6810
|
SELECT EXISTS (
|
|
6529
6811
|
SELECT FROM information_schema.tables
|
|
6530
6812
|
WHERE table_name = 'drizzle_migrations'
|
|
@@ -6535,24 +6817,24 @@ async function hasPendingMigrations(connectionUrl) {
|
|
|
6535
6817
|
}
|
|
6536
6818
|
return false;
|
|
6537
6819
|
} finally {
|
|
6538
|
-
await
|
|
6820
|
+
await sql22.end();
|
|
6539
6821
|
}
|
|
6540
6822
|
}
|
|
6541
6823
|
async function ensureDatabase(config) {
|
|
6542
6824
|
const { connectionUrl, databaseName } = config;
|
|
6543
|
-
const
|
|
6825
|
+
const sql22 = postgres2__default.default(connectionUrl, { max: 1 });
|
|
6544
6826
|
try {
|
|
6545
|
-
const result = await
|
|
6827
|
+
const result = await sql22`
|
|
6546
6828
|
SELECT 1 FROM pg_database WHERE datname = ${databaseName}
|
|
6547
6829
|
`;
|
|
6548
6830
|
if (result.length === 0) {
|
|
6549
|
-
await
|
|
6831
|
+
await sql22.unsafe(`CREATE DATABASE "${databaseName}"`);
|
|
6550
6832
|
console.log(`[QZPay] Created database: ${databaseName}`);
|
|
6551
6833
|
return true;
|
|
6552
6834
|
}
|
|
6553
6835
|
return false;
|
|
6554
6836
|
} finally {
|
|
6555
|
-
await
|
|
6837
|
+
await sql22.end();
|
|
6556
6838
|
}
|
|
6557
6839
|
}
|
|
6558
6840
|
|
|
@@ -6787,6 +7069,7 @@ async function executeTransaction(db, options, fn) {
|
|
|
6787
7069
|
return withTransaction(db, executeFn);
|
|
6788
7070
|
}
|
|
6789
7071
|
|
|
7072
|
+
exports.POLLING_JOB_DEFAULTS = POLLING_JOB_DEFAULTS;
|
|
6790
7073
|
exports.QZPAY_DRIZZLE_SCHEMA_VERSION = QZPAY_DRIZZLE_SCHEMA_VERSION;
|
|
6791
7074
|
exports.QZPAY_PAGINATION_DEFAULTS = QZPAY_PAGINATION_DEFAULTS;
|
|
6792
7075
|
exports.QZPayAddonsRepository = QZPayAddonsRepository;
|
|
@@ -6802,6 +7085,7 @@ exports.QZPayPaymentsRepository = QZPayPaymentsRepository;
|
|
|
6802
7085
|
exports.QZPayPlansRepository = QZPayPlansRepository;
|
|
6803
7086
|
exports.QZPayPricesRepository = QZPayPricesRepository;
|
|
6804
7087
|
exports.QZPayPromoCodesRepository = QZPayPromoCodesRepository;
|
|
7088
|
+
exports.QZPaySubscriptionPollingJobsRepository = QZPaySubscriptionPollingJobsRepository;
|
|
6805
7089
|
exports.QZPaySubscriptionsRepository = QZPaySubscriptionsRepository;
|
|
6806
7090
|
exports.QZPayUsageRecordsRepository = QZPayUsageRecordsRepository;
|
|
6807
7091
|
exports.QZPayVendorsRepository = QZPayVendorsRepository;
|
|
@@ -6879,6 +7163,10 @@ exports.billingSubscriptionAddonSelectSchema = billingSubscriptionAddonSelectSch
|
|
|
6879
7163
|
exports.billingSubscriptionAddons = billingSubscriptionAddons;
|
|
6880
7164
|
exports.billingSubscriptionAddonsRelations = billingSubscriptionAddonsRelations;
|
|
6881
7165
|
exports.billingSubscriptionInsertSchema = billingSubscriptionInsertSchema;
|
|
7166
|
+
exports.billingSubscriptionPollingJobInsertSchema = billingSubscriptionPollingJobInsertSchema;
|
|
7167
|
+
exports.billingSubscriptionPollingJobSelectSchema = billingSubscriptionPollingJobSelectSchema;
|
|
7168
|
+
exports.billingSubscriptionPollingJobs = billingSubscriptionPollingJobs;
|
|
7169
|
+
exports.billingSubscriptionPollingJobsRelations = billingSubscriptionPollingJobsRelations;
|
|
6882
7170
|
exports.billingSubscriptionSelectSchema = billingSubscriptionSelectSchema;
|
|
6883
7171
|
exports.billingSubscriptions = billingSubscriptions;
|
|
6884
7172
|
exports.billingSubscriptionsRelations = billingSubscriptionsRelations;
|
|
@@ -6963,6 +7251,7 @@ exports.mapDrizzleLimitToCore = mapDrizzleLimitToCore;
|
|
|
6963
7251
|
exports.mapDrizzlePaymentMethodToCore = mapDrizzlePaymentMethodToCore;
|
|
6964
7252
|
exports.mapDrizzlePaymentToCore = mapDrizzlePaymentToCore;
|
|
6965
7253
|
exports.mapDrizzlePlanToCore = mapDrizzlePlanToCore;
|
|
7254
|
+
exports.mapDrizzlePollingJobToCore = mapDrizzlePollingJobToCore;
|
|
6966
7255
|
exports.mapDrizzlePriceToCore = mapDrizzlePriceToCore;
|
|
6967
7256
|
exports.mapDrizzlePromoCodeToCore = mapDrizzlePromoCodeToCore;
|
|
6968
7257
|
exports.mapDrizzleSubscriptionAddonToCore = mapDrizzleSubscriptionAddonToCore;
|
|
@@ -6970,6 +7259,7 @@ exports.mapDrizzleSubscriptionToCore = mapDrizzleSubscriptionToCore;
|
|
|
6970
7259
|
exports.mapDrizzleUsageRecordToCore = mapDrizzleUsageRecordToCore;
|
|
6971
7260
|
exports.mapDrizzleVendorPayoutToCore = mapDrizzleVendorPayoutToCore;
|
|
6972
7261
|
exports.mapDrizzleVendorToCore = mapDrizzleVendorToCore;
|
|
7262
|
+
exports.mapPollingScheduleInputToDrizzleInsert = mapPollingScheduleInputToDrizzleInsert;
|
|
6973
7263
|
exports.normalizePaginationOptions = normalizePaginationOptions;
|
|
6974
7264
|
exports.offsetToPage = offsetToPage;
|
|
6975
7265
|
exports.onlyDeleted = onlyDeleted;
|