@arcblock/payment-service 1.29.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.
- package/dist/drivers.d.ts +144 -0
- package/dist/drivers.js +850 -0
- package/dist/index.d.ts +61 -0
- package/dist/index.js +76355 -0
- package/package.json +88 -0
package/dist/drivers.js
ADDED
|
@@ -0,0 +1,850 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __create = Object.create;
|
|
3
|
+
var __defProp = Object.defineProperty;
|
|
4
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
+
var __esm = (fn, res) => function __init() {
|
|
9
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
10
|
+
};
|
|
11
|
+
var __export = (target, all) => {
|
|
12
|
+
for (var name in all)
|
|
13
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
14
|
+
};
|
|
15
|
+
var __copyProps = (to, from, except, desc) => {
|
|
16
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
17
|
+
for (let key of __getOwnPropNames(from))
|
|
18
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
19
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
20
|
+
}
|
|
21
|
+
return to;
|
|
22
|
+
};
|
|
23
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
24
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
25
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
26
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
27
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
28
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
29
|
+
mod
|
|
30
|
+
));
|
|
31
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
32
|
+
|
|
33
|
+
// ../../blocklets/core/api/src/libs/drivers/db.ts
|
|
34
|
+
function createNodeDbDriver(sequelize) {
|
|
35
|
+
if (!sequelize) throw new Error("createNodeDbDriver: sequelize instance is required");
|
|
36
|
+
const toBind = (sql) => {
|
|
37
|
+
let i = 0;
|
|
38
|
+
return sql.replace(/\?/g, () => {
|
|
39
|
+
i += 1;
|
|
40
|
+
return `$${i}`;
|
|
41
|
+
});
|
|
42
|
+
};
|
|
43
|
+
return {
|
|
44
|
+
kind: "node",
|
|
45
|
+
sequelize,
|
|
46
|
+
async exec(sql, params = []) {
|
|
47
|
+
const [, meta] = await sequelize.query(toBind(sql), { bind: params });
|
|
48
|
+
const changes = (meta && (meta.changes ?? meta.rowCount)) ?? 0;
|
|
49
|
+
return { changes };
|
|
50
|
+
},
|
|
51
|
+
async all(sql, params = []) {
|
|
52
|
+
const rows = await sequelize.query(toBind(sql), {
|
|
53
|
+
bind: params,
|
|
54
|
+
type: sequelize.QueryTypes ? sequelize.QueryTypes.SELECT : "SELECT"
|
|
55
|
+
});
|
|
56
|
+
return rows;
|
|
57
|
+
},
|
|
58
|
+
async get(sql, params = []) {
|
|
59
|
+
const rows = await sequelize.query(toBind(sql), {
|
|
60
|
+
bind: params,
|
|
61
|
+
type: sequelize.QueryTypes ? sequelize.QueryTypes.SELECT : "SELECT"
|
|
62
|
+
});
|
|
63
|
+
return rows[0] ?? null;
|
|
64
|
+
},
|
|
65
|
+
// eslint-disable-next-line require-await -- async contract; returns the transaction promise
|
|
66
|
+
async batch(ops) {
|
|
67
|
+
return sequelize.transaction(async (t) => {
|
|
68
|
+
const results = [];
|
|
69
|
+
for (const op of ops) {
|
|
70
|
+
const rows = await sequelize.query(toBind(op.sql), { bind: op.params ?? [], transaction: t });
|
|
71
|
+
results.push(rows);
|
|
72
|
+
}
|
|
73
|
+
return results;
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
}
|
|
78
|
+
function createD1DbDriver(binding) {
|
|
79
|
+
if (!binding) throw new Error("createD1DbDriver: D1 binding (or getter) is required");
|
|
80
|
+
const resolve = () => {
|
|
81
|
+
const b = typeof binding === "function" ? binding() : binding;
|
|
82
|
+
if (!b) throw new Error("createD1DbDriver: D1 binding is not available");
|
|
83
|
+
return b;
|
|
84
|
+
};
|
|
85
|
+
return {
|
|
86
|
+
kind: "d1",
|
|
87
|
+
async exec(sql, params = []) {
|
|
88
|
+
const res = await resolve().prepare(sql).bind(...params).run();
|
|
89
|
+
const changes = res?.meta?.changes ?? res?.meta?.rows_written ?? 0;
|
|
90
|
+
return { changes };
|
|
91
|
+
},
|
|
92
|
+
async all(sql, params = []) {
|
|
93
|
+
const res = await resolve().prepare(sql).bind(...params).all();
|
|
94
|
+
return res?.results ?? [];
|
|
95
|
+
},
|
|
96
|
+
async get(sql, params = []) {
|
|
97
|
+
const row = await resolve().prepare(sql).bind(...params).first();
|
|
98
|
+
return row ?? null;
|
|
99
|
+
},
|
|
100
|
+
// eslint-disable-next-line require-await -- async contract; resolve() throws surface as rejection
|
|
101
|
+
async batch(ops) {
|
|
102
|
+
const b = resolve();
|
|
103
|
+
const stmts = ops.map((op) => b.prepare(op.sql).bind(...op.params ?? []));
|
|
104
|
+
return b.batch(stmts);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
var init_db = __esm({
|
|
109
|
+
"../../blocklets/core/api/src/libs/drivers/db.ts"() {
|
|
110
|
+
"use strict";
|
|
111
|
+
}
|
|
112
|
+
});
|
|
113
|
+
|
|
114
|
+
// ../../blocklets/core/api/src/libs/drivers/locks.ts
|
|
115
|
+
function scopedLockName(name, instanceDid, scope) {
|
|
116
|
+
if (scope === "global") return name;
|
|
117
|
+
if (!instanceDid) {
|
|
118
|
+
throw new Error("scopedLockName: tenant-scoped lock requires a non-empty instanceDid");
|
|
119
|
+
}
|
|
120
|
+
return `tenant:${instanceDid}::${name}`;
|
|
121
|
+
}
|
|
122
|
+
function createMemoryLocksDriver() {
|
|
123
|
+
const locks = /* @__PURE__ */ new Map();
|
|
124
|
+
return {
|
|
125
|
+
kind: "memory",
|
|
126
|
+
getLock(name) {
|
|
127
|
+
const exist = locks.get(name);
|
|
128
|
+
if (exist instanceof MemoryLock) return exist;
|
|
129
|
+
const lock = new MemoryLock(name);
|
|
130
|
+
locks.set(name, lock);
|
|
131
|
+
return lock;
|
|
132
|
+
}
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
function simpleId() {
|
|
136
|
+
nanoidCounter += 1;
|
|
137
|
+
return `${Date.now().toString(36)}-${nanoidCounter.toString(36)}-${Math.random().toString(36).slice(2, 6)}`;
|
|
138
|
+
}
|
|
139
|
+
function createD1LocksDriver(getBinding) {
|
|
140
|
+
return {
|
|
141
|
+
kind: "d1",
|
|
142
|
+
getLock(name, options) {
|
|
143
|
+
return new D1Lock(getBinding, name, options);
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
var EventEmitter, MemoryLock, nanoidCounter, D1Lock;
|
|
148
|
+
var init_locks = __esm({
|
|
149
|
+
"../../blocklets/core/api/src/libs/drivers/locks.ts"() {
|
|
150
|
+
"use strict";
|
|
151
|
+
({ EventEmitter } = require("events"));
|
|
152
|
+
MemoryLock = class {
|
|
153
|
+
constructor(name) {
|
|
154
|
+
this.name = name;
|
|
155
|
+
this.locked = false;
|
|
156
|
+
this.events = new EventEmitter();
|
|
157
|
+
}
|
|
158
|
+
acquire() {
|
|
159
|
+
return new Promise((resolve) => {
|
|
160
|
+
if (this.locked) {
|
|
161
|
+
const tryAcquire = () => {
|
|
162
|
+
if (!this.locked) {
|
|
163
|
+
this.locked = true;
|
|
164
|
+
this.events.removeListener("release", tryAcquire);
|
|
165
|
+
resolve(true);
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
this.events.on("release", tryAcquire);
|
|
169
|
+
} else {
|
|
170
|
+
this.locked = true;
|
|
171
|
+
resolve(true);
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
release() {
|
|
176
|
+
this.locked = false;
|
|
177
|
+
setImmediate(() => this.events.emit("release"));
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
nanoidCounter = 0;
|
|
181
|
+
D1Lock = class {
|
|
182
|
+
constructor(getBinding, name, options) {
|
|
183
|
+
this.getBinding = getBinding;
|
|
184
|
+
this.name = name;
|
|
185
|
+
this.owner = simpleId();
|
|
186
|
+
this.locked = false;
|
|
187
|
+
this.ttl = options?.ttl || 5e3;
|
|
188
|
+
}
|
|
189
|
+
async acquire(maxWaitMs = 1e4) {
|
|
190
|
+
const db = this.getBinding();
|
|
191
|
+
const deadline = Date.now() + maxWaitMs;
|
|
192
|
+
let delay = 30;
|
|
193
|
+
while (Date.now() < deadline) {
|
|
194
|
+
const now = Date.now();
|
|
195
|
+
try {
|
|
196
|
+
const batchResult = await db.batch([
|
|
197
|
+
db.prepare("DELETE FROM _locks WHERE name = ? AND expires_at < ?").bind(this.name, now),
|
|
198
|
+
db.prepare("INSERT OR IGNORE INTO _locks (name, owner, expires_at) VALUES (?, ?, ?)").bind(this.name, this.owner, now + this.ttl),
|
|
199
|
+
db.prepare("SELECT owner FROM _locks WHERE name = ?").bind(this.name)
|
|
200
|
+
]);
|
|
201
|
+
const row = batchResult[2]?.results?.[0];
|
|
202
|
+
if (row?.owner === this.owner) {
|
|
203
|
+
this.locked = true;
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
} catch (err) {
|
|
207
|
+
console.error(`[D1Lock] acquire error for "${this.name}":`, err?.message || err);
|
|
208
|
+
}
|
|
209
|
+
const waitMs = delay + Math.random() * delay * 0.3;
|
|
210
|
+
await new Promise((r) => setTimeout(r, waitMs));
|
|
211
|
+
delay = Math.min(delay * 2, 500);
|
|
212
|
+
}
|
|
213
|
+
throw new Error(`[D1Lock] Failed to acquire lock "${this.name}" within ${maxWaitMs}ms`);
|
|
214
|
+
}
|
|
215
|
+
release() {
|
|
216
|
+
if (!this.locked) return;
|
|
217
|
+
this.locked = false;
|
|
218
|
+
try {
|
|
219
|
+
const db = this.getBinding();
|
|
220
|
+
const promise = db.prepare("DELETE FROM _locks WHERE name = ? AND owner = ?").bind(this.name, this.owner).run().catch((err) => console.error(`[D1Lock] release error for "${this.name}":`, err?.message || err));
|
|
221
|
+
const isHttp = globalThis.__cfHttpContext__;
|
|
222
|
+
if (isHttp) {
|
|
223
|
+
const waitUntil = globalThis.__cfWaitUntil__;
|
|
224
|
+
if (typeof waitUntil === "function") waitUntil(promise);
|
|
225
|
+
} else {
|
|
226
|
+
const pending = globalThis.__cfPendingJobs__;
|
|
227
|
+
if (Array.isArray(pending)) pending.push(promise);
|
|
228
|
+
}
|
|
229
|
+
} catch (err) {
|
|
230
|
+
console.error(`[D1Lock] release setup error for "${this.name}":`, err?.message || err);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
// ../../blocklets/core/api/src/libs/drivers/auth-storage.ts
|
|
238
|
+
function createAuthStorage(driver) {
|
|
239
|
+
return new DbAuthStorage(driver);
|
|
240
|
+
}
|
|
241
|
+
var EventEmitter2, TABLE, DbAuthStorage;
|
|
242
|
+
var init_auth_storage = __esm({
|
|
243
|
+
"../../blocklets/core/api/src/libs/drivers/auth-storage.ts"() {
|
|
244
|
+
"use strict";
|
|
245
|
+
({ EventEmitter: EventEmitter2 } = require("events"));
|
|
246
|
+
TABLE = "did_auth_records";
|
|
247
|
+
DbAuthStorage = class extends EventEmitter2 {
|
|
248
|
+
constructor(driver) {
|
|
249
|
+
super();
|
|
250
|
+
this.ready = null;
|
|
251
|
+
if (!driver) throw new Error("DbAuthStorage requires a db driver");
|
|
252
|
+
this.driver = driver;
|
|
253
|
+
}
|
|
254
|
+
// idempotent lazy schema — the original file store self-managed its db file
|
|
255
|
+
// (it was never part of the Umzug/D1 migration chain), so we keep that here.
|
|
256
|
+
ensureTable() {
|
|
257
|
+
if (!this.ready) {
|
|
258
|
+
this.ready = this.driver.exec(
|
|
259
|
+
`CREATE TABLE IF NOT EXISTS ${TABLE} (token TEXT PRIMARY KEY, doc TEXT NOT NULL, created_at INTEGER NOT NULL, updated_at INTEGER NOT NULL)`
|
|
260
|
+
).then(() => void 0).catch((err) => {
|
|
261
|
+
this.ready = null;
|
|
262
|
+
throw err;
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
return this.ready;
|
|
266
|
+
}
|
|
267
|
+
async read(token) {
|
|
268
|
+
if (!token) throw new Error("token is required to read auth record");
|
|
269
|
+
await this.ensureTable();
|
|
270
|
+
const row = await this.driver.get(`SELECT doc FROM ${TABLE} WHERE token = ?`, [token]);
|
|
271
|
+
if (!row) return null;
|
|
272
|
+
return JSON.parse(row.doc);
|
|
273
|
+
}
|
|
274
|
+
async create(token, status = "created") {
|
|
275
|
+
if (!token) throw new Error("token is required to create auth record");
|
|
276
|
+
await this.ensureTable();
|
|
277
|
+
const now = Date.now();
|
|
278
|
+
const doc = { token, status, createdAt: now, updatedAt: now };
|
|
279
|
+
await this.driver.exec(`INSERT INTO ${TABLE} (token, doc, created_at, updated_at) VALUES (?, ?, ?, ?)`, [
|
|
280
|
+
token,
|
|
281
|
+
JSON.stringify(doc),
|
|
282
|
+
now,
|
|
283
|
+
now
|
|
284
|
+
]);
|
|
285
|
+
this.emit("create", doc);
|
|
286
|
+
return doc;
|
|
287
|
+
}
|
|
288
|
+
async update(token, updates = {}) {
|
|
289
|
+
if (!token) throw new Error("token is required to update auth record");
|
|
290
|
+
await this.ensureTable();
|
|
291
|
+
const current = await this.read(token);
|
|
292
|
+
if (!current) return null;
|
|
293
|
+
const now = Date.now();
|
|
294
|
+
const merged = { ...current, ...updates, token, updatedAt: now };
|
|
295
|
+
await this.driver.exec(`UPDATE ${TABLE} SET doc = ?, updated_at = ? WHERE token = ?`, [
|
|
296
|
+
JSON.stringify(merged),
|
|
297
|
+
now,
|
|
298
|
+
token
|
|
299
|
+
]);
|
|
300
|
+
this.emit("update", merged);
|
|
301
|
+
return merged;
|
|
302
|
+
}
|
|
303
|
+
async delete(token) {
|
|
304
|
+
if (!token) throw new Error("token is required to delete auth record");
|
|
305
|
+
await this.ensureTable();
|
|
306
|
+
const res = await this.driver.exec(`DELETE FROM ${TABLE} WHERE token = ?`, [token]);
|
|
307
|
+
this.emit("destroy", token);
|
|
308
|
+
return res.changes;
|
|
309
|
+
}
|
|
310
|
+
async exist(token, did) {
|
|
311
|
+
if (!token) throw new Error("token is required to check auth record");
|
|
312
|
+
const doc = await this.read(token);
|
|
313
|
+
return !!doc && doc.did === did;
|
|
314
|
+
}
|
|
315
|
+
async clear() {
|
|
316
|
+
await this.ensureTable();
|
|
317
|
+
await this.driver.exec(`DELETE FROM ${TABLE}`);
|
|
318
|
+
}
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// ../../blocklets/core/api/src/libs/drivers/queue.ts
|
|
324
|
+
function setQueueHostHooks(hooks) {
|
|
325
|
+
activeQueueHostHooks = hooks;
|
|
326
|
+
}
|
|
327
|
+
function getQueueHostHooks() {
|
|
328
|
+
return activeQueueHostHooks;
|
|
329
|
+
}
|
|
330
|
+
var nodeQueueHostHooks, activeQueueHostHooks;
|
|
331
|
+
var init_queue = __esm({
|
|
332
|
+
"../../blocklets/core/api/src/libs/drivers/queue.ts"() {
|
|
333
|
+
"use strict";
|
|
334
|
+
nodeQueueHostHooks = {
|
|
335
|
+
async flush() {
|
|
336
|
+
}
|
|
337
|
+
};
|
|
338
|
+
activeQueueHostHooks = nodeQueueHostHooks;
|
|
339
|
+
}
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
// ../../blocklets/core/api/src/libs/drivers/cron.ts
|
|
343
|
+
function parseField(field, min, max) {
|
|
344
|
+
if (field === "*") return null;
|
|
345
|
+
const values = /* @__PURE__ */ new Set();
|
|
346
|
+
for (const part of field.split(",")) {
|
|
347
|
+
const stepMatch = part.match(/^\*\/(\d+)$/);
|
|
348
|
+
const rangeMatch = part.match(/^(\d+)-(\d+)$/);
|
|
349
|
+
if (stepMatch) {
|
|
350
|
+
const step = parseInt(stepMatch[1], 10);
|
|
351
|
+
for (let i = min; i <= max; i += step) values.add(i);
|
|
352
|
+
} else if (rangeMatch) {
|
|
353
|
+
const from = parseInt(rangeMatch[1], 10);
|
|
354
|
+
const to = parseInt(rangeMatch[2], 10);
|
|
355
|
+
for (let i = from; i <= to; i += 1) values.add(i);
|
|
356
|
+
} else {
|
|
357
|
+
const num = parseInt(part, 10);
|
|
358
|
+
if (!Number.isNaN(num)) values.add(num);
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
return values.size > 0 ? Array.from(values) : null;
|
|
362
|
+
}
|
|
363
|
+
function matchesCron(cronExpr, date) {
|
|
364
|
+
const fields = cronExpr.trim().split(/\s+/);
|
|
365
|
+
if (fields.length < 5) return true;
|
|
366
|
+
const offset = fields.length >= 6 ? 1 : 0;
|
|
367
|
+
const minuteField = parseField(fields[offset], 0, 59);
|
|
368
|
+
const hourField = parseField(fields[offset + 1], 0, 23);
|
|
369
|
+
const domField = parseField(fields[offset + 2], 1, 31);
|
|
370
|
+
const monthField = parseField(fields[offset + 3], 1, 12);
|
|
371
|
+
const dowField = parseField(fields[offset + 4], 0, 6);
|
|
372
|
+
const m = date.getUTCMinutes();
|
|
373
|
+
const h = date.getUTCHours();
|
|
374
|
+
const dom = date.getUTCDate();
|
|
375
|
+
const month = date.getUTCMonth() + 1;
|
|
376
|
+
const dow = date.getUTCDay();
|
|
377
|
+
if (minuteField && !minuteField.includes(m)) return false;
|
|
378
|
+
if (hourField && !hourField.includes(h)) return false;
|
|
379
|
+
if (domField && !domField.includes(dom)) return false;
|
|
380
|
+
if (monthField && !monthField.includes(month)) return false;
|
|
381
|
+
if (dowField && !dowField.includes(dow)) return false;
|
|
382
|
+
return true;
|
|
383
|
+
}
|
|
384
|
+
function shouldRunInWindow(cronExpr, date) {
|
|
385
|
+
return matchesCron(cronExpr, date);
|
|
386
|
+
}
|
|
387
|
+
function createCronRegistry(kind) {
|
|
388
|
+
const jobs = [];
|
|
389
|
+
let onErrorHandler;
|
|
390
|
+
return {
|
|
391
|
+
kind,
|
|
392
|
+
register(next, onError) {
|
|
393
|
+
jobs.length = 0;
|
|
394
|
+
onErrorHandler = onError;
|
|
395
|
+
for (const job of next || []) {
|
|
396
|
+
if (job.name && job.time && typeof job.fn === "function") jobs.push(job);
|
|
397
|
+
}
|
|
398
|
+
},
|
|
399
|
+
addJob(name, time, fn, options) {
|
|
400
|
+
jobs.push({ name, time, fn, options });
|
|
401
|
+
},
|
|
402
|
+
async runDue(now = /* @__PURE__ */ new Date()) {
|
|
403
|
+
const ran = [];
|
|
404
|
+
const skipped = [];
|
|
405
|
+
for (const job of jobs) {
|
|
406
|
+
if (shouldRunInWindow(job.time, now)) {
|
|
407
|
+
ran.push(job.name);
|
|
408
|
+
try {
|
|
409
|
+
await job.fn();
|
|
410
|
+
} catch (err) {
|
|
411
|
+
onErrorHandler?.(err, job.name);
|
|
412
|
+
}
|
|
413
|
+
} else {
|
|
414
|
+
skipped.push(job.name);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
return { ran, skipped };
|
|
418
|
+
},
|
|
419
|
+
async runJob(name) {
|
|
420
|
+
const job = jobs.find((j) => j.name === name);
|
|
421
|
+
if (!job) return;
|
|
422
|
+
try {
|
|
423
|
+
await job.fn();
|
|
424
|
+
} catch (err) {
|
|
425
|
+
onErrorHandler?.(err, name);
|
|
426
|
+
}
|
|
427
|
+
},
|
|
428
|
+
getJobNames() {
|
|
429
|
+
return jobs.map((j) => `${j.name} (${j.time})`);
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
}
|
|
433
|
+
function setCronDriver(driver) {
|
|
434
|
+
activeCronDriver = driver;
|
|
435
|
+
}
|
|
436
|
+
function getCronDriver() {
|
|
437
|
+
return activeCronDriver;
|
|
438
|
+
}
|
|
439
|
+
var activeCronDriver;
|
|
440
|
+
var init_cron = __esm({
|
|
441
|
+
"../../blocklets/core/api/src/libs/drivers/cron.ts"() {
|
|
442
|
+
"use strict";
|
|
443
|
+
activeCronDriver = createCronRegistry("node-cron");
|
|
444
|
+
}
|
|
445
|
+
});
|
|
446
|
+
|
|
447
|
+
// ../../blocklets/core/api/src/libs/drivers/migrate-runner.ts
|
|
448
|
+
function splitStatements(sql) {
|
|
449
|
+
return sql.split("\n").filter((line) => !line.trim().startsWith("--")).join("\n").split(";").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
450
|
+
}
|
|
451
|
+
async function applySqlMigrations(driver, migrations) {
|
|
452
|
+
await driver.exec("CREATE TABLE IF NOT EXISTS _sql_migrations (name TEXT PRIMARY KEY, applied_at TEXT NOT NULL)");
|
|
453
|
+
const rows = await driver.all("SELECT name FROM _sql_migrations");
|
|
454
|
+
const applied = new Set(rows.map((r) => r.name));
|
|
455
|
+
const ran = [];
|
|
456
|
+
const pending = migrations.filter((m) => !applied.has(m.name));
|
|
457
|
+
for (const m of pending) {
|
|
458
|
+
const ops = splitStatements(m.sql).map((sql) => ({ sql }));
|
|
459
|
+
ops.push({
|
|
460
|
+
sql: "INSERT INTO _sql_migrations (name, applied_at) VALUES (?, ?)",
|
|
461
|
+
params: [m.name, (/* @__PURE__ */ new Date()).toISOString()]
|
|
462
|
+
});
|
|
463
|
+
await driver.batch(ops);
|
|
464
|
+
ran.push(m.name);
|
|
465
|
+
}
|
|
466
|
+
return ran;
|
|
467
|
+
}
|
|
468
|
+
var init_migrate_runner = __esm({
|
|
469
|
+
"../../blocklets/core/api/src/libs/drivers/migrate-runner.ts"() {
|
|
470
|
+
"use strict";
|
|
471
|
+
}
|
|
472
|
+
});
|
|
473
|
+
|
|
474
|
+
// ../../blocklets/core/api/src/store/sql-migrations.ts
|
|
475
|
+
var paymentCoreSqlMigrations;
|
|
476
|
+
var init_sql_migrations = __esm({
|
|
477
|
+
"../../blocklets/core/api/src/store/sql-migrations.ts"() {
|
|
478
|
+
"use strict";
|
|
479
|
+
paymentCoreSqlMigrations = [
|
|
480
|
+
{ name: "0001_initial_schema.sql", sql: "-- Payment Kit: Complete D1 schema\n-- All statements use IF NOT EXISTS for idempotency.\n\nCREATE TABLE IF NOT EXISTS `archive_locks` (`id` VARCHAR(40) NOT NULL PRIMARY KEY, `locked_by` VARCHAR(64), `locked_at` INTEGER, `expires_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `archive_metadata` (`id` VARCHAR(40) NOT NULL PRIMARY KEY, `archive_file` VARCHAR(128) NOT NULL, `date_range_start` INTEGER NOT NULL, `date_range_end` INTEGER NOT NULL, `tables` JSON NOT NULL DEFAULT '{}', `total_records` INTEGER NOT NULL DEFAULT 0, `checksum` VARCHAR(128), `file_size` INTEGER, `duration_ms` INTEGER, `triggered_by` TEXT NOT NULL, `triggered_by_user_id` VARCHAR(64), `status` TEXT NOT NULL, `error` TEXT, `query_count` INTEGER NOT NULL DEFAULT 0, `query_actor_ids` JSON DEFAULT '[]', `last_queried_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `auto_recharge_configs` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `customer_id` VARCHAR(18) NOT NULL REFERENCES `customers` (`id`), `livemode` TINYINT(1) NOT NULL, `enabled` TINYINT(1) NOT NULL DEFAULT 0, `threshold` VARCHAR(32) NOT NULL, `payment_method_id` VARCHAR(15), `currency_id` VARCHAR(15) NOT NULL, `recharge_currency_id` VARCHAR(15), `price_id` VARCHAR(32) NOT NULL, `quantity` INTEGER NOT NULL DEFAULT 1, `payment_settings` JSON DEFAULT '{\"payment_method_types\":[],\"payment_method_options\":{}}', `payment_details` JSON, `daily_limits` JSON DEFAULT '{\"max_attempts\":0,\"max_amount\":\"0\"}', `last_recharge_date` VARCHAR(10), `daily_stats` JSON NOT NULL DEFAULT '{\"attempt_count\":0,\"total_amount\":\"0\"}', `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `slippage_config` JSON);\n\nCREATE TABLE IF NOT EXISTS `checkout_sessions` (`id` VARCHAR(64) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `client_reference_id` VARCHAR(128), `currency_id` VARCHAR(15) NOT NULL, `invoice_id` VARCHAR(30), `customer_id` VARCHAR(30), `customer_did` VARCHAR(40), `payment_link_id` VARCHAR(30), `subscription_id` VARCHAR(30), `recovered_from` VARCHAR(30), `payment_intent_id` VARCHAR(30), `mode` TEXT NOT NULL, `status` TEXT NOT NULL, `payment_status` TEXT NOT NULL, `line_items` JSON NOT NULL, `amount_subtotal` VARCHAR(32) NOT NULL, `amount_total` VARCHAR(32) NOT NULL, `total_details` JSON NOT NULL, `url` VARCHAR(512), `cancel_url` VARCHAR(512), `success_url` VARCHAR(512), `currency_conversion` JSON, `after_expiration` JSON, `allow_promotion_codes` TINYINT(1) DEFAULT 0, `consent_collection` JSON, `consent` JSON, `custom_fields` JSON DEFAULT '[]', `custom_text` JSON, `customer_creation` TEXT NOT NULL, `customer_update` JSON DEFAULT '{\"address\":\"never\",\"name\":\"never\",\"shipping\":\"never\"}', `expires_at` INTEGER, `invoice_creation` JSON, `payment_method_types` JSON DEFAULT '[]', `phone_number_collection` JSON, `billing_address_collection` TEXT NOT NULL DEFAULT 'auto', `submit_type` TEXT NOT NULL, `subscription_data` JSON, `payment_details` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `nft_mint_settings` JSON, `payment_intent_data` JSON, `nft_mint_details` JSON, `nft_mint_status` TEXT NOT NULL DEFAULT 'disabled', `cross_sell_behavior` TEXT DEFAULT 'auto', `setup_intent_id` VARCHAR(30), `enable_subscription_grouping` TINYINT(1) DEFAULT 0, `subscription_groups` JSON, `success_subscription_count` INTEGER DEFAULT 0, \"discounts\" JSON, `fulfillment_status` VARCHAR(255), `vendor_info` JSON, `slippage_percent` DECIMAL(5,2) NOT NULL DEFAULT 0.5);\n\nCREATE TABLE IF NOT EXISTS `coupons` (`id` VARCHAR(15) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount_off` VARCHAR(32) DEFAULT '0', `percent_off` INTEGER DEFAULT '0', `currency_id` VARCHAR(15) NOT NULL, `duration` TEXT, `duration_in_months` INTEGER NOT NULL, `name` VARCHAR(64) NOT NULL, `applies_to` JSON, `currency_options` JSON DEFAULT '{}', `max_redemptions` INTEGER, `times_redeemed` INTEGER DEFAULT '0', `valid` TINYINT(1) DEFAULT 0, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `created_via` TEXT, `locked` TINYINT(1) NOT NULL DEFAULT 0, `redeem_by` INTEGER, `redeem_by_new` INTEGER, `description` TEXT);\n\nCREATE TABLE IF NOT EXISTS `credit_grants` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `object` VARCHAR(32) NOT NULL DEFAULT 'credit_grant', `amount` VARCHAR(32) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `applicability_config` JSON, `category` TEXT NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `effective_at` INTEGER, `expires_at` INTEGER, `livemode` TINYINT(1) NOT NULL, `metadata` JSON, `name` VARCHAR(255), `priority` INTEGER NOT NULL DEFAULT 50, `test_clock` VARCHAR(32), `voided_at` INTEGER, `status` TEXT NOT NULL DEFAULT 'granted', `remaining_amount` VARCHAR(32) NOT NULL, `created_by` VARCHAR(40), `updated_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `chain_status` TEXT, `chain_detail` JSON);\n\nCREATE TABLE IF NOT EXISTS `credit_transactions` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `quantity` VARCHAR(32) NOT NULL, `credit_amount` VARCHAR(32) NOT NULL, `remaining_balance` VARCHAR(32) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `credit_grant_id` VARCHAR(18) NOT NULL, `meter_id` VARCHAR(18), `subscription_id` VARCHAR(18), `source` VARCHAR(255), `meter_event_name` VARCHAR(128) NOT NULL, `meter_unit` VARCHAR(32) NOT NULL, `description` TEXT, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `transfer_status` TEXT, `transfer_hash` VARCHAR(255));\n\nCREATE TABLE IF NOT EXISTS `customers` (`id` VARCHAR(18) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `did` VARCHAR(40) NOT NULL, `address` JSON, `description` VARCHAR(512), `name` VARCHAR(64), `email` VARCHAR(128), `phone` VARCHAR(32), `shipping` JSON, `balance` VARCHAR(32) DEFAULT '0', `currency_id` VARCHAR(15), `delinquent` TINYINT(1) NOT NULL, `discount_id` VARCHAR(32), `metadata` JSON, `invoice_credit_balance` JSON, `invoice_prefix` VARCHAR(30), `invoice_settings` JSON, `next_invoice_sequence` NUMBER DEFAULT '1', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `token_balance` JSON DEFAULT '\"{}\"', `last_sync_at` INTEGER, `preference` JSON DEFAULT '\"{\\\"notification\\\":{\\\"frequency\\\":\\\"monthly\\\",\\\"schedule\\\":{\\\"time\\\":\\\"10:00\\\",\\\"date\\\":1}}}\"');\n\nCREATE TABLE IF NOT EXISTS `discounts` (`id` VARCHAR(15) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `coupon_id` VARCHAR(30) NOT NULL, `customer_id` VARCHAR(30) NOT NULL, `promotion_code_id` VARCHAR(30), `subscription_id` VARCHAR(30), `checkout_session_id` VARCHAR(30), `invoice_id` VARCHAR(30), `invoice_item_id` VARCHAR(30), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `verification_method` VARCHAR(50), `verification_data` JSON, `start` INTEGER NOT NULL, `end` INTEGER, `confirmed` TINYINT(1) NOT NULL DEFAULT 1);\n\nCREATE TABLE IF NOT EXISTS `events` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `type` VARCHAR(128) NOT NULL, `object_type` VARCHAR(64) NOT NULL, `object_id` VARCHAR(64) NOT NULL, `data` JSON NOT NULL, `request` JSON, `pending_webhooks` INTEGER NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `exchange_rate_providers` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `name` VARCHAR(64) NOT NULL UNIQUE, `enabled` TINYINT(1) NOT NULL DEFAULT 1, `priority` INTEGER NOT NULL DEFAULT 1, `status` TEXT NOT NULL DEFAULT 'active', `paused_reason` VARCHAR(512), `config` JSON, `last_success_at` DATETIME, `last_failure_at` DATETIME, `failure_count` INTEGER NOT NULL DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `type` VARCHAR(32) NOT NULL DEFAULT 'token-data');\n\nCREATE TABLE IF NOT EXISTS `invoice_items` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `quantity` INTEGER NOT NULL, `description` VARCHAR(256) NOT NULL, `period` JSON, `customer_id` VARCHAR(18) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `price_id` VARCHAR(30) NOT NULL, `invoice_id` VARCHAR(30) NOT NULL, `subscription_id` VARCHAR(30), `subscription_item_id` VARCHAR(30), `discountable` TINYINT(1) NOT NULL, `discount_amounts` JSON DEFAULT '[]', `discounts` JSON DEFAULT '[]', `proration` TINYINT(1) DEFAULT 0, `proration_details` JSON, `metadata` JSON DEFAULT '{}', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `tax_rate_id` VARCHAR(30));\n\nCREATE TABLE IF NOT EXISTS `invoices` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `auto_advance` TINYINT(1) NOT NULL, `account_country` VARCHAR(64), `account_name` VARCHAR(64), `charge_id` VARCHAR(30), `collection_method` TEXT NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `description` VARCHAR(512), `hosted_invoice_url` VARCHAR(512), `payment_intent_id` VARCHAR(30), `period_end` INTEGER DEFAULT 0, `period_start` INTEGER DEFAULT 0, `status` TEXT NOT NULL, `checkout_session_id` VARCHAR(64), `subscription_id` VARCHAR(30), `subscription_details` JSON DEFAULT '{}', `subscription_proration_date` INTEGER, `total` VARCHAR(32) NOT NULL, `subtotal` VARCHAR(32) NOT NULL, `subtotal_excluding_tax` VARCHAR(32) NOT NULL, `tax` VARCHAR(32) DEFAULT '0', `amount_due` VARCHAR(32) NOT NULL, `amount_paid` VARCHAR(32) DEFAULT '0', `amount_remaining` VARCHAR(32) NOT NULL, `amount_shipping` VARCHAR(32) DEFAULT '0', `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_payment_attempt` INTEGER, `billing_reason` TEXT, `custom_fields` JSON DEFAULT '[]', `customer_address` JSON, `customer_name` VARCHAR(64), `customer_email` VARCHAR(128), `customer_phone` VARCHAR(32), `customer_shipping` JSON, `default_payment_method_id` VARCHAR(30), `discounts` JSON DEFAULT '[]', `due_date` INTEGER, `effective_at` INTEGER, `ending_balance` VARCHAR(32) DEFAULT '0', `footer` VARCHAR(512), `from_invoice_id` VARCHAR(30), `invoice_pdf` VARCHAR(512), `last_finalization_error` JSON, `latest_revision` VARCHAR(30), `number` VARCHAR(64), `paid` TINYINT(1) DEFAULT 0, `paid_out_of_band` TINYINT(1) DEFAULT 0, `payment_settings` JSON, `post_payment_credit_notes_amount` VARCHAR(32) DEFAULT '0', `pre_payment_credit_notes_amount` VARCHAR(32) DEFAULT '0', `quote_id` VARCHAR(30), `receipt_number` VARCHAR(64), `days_until_due` NUMBER, `rendering_options` JSON, `starting_balance` VARCHAR(32) DEFAULT '0', `statement_descriptor` VARCHAR(64), `status_transitions` JSON DEFAULT '{}', `test_clock_id` VARCHAR(30), `threshold_reason` JSON, `total_discount_amounts` JSON DEFAULT '[]', `webhooks_delivered_at` INTEGER, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `starting_token_balance` JSON DEFAULT '\"{}\"', `ending_token_balance` JSON DEFAULT '\"{}\"');\n\nCREATE TABLE IF NOT EXISTS `jobs` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `queue` VARCHAR(32) NOT NULL, `job` JSON NOT NULL, `retry_count` INTEGER DEFAULT 0, `delay` INTEGER DEFAULT -1, `will_run_at` INTEGER DEFAULT -1, `cancelled` TINYINT(1) DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `locks` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `lock_at` INTEGER DEFAULT 0, `release_at` INTEGER DEFAULT -1, `reason` VARCHAR(255), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `meter_events` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `event_name` VARCHAR(128) NOT NULL, `timestamp` INTEGER NOT NULL, `payload` JSON NOT NULL, `identifier` VARCHAR(255) NOT NULL UNIQUE, `livemode` TINYINT(1) NOT NULL, `status` TEXT NOT NULL DEFAULT 'pending', `attempt_count` INTEGER NOT NULL DEFAULT 0, `next_attempt` INTEGER, `processed_at` INTEGER, `credit_consumed` VARCHAR(40) NOT NULL DEFAULT '0', `credit_pending` VARCHAR(40) NOT NULL DEFAULT '0', `metadata` JSON, `created_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `source_data` JSON);\n\nCREATE TABLE IF NOT EXISTS `meters` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `object` VARCHAR(32) NOT NULL DEFAULT 'meter', `name` VARCHAR(255) NOT NULL, `event_name` VARCHAR(128) NOT NULL UNIQUE, `aggregation_method` TEXT NOT NULL DEFAULT 'sum', `status` TEXT NOT NULL DEFAULT 'active', `unit` VARCHAR(32) NOT NULL, `description` TEXT, `component_did` VARCHAR(40), `currency_id` VARCHAR(40), `livemode` TINYINT(1) NOT NULL, `metadata` JSON, `created_by` VARCHAR(40), `updated_by` VARCHAR(40), `created_via` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `payment_currencies` (`id` VARCHAR(15) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `is_base_currency` TINYINT(1) DEFAULT 0, `payment_method_id` VARCHAR(30) NOT NULL, `name` VARCHAR(64) NOT NULL, `description` VARCHAR(512), `logo` VARCHAR(512) NOT NULL, `symbol` VARCHAR(16) NOT NULL, `decimal` NUMBER DEFAULT 2, `maximum_precision` NUMBER DEFAULT 6, `minimum_payment_amount` VARCHAR(32) DEFAULT '0', `maximum_payment_amount` VARCHAR(32) DEFAULT '0', `contract` VARCHAR(256), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `vault_config` JSON, `type` TEXT NOT NULL DEFAULT 'standard', `recharge_config` JSON, `token_config` JSON);\n\nCREATE TABLE IF NOT EXISTS `payment_intents` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `amount_received` VARCHAR(32), `amount_capturable` VARCHAR(32), `amount_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `description` VARCHAR(512), `last_payment_error` JSON, `last_charge` VARCHAR(30), `metadata` JSON, `invoice_id` VARCHAR(30), `payment_method_id` VARCHAR(30) NOT NULL, `receipt_email` VARCHAR(255), `statement_descriptor` VARCHAR(32), `statement_descriptor_suffix` VARCHAR(32), `status` TEXT NOT NULL, `canceled_at` DATETIME, `cancellation_reason` TEXT, `capture_method` TEXT NOT NULL, `confirmation_method` TEXT NOT NULL, `payment_method_types` JSON DEFAULT '[]', `review` VARCHAR(30), `payment_details` JSON, `setup_future_usage` TEXT, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `beneficiaries` JSON, `quote_locked_at` DATETIME);\n\nCREATE TABLE IF NOT EXISTS `payment_links` (`id` VARCHAR(40) NOT NULL UNIQUE PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `line_items` JSON DEFAULT '[]', `name` VARCHAR(255), `currency_id` VARCHAR(16), `after_completion` JSON DEFAULT '{\"type\":\"hosted_confirmation\"}', `allow_promotion_codes` TINYINT(1) DEFAULT 0, `consent_collection` JSON, `custom_fields` JSON DEFAULT '[]', `custom_text` JSON, `customer_creation` TEXT NOT NULL, `invoice_creation` JSON, `payment_method_types` JSON DEFAULT '[]', `phone_number_collection` JSON, `billing_address_collection` TEXT NOT NULL DEFAULT 'auto', `submit_type` TEXT NOT NULL, `subscription_data` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `nft_mint_settings` JSON, `cross_sell_behavior` TEXT DEFAULT 'auto', `donation_settings` JSON, `beneficiaries` JSON, `enable_subscription_grouping` TINYINT(1) DEFAULT 0, `lookup_key` VARCHAR(128));\n\nCREATE TABLE IF NOT EXISTS `payment_methods` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT, `name` VARCHAR(64), `description` VARCHAR(512), `logo` VARCHAR(512), `default_currency_id` VARCHAR(15), `confirmation` JSON NOT NULL, `settings` JSON NOT NULL, `features` JSON NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `payment_stats` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `timestamp` INTEGER DEFAULT 0, `currency_id` VARCHAR(16) NOT NULL, `amount_paid` VARCHAR(64) DEFAULT '0', `amount_payout` VARCHAR(64) DEFAULT '0', `amount_refund` VARCHAR(64) DEFAULT '0', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `payouts` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `automatic` TINYINT(1) NOT NULL, `description` VARCHAR(512), `amount` VARCHAR(32) NOT NULL, `destination` VARCHAR(512) NOT NULL, `payment_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `payment_intent_id` VARCHAR(16) NOT NULL, `payment_method_id` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `failure_message` VARCHAR(256), `failure_code` TEXT, `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_attempt` INTEGER, `last_attempt_error` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `vendor_info` JSON);\n\nCREATE TABLE IF NOT EXISTS `price_quotes` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `price_id` VARCHAR(32) NOT NULL, `session_id` VARCHAR(32), `invoice_id` VARCHAR(32), `idempotency_key` VARCHAR(128) NOT NULL UNIQUE, `base_currency` VARCHAR(8) NOT NULL DEFAULT 'USD', `base_amount` VARCHAR(32) NOT NULL, `target_currency_id` VARCHAR(16) NOT NULL, `rate_currency_symbol` VARCHAR(16) NOT NULL, `exchange_rate` VARCHAR(32) NOT NULL, `quoted_amount` VARCHAR(64) NOT NULL, `rate_provider_id` VARCHAR(32) NOT NULL, `rate_provider_name` VARCHAR(64) NOT NULL, `rate_timestamp_ms` BIGINT NOT NULL, `expires_at` INTEGER NOT NULL, `status` TEXT NOT NULL DEFAULT 'active', `metadata` JSON, `created_at` DATETIME NOT NULL, `slippage_percent` DECIMAL(5,2), `max_payable_token` VARCHAR(64), `min_acceptable_rate` VARCHAR(32), `slippage_derived_at_ms` BIGINT);\n\nCREATE TABLE IF NOT EXISTS `prices` (`id` VARCHAR(32) NOT NULL PRIMARY KEY, `product_id` VARCHAR(32) NOT NULL, `nickname` VARCHAR(512), `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT NOT NULL, `billing_scheme` TEXT NOT NULL, `unit_amount` VARCHAR(32) NOT NULL, `recurring` JSON, `tiers_mode` TEXT, `tiers` JSON, `custom_unit_amount` JSON, `lookup_key` VARCHAR(128), `metadata` JSON, `transform_quantity` JSON, `currency_id` VARCHAR(16), `currency_options` JSON DEFAULT '[]', `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `upsell` JSON, `quantity_available` INTEGER NOT NULL DEFAULT 0, `quantity_sold` INTEGER NOT NULL DEFAULT 0, `quantity_limit_per_checkout` INTEGER NOT NULL DEFAULT 0, `tax_behavior` TEXT NOT NULL DEFAULT 'inclusive', `pricing_type` TEXT NOT NULL DEFAULT 'fixed', `base_currency` VARCHAR(8), `base_amount` VARCHAR(32), `dynamic_pricing_config` JSON);\n\nCREATE TABLE IF NOT EXISTS `pricing_tables` (`id` VARCHAR(42) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) NOT NULL, `name` VARCHAR(255), `items` JSON DEFAULT '[]', `branding_settings` JSON NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `product_vendors` (`id` STRING NOT NULL UNIQUE PRIMARY KEY, `vendor_key` STRING NOT NULL, `name` STRING NOT NULL, `description` TEXT, `app_url` STRING NOT NULL, `app_pid` STRING NOT NULL, `app_logo` STRING, `status` STRING NOT NULL DEFAULT 'active', `metadata` JSON DEFAULT '{}', `created_by` STRING, `created_at` DATE NOT NULL DEFAULT 'CURRENT_TIMESTAMP', `updated_at` DATE NOT NULL DEFAULT 'CURRENT_TIMESTAMP', `vendor_type` STRING NOT NULL DEFAULT 'launcher', `vendor_did` STRING, `extends` JSON);\n\nCREATE TABLE IF NOT EXISTS `products` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `active` TINYINT(1) NOT NULL, `livemode` TINYINT(1) NOT NULL, `locked` TINYINT(1) DEFAULT 0, `type` TEXT, `name` VARCHAR(512), `description` VARCHAR(2048), `images` JSON DEFAULT '[]', `features` JSON DEFAULT '[]', `unit_label` VARCHAR(32), `default_price_id` VARCHAR(32), `metadata` JSON, `statement_descriptor` VARCHAR(32), `nft_factory` VARCHAR(40), `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL, `cross_sell` JSON, `vendor_config` JSON, `tax_code` VARCHAR(20));\n\nCREATE TABLE IF NOT EXISTS `promotion_codes` (`id` VARCHAR(30) NOT NULL UNIQUE PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) DEFAULT 1, `code` VARCHAR(16) NOT NULL, `coupon_id` VARCHAR(30), `max_redemptions` INTEGER, `restrictions` JSON DEFAULT '{}', `customer_id` VARCHAR(30), `times_redeemed` INTEGER DEFAULT '0', `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `verification_type` TEXT NOT NULL DEFAULT 'code', `nft_config` JSON, `vc_config` JSON, `customer_dids` JSON, `created_via` TEXT, `locked` TINYINT(1) NOT NULL DEFAULT 0, `expires_at` INTEGER, `expires_at_new` INTEGER, `description` TEXT);\n\nCREATE TABLE IF NOT EXISTS `refunds` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `description` VARCHAR(512), `livemode` TINYINT(1) NOT NULL, `amount` VARCHAR(32) NOT NULL, `payment_details` JSON, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `payment_intent_id` VARCHAR(16) NOT NULL, `invoice_id` VARCHAR(30), `subscription_id` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `reason` TEXT, `failure_reason` TEXT, `attempt_count` INTEGER DEFAULT 0, `attempted` TINYINT(1) DEFAULT 0, `next_attempt` INTEGER, `last_attempt_error` JSON, `starting_balance` VARCHAR(32) DEFAULT '0', `ending_balance` VARCHAR(32) DEFAULT '0', `starting_token_balance` JSON DEFAULT '{}', `ending_token_balance` JSON DEFAULT '{}', `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `payment_method_id` VARCHAR(30), `type` TEXT DEFAULT 'refund');\n\nCREATE TABLE IF NOT EXISTS `revenue_snapshots` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(16) NOT NULL, `timestamp` INTEGER NOT NULL, `period_type` TEXT NOT NULL DEFAULT 'monthly', `total_revenue` VARCHAR(64) DEFAULT '0', `refund_amount` VARCHAR(64) DEFAULT '0', `promotion_cost` VARCHAR(64) DEFAULT '0', `credit_grant_cost` VARCHAR(64) DEFAULT '0', `vendor_cost` VARCHAR(64) DEFAULT '0', `taxed_revenue` VARCHAR(64) DEFAULT '0', `net_revenue` VARCHAR(64) DEFAULT '0', `archive_metadata_id` VARCHAR(40), `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `settings` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) NOT NULL DEFAULT 1, `type` VARCHAR(64) NOT NULL, `mount_location` VARCHAR(255) NOT NULL, `component_did` VARCHAR(255), `description` VARCHAR(255) NOT NULL, `settings` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `setup_intents` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(16) NOT NULL, `customer_id` VARCHAR(30), `description` VARCHAR(512), `last_setup_error` JSON, `last_attempt` VARCHAR(30), `metadata` JSON, `status` TEXT NOT NULL, `usage` TEXT NOT NULL, `canceled_at` INTEGER, `cancellation_reason` TEXT, `flow_directions` JSON DEFAULT '[\"inbound\",\"outbound\"]', `payment_method_types` JSON DEFAULT '[]', `payment_method_options` JSON, `payment_method_id` VARCHAR(30) NOT NULL, `setup_details` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `subscription_items` (`id` VARCHAR(18) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `subscription_id` VARCHAR(30) NOT NULL, `price_id` VARCHAR(30) NOT NULL, `quantity` INTEGER, `metadata` JSON, `billing_threshold` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `subscription_schedules` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `current_phase` JSON NOT NULL, `customer_id` VARCHAR(30) NOT NULL, `subscription_id` VARCHAR(30) NOT NULL, `released_subscription_id` VARCHAR(30), `status` TEXT NOT NULL, `default_settings` JSON, `end_behavior` TEXT NOT NULL, `test_clock_id` VARCHAR(30), `metadata` JSON, `canceled_at` INTEGER, `completed_at` INTEGER, `released_at` INTEGER, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `subscriptions` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `currency_id` VARCHAR(15) NOT NULL, `customer_id` VARCHAR(18) NOT NULL, `cancel_at_period_end` TINYINT(1) NOT NULL, `current_period_end` INTEGER NOT NULL, `current_period_start` INTEGER NOT NULL, `default_payment_method_id` VARCHAR(30), `description` VARCHAR(512), `latest_invoice_id` VARCHAR(30), `pending_setup_intent` VARCHAR(30), `pending_update` JSON, `status` TEXT NOT NULL, `cancel_at` INTEGER, `canceled_at` INTEGER, `cancelation_details` JSON, `billing_cycle_anchor` INTEGER NOT NULL, `billing_thresholds` JSON, `collection_method` TEXT NOT NULL, `days_until_due` NUMBER, `discount_id` VARCHAR(30), `next_pending_invoice_item_invoice_id` VARCHAR(30), `pause_collection` JSON, `payment_settings` JSON, `pending_invoice_item_interval` JSON NOT NULL, `schedule_id` VARCHAR(30), `end_at` INTEGER, `start_date` INTEGER NOT NULL, `payment_details` JSON, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `proration_behavior` TEXT DEFAULT 'none', `payment_behavior` TEXT DEFAULT 'default_incomplete', `days_until_cancel` NUMBER, `service_actions` JSON DEFAULT '\"[]\"', `trial_start` INTEGER, `trial_end` INTEGER, `trial_settings` JSON, `recovered_from` VARCHAR(40), `overdraft_protection` JSON DEFAULT '\"{\\\"enabled\\\":false,\\\"payment_method_id\\\":null,\\\"payment_details\\\":null}\"', `credit_schedule_state` JSON DEFAULT NULL, `slippage_config` JSON);\n\nCREATE TABLE IF NOT EXISTS `tax_rates` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `active` TINYINT(1) DEFAULT 1, `country` VARCHAR(2) NOT NULL, `state` VARCHAR(50), `postal_code` VARCHAR(20), `tax_code` VARCHAR(20), `percentage` DECIMAL(5,4) NOT NULL, `display_name` VARCHAR(100) NOT NULL, `description` VARCHAR(500), `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `usage_records` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `timestamp` INTEGER NOT NULL, `quantity` BIGINT NOT NULL, `subscription_item_id` VARCHAR(30) NOT NULL, `metadata` JSON, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL, `billed` TINYINT(1) DEFAULT 0);\n\nCREATE TABLE IF NOT EXISTS `webhook_attempts` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `event_id` VARCHAR(30) NOT NULL, `webhook_endpoint_id` VARCHAR(30) NOT NULL, `status` TEXT NOT NULL, `response_status` INTEGER NOT NULL, `response_body` JSON NOT NULL, `retry_count` INTEGER DEFAULT 0, `created_at` DATETIME NOT NULL, `updated_at` DATETIME NOT NULL);\n\nCREATE TABLE IF NOT EXISTS `webhook_endpoints` (`id` VARCHAR(30) NOT NULL PRIMARY KEY, `livemode` TINYINT(1) NOT NULL, `api_version` VARCHAR(16) NOT NULL, `url` VARCHAR(512) NOT NULL, `description` VARCHAR(512), `enabled_events` JSON NOT NULL, `metadata` JSON, `status` TEXT NOT NULL, `created_at` DATETIME NOT NULL, `created_via` TEXT, `updated_at` DATETIME NOT NULL);\n" },
|
|
481
|
+
{ name: "0002_indexes.sql", sql: "-- Payment Kit: All indexes\n-- Matches the indexes from the original Sequelize migrations.\n\nCREATE INDEX IF NOT EXISTS `idx_auto_recharge_configs_currency_id` ON `auto_recharge_configs` (`currency_id`);\nCREATE INDEX IF NOT EXISTS `idx_auto_recharge_configs_customer_id` ON `auto_recharge_configs` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_fulfillment_status` ON `checkout_sessions` (`fulfillment_status`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_payment_intent` ON `checkout_sessions` (`payment_intent_id`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_payment_link_status_livemode` ON `checkout_sessions` (`payment_link_id`, `status`, `livemode`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_status` ON `checkout_sessions` (`status`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_subscription` ON `checkout_sessions` (`subscription_id`);\nCREATE INDEX IF NOT EXISTS idx_credit_grant_stats_by_grantor ON credit_grants(json_extract(metadata, '$.granted_by'), currency_id, created_at) WHERE json_extract(metadata, '$.granted_by') IS NOT NULL;\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_chain_status` ON `credit_grants` (`chain_status`);\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_currency` ON `credit_grants` (`currency_id`);\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_customer` ON `credit_grants` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_customer_currency_status` ON `credit_grants` (`customer_id`, `currency_id`, `status`);\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_status` ON `credit_grants` (`status`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_created` ON `credit_transactions` (`created_at`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_customer_created` ON `credit_transactions` (`customer_id`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_event_created` ON `credit_transactions` (`meter_event_name`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_meter_created` ON `credit_transactions` (`meter_id`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_subscription_created` ON `credit_transactions` (`subscription_id`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_transfer_status` ON `credit_transactions` (`transfer_status`);\nCREATE INDEX IF NOT EXISTS `idx_customers_did` ON `customers` (`did`);\nCREATE INDEX IF NOT EXISTS `idx_erp_enabled_priority` ON `exchange_rate_providers` (`enabled`, `priority`);\nCREATE UNIQUE INDEX IF NOT EXISTS `idx_erp_name` ON `exchange_rate_providers` (`name`);\nCREATE INDEX IF NOT EXISTS `idx_events_object_id_created` ON `events` (`object_id`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_events_object_type_id_created` ON `events` (`object_type`, `object_id`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_events_type_created` ON `events` (`type`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_currency_id` ON `invoices` (`currency_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_customer_id` ON `invoices` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_customer_total` ON `invoices` (`customer_id`, `total`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_items_invoice_id` ON `invoice_items` (`invoice_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_items_tax_rate_id_invoice_id` ON `invoice_items` (`tax_rate_id`, `invoice_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_status_collection` ON `invoices` (`status`, `collection_method`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_status_total` ON `invoices` (`status`, `total`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_subscription_id` ON `invoices` (`subscription_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_subtotal` ON `invoices` (`subtotal`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_total` ON `invoices` (`total`);\nCREATE INDEX IF NOT EXISTS `idx_invoices_created_at` ON `invoices` (`created_at`);\nCREATE INDEX IF NOT EXISTS `idx_invoices_status` ON `invoices` (`status`);\nCREATE INDEX IF NOT EXISTS `idx_jobs_cancelled_run_at` ON `jobs` (`cancelled`, `will_run_at`);\nCREATE INDEX IF NOT EXISTS `idx_jobs_queue_cancelled_run_at_delay` ON `jobs` (`queue`, `cancelled`, `will_run_at`, `delay`);\nCREATE INDEX IF NOT EXISTS `idx_jobs_queue_id` ON `jobs` (`queue`, `id`);\nCREATE INDEX IF NOT EXISTS `idx_jobs_queue_run_at` ON `jobs` (`queue`, `will_run_at`);\nCREATE INDEX IF NOT EXISTS idx_meter_events_customer_status ON meter_events(json_extract(payload, '$.customer_id'), status, livemode, created_at);\nCREATE INDEX IF NOT EXISTS `idx_meter_events_event_livemode_created` ON `meter_events` (`event_name`, `livemode`, `created_at`);\nCREATE INDEX IF NOT EXISTS `idx_meter_events_livemode_event_timestamp` ON `meter_events` (`livemode`, `event_name`, `timestamp`);\nCREATE INDEX IF NOT EXISTS `idx_meter_events_status_created` ON `meter_events` (`status`, `created_at`);\nCREATE INDEX IF NOT EXISTS idx_meter_events_subscription_status ON meter_events(json_extract(payload, '$.subscription_id'), status, livemode, created_at);\nCREATE INDEX IF NOT EXISTS `idx_meters_livemode_status` ON `meters` (`livemode`, `status`);\nCREATE INDEX IF NOT EXISTS `idx_payment_currencies_base_livemode` ON `payment_currencies` (`is_base_currency`, `livemode`);\nCREATE INDEX IF NOT EXISTS `idx_payment_intent_currency_id` ON `payment_intents` (`currency_id`);\nCREATE INDEX IF NOT EXISTS `idx_payment_intent_customer_id` ON `payment_intents` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_payment_intent_invoice_id` ON `payment_intents` (`invoice_id`);\nCREATE INDEX IF NOT EXISTS `idx_payment_intent_status_updated_at` ON `payment_intents` (`status`, `updated_at`);\nCREATE INDEX IF NOT EXISTS `idx_payment_stats_timestamp_currency_id` ON `payment_stats` (`timestamp`, `currency_id`);\nCREATE INDEX IF NOT EXISTS `idx_payouts_updated_at_status` ON `payouts` (`updated_at`, `status`);\nCREATE INDEX IF NOT EXISTS `idx_pq_created` ON `price_quotes` (`created_at`);\nCREATE INDEX IF NOT EXISTS `idx_pq_currency_created` ON `price_quotes` (`rate_currency_symbol`, `created_at`);\nCREATE UNIQUE INDEX IF NOT EXISTS `idx_pq_idempotency` ON `price_quotes` (`idempotency_key`);\nCREATE INDEX IF NOT EXISTS `idx_pq_invoice_status` ON `price_quotes` (`invoice_id`, `status`);\nCREATE INDEX IF NOT EXISTS `idx_pq_session_status_expires` ON `price_quotes` (`session_id`, `status`, `expires_at`);\nCREATE INDEX IF NOT EXISTS `idx_refunds_payment_intent_id_type` ON `refunds` (`payment_intent_id`, `type`);\nCREATE INDEX IF NOT EXISTS `idx_refunds_status_type_updated_at` ON `refunds` (`status`, `type`, `updated_at`);\nCREATE INDEX IF NOT EXISTS `idx_refunds_subscription_id_type` ON `refunds` (`subscription_id`, `type`);\nCREATE UNIQUE INDEX IF NOT EXISTS `idx_revenue_snapshots_unique` ON `revenue_snapshots` (`timestamp`, `currency_id`, `livemode`, `period_type`);\nCREATE INDEX IF NOT EXISTS `idx_subscription_item_subscription_id_price_id` ON `subscription_items` (`subscription_id`, `price_id`);\nCREATE INDEX IF NOT EXISTS `idx_subscription_period` ON `subscriptions` (`current_period_start`, `current_period_end`);\nCREATE INDEX IF NOT EXISTS `idx_subscription_status` ON `subscriptions` (`status`);\nCREATE INDEX IF NOT EXISTS `idx_subscriptions_customer_id` ON `subscriptions` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_usage_records_subscription_item_id_timestamp` ON `usage_records` (`subscription_item_id`, `timestamp`);\nCREATE INDEX IF NOT EXISTS `idx_webhook_attempts_event_id` ON `webhook_attempts` (`event_id`);\nCREATE INDEX IF NOT EXISTS `idx_webhook_attempts_webhook_endpoint_id` ON `webhook_attempts` (`webhook_endpoint_id`);\nCREATE INDEX IF NOT EXISTS `idx_webhook_endpoint_status_livemode` ON `webhook_endpoints` (`status`, `livemode`);\nCREATE INDEX IF NOT EXISTS `tax_rates_query_index` ON `tax_rates` (`country`, `state`, `postal_code`, `tax_code`);\n" },
|
|
482
|
+
{ name: "0003_locks_and_constraints.sql", sql: "-- Distributed locks table for D1-based locking across CF Worker isolates\nCREATE TABLE IF NOT EXISTS _locks (\n name TEXT PRIMARY KEY,\n owner TEXT NOT NULL,\n expires_at INTEGER NOT NULL\n);\n\n-- Unique index on Stripe invoice ID to prevent duplicate mirroring\nCREATE UNIQUE INDEX IF NOT EXISTS idx_invoices_stripe_id\n ON invoices(json_extract(metadata, '$.stripe_id'))\n WHERE json_extract(metadata, '$.stripe_id') IS NOT NULL;\n\n-- DID Connect token storage (D1 for strong consistency instead of KV)\nCREATE TABLE IF NOT EXISTS _did_connect_tokens (\n token TEXT PRIMARY KEY,\n data TEXT NOT NULL,\n expires_at INTEGER NOT NULL\n);\n" },
|
|
483
|
+
{ name: "0004_iap_foundation.sql", sql: "-- Payment Kit: IAP foundation\n-- Adds schema needed for App Store + Google Play subscription channels.\n-- Mirrors blocklets/core/api/src/store/migrations/20260526-iap-foundation.ts.\n--\n-- NOTE: SQLite does not support `ALTER TABLE ADD COLUMN IF NOT EXISTS`.\n-- Wrangler tracks applied migrations in the `d1_migrations` table and skips\n-- re-application by filename, so re-running this file via `wrangler d1\n-- migrations apply` is safe. Do not invoke via `wrangler d1 execute` more\n-- than once on the same database.\n\n-- 1. Customer: per-channel UUID for IAP appAccountToken / obfuscatedAccountId mapping (D-004)\nALTER TABLE customers ADD COLUMN app_store_uuid VARCHAR(36);\nALTER TABLE customers ADD COLUMN google_play_uuid VARCHAR(36);\nCREATE UNIQUE INDEX IF NOT EXISTS idx_customers_app_store_uuid\n ON customers(app_store_uuid)\n WHERE app_store_uuid IS NOT NULL;\nCREATE UNIQUE INDEX IF NOT EXISTS idx_customers_google_play_uuid\n ON customers(google_play_uuid)\n WHERE google_play_uuid IS NOT NULL;\n\n-- 2. Subscription: channel + environment (D-005)\nALTER TABLE subscriptions ADD COLUMN channel VARCHAR(20);\nALTER TABLE subscriptions ADD COLUMN environment VARCHAR(20) DEFAULT 'production';\n\n-- 3. Invoice: three-segment amounts (D-001 A)\nALTER TABLE invoices ADD COLUMN gross_amount VARCHAR(32);\nALTER TABLE invoices ADD COLUMN platform_fee VARCHAR(32) DEFAULT '0';\nALTER TABLE invoices ADD COLUMN net_amount VARCHAR(32);\nUPDATE invoices SET gross_amount = total, net_amount = total WHERE gross_amount IS NULL;\n\n-- 4. Refund: origin source (merchant_initiated | platform_initiated)\nALTER TABLE refunds ADD COLUMN source VARCHAR(30) DEFAULT 'merchant_initiated';\n\n-- 5. Entitlement tables (D-003 B)\nCREATE TABLE IF NOT EXISTS `entitlements` (\n `id` VARCHAR(30) NOT NULL PRIMARY KEY,\n `livemode` TINYINT(1) NOT NULL,\n `key` VARCHAR(64) NOT NULL UNIQUE,\n `name` VARCHAR(255),\n `description` TEXT,\n `metadata` JSON,\n `created_at` DATETIME NOT NULL,\n `updated_at` DATETIME NOT NULL\n);\nCREATE UNIQUE INDEX IF NOT EXISTS `idx_entitlements_key` ON `entitlements` (`key`);\n\nCREATE TABLE IF NOT EXISTS `entitlement_products` (\n `entitlement_id` VARCHAR(30) NOT NULL,\n `product_id` VARCHAR(30) NOT NULL,\n `created_at` DATETIME NOT NULL,\n `updated_at` DATETIME NOT NULL,\n PRIMARY KEY (`entitlement_id`, `product_id`)\n);\n\nCREATE TABLE IF NOT EXISTS `entitlement_grants` (\n `id` VARCHAR(30) NOT NULL PRIMARY KEY,\n `livemode` TINYINT(1) NOT NULL,\n `entitlement_id` VARCHAR(30) NOT NULL,\n `customer_id` VARCHAR(18) NOT NULL,\n `source_subscription_id` VARCHAR(30),\n `source_channel` VARCHAR(20) NOT NULL,\n `active_from` INTEGER NOT NULL,\n `active_until` INTEGER NOT NULL,\n `status` VARCHAR(20) NOT NULL DEFAULT 'active',\n `metadata` JSON,\n `created_at` DATETIME NOT NULL,\n `updated_at` DATETIME NOT NULL\n);\nCREATE INDEX IF NOT EXISTS `idx_entitlement_grants_lookup`\n ON `entitlement_grants` (`customer_id`, `entitlement_id`, `status`);\nCREATE INDEX IF NOT EXISTS `idx_entitlement_grants_source_sub`\n ON `entitlement_grants` (`source_subscription_id`);\n" },
|
|
484
|
+
{ name: "0005_iap_tenant_backfill.sql", sql: "-- Payment Kit: IAP multi-tenant backfill\n-- Backfills metadata.bundle_id / metadata.package_name on existing Prices and\n-- payment_details.app_store.bundle_id / payment_details.google_play.package_name\n-- on existing Subscriptions, so Payment Kit can be wired into multiple iOS /\n-- Android apps without same-SKU collisions across App Store / Play Console\n-- namespaces (each store's SKU space is per-app, not global).\n--\n-- Backend code already filters Price.findOne by (sku, bundle_id) / (sku,\n-- package_name); without this backfill, every pre-existing Price would stop\n-- resolving the moment the new lookup ships.\n--\n-- Safety: tenant value is DERIVED from the configured PaymentMethods (which\n-- store bundle_id / package_name as plain text under settings JSON \u2014 only\n-- private keys are encrypted). The migration deliberately refuses to guess in\n-- ambiguous setups:\n--\n-- * For Subscriptions we always use the sub's own\n-- `default_payment_method_id` to resolve the tenant, which is a 1:1 map \u2014\n-- never ambiguous as long as the row points at a real PaymentMethod.\n-- * For Prices we update only when EXACTLY ONE active PaymentMethod of the\n-- matching type + livemode exists with a non-null tenant. Multi-tenant\n-- installations (two iOS apps sharing one Payment Kit, etc.) skip the\n-- Price backfill \u2014 admin must set bundle_id / package_name explicitly\n-- because the migration can't safely guess which app a Price belongs to.\n--\n-- Idempotent. The IS NULL guards make re-runs a no-op for already-backfilled\n-- rows, and the subquery filters skip rows that can't be resolved safely.\n\n-- 1. Prices with App Store SKU \u2192 set bundle_id (only when one active\n-- app_store PaymentMethod for the same livemode unambiguously identifies\n-- the tenant).\nUPDATE prices\nSET metadata = json_set(\n metadata,\n '$.bundle_id',\n (SELECT json_extract(pm.settings, '$.app_store.bundle_id')\n FROM payment_methods pm\n WHERE pm.type = 'app_store'\n AND pm.livemode = prices.livemode\n AND pm.active = 1\n AND json_extract(pm.settings, '$.app_store.bundle_id') IS NOT NULL\n LIMIT 1)\n)\nWHERE json_extract(metadata, '$.app_store_product_id') IS NOT NULL\n AND json_extract(metadata, '$.bundle_id') IS NULL\n AND (\n SELECT COUNT(*) FROM payment_methods pm\n WHERE pm.type = 'app_store'\n AND pm.livemode = prices.livemode\n AND pm.active = 1\n AND json_extract(pm.settings, '$.app_store.bundle_id') IS NOT NULL\n ) = 1;\n\n-- 2. Prices with Google Play SKU \u2192 set package_name (same single-tenant guard).\nUPDATE prices\nSET metadata = json_set(\n metadata,\n '$.package_name',\n (SELECT json_extract(pm.settings, '$.google_play.package_name')\n FROM payment_methods pm\n WHERE pm.type = 'google_play'\n AND pm.livemode = prices.livemode\n AND pm.active = 1\n AND json_extract(pm.settings, '$.google_play.package_name') IS NOT NULL\n LIMIT 1)\n)\nWHERE json_extract(metadata, '$.google_play_product_id') IS NOT NULL\n AND json_extract(metadata, '$.package_name') IS NULL\n AND (\n SELECT COUNT(*) FROM payment_methods pm\n WHERE pm.type = 'google_play'\n AND pm.livemode = prices.livemode\n AND pm.active = 1\n AND json_extract(pm.settings, '$.google_play.package_name') IS NOT NULL\n ) = 1;\n\n-- 3. App Store Subscriptions \u2192 set payment_details.app_store.bundle_id from\n-- the sub's own default_payment_method (1:1 \u2014 always safe).\nUPDATE subscriptions\nSET payment_details = json_set(\n payment_details,\n '$.app_store.bundle_id',\n (SELECT json_extract(pm.settings, '$.app_store.bundle_id')\n FROM payment_methods pm\n WHERE pm.id = subscriptions.default_payment_method_id)\n)\nWHERE channel = 'app_store'\n AND json_extract(payment_details, '$.app_store.bundle_id') IS NULL\n AND default_payment_method_id IS NOT NULL\n AND (\n SELECT json_extract(pm.settings, '$.app_store.bundle_id')\n FROM payment_methods pm\n WHERE pm.id = subscriptions.default_payment_method_id\n ) IS NOT NULL;\n\n-- 4. Google Play Subscriptions \u2192 set payment_details.google_play.package_name.\nUPDATE subscriptions\nSET payment_details = json_set(\n payment_details,\n '$.google_play.package_name',\n (SELECT json_extract(pm.settings, '$.google_play.package_name')\n FROM payment_methods pm\n WHERE pm.id = subscriptions.default_payment_method_id)\n)\nWHERE channel = 'google_play'\n AND json_extract(payment_details, '$.google_play.package_name') IS NULL\n AND default_payment_method_id IS NOT NULL\n AND (\n SELECT json_extract(pm.settings, '$.google_play.package_name')\n FROM payment_methods pm\n WHERE pm.id = subscriptions.default_payment_method_id\n ) IS NOT NULL;\n" },
|
|
485
|
+
{ name: "0006_tenant_columns.sql", sql: "-- Payment Kit: tenant columns (Phase 1, W1-1a)\n-- Adds a nullable instance_did column to all 38 tenant tables.\n-- Mirrors blocklets/core/api/src/store/migrations/20260610-tenant-columns.ts.\n-- No constraints / indexes / backfill here \u2014 those land in 0007 (Phase 2).\n--\n-- NOTE: wrangler tracks applied migrations in `d1_migrations` by filename,\n-- so this file is applied exactly once via `wrangler d1 migrations apply`.\n\nALTER TABLE customers ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE products ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE prices ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE pricing_tables ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payment_methods ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE checkout_sessions ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payment_intents ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payment_links ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE setup_intents ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE price_quotes ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE subscriptions ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE subscription_items ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE subscription_schedules ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE invoices ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE invoice_items ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE refunds ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE credit_grants ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE credit_transactions ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE meters ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE meter_events ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE usage_records ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE coupons ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE promotion_codes ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE discounts ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE entitlements ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE entitlement_grants ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE entitlement_products ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE events ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE webhook_endpoints ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE webhook_attempts ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payouts ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payment_stats ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE revenue_snapshots ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE auto_recharge_configs ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE tax_rates ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE settings ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE payment_currencies ADD COLUMN instance_did VARCHAR(64);\nALTER TABLE product_vendors ADD COLUMN instance_did VARCHAR(64);\n" },
|
|
486
|
+
{ name: "0007_tenant_backfill_indexes.sql", sql: "-- Payment Kit: tenant unique keys + indexes (Phase 2, W1-1b)\n-- Mirrors the index/unique-key part of api/src/store/migrations/20260611-tenant-backfill.ts.\n--\n-- IMPORTANT: the instance_did BACKFILL is NOT here. Static migration SQL\n-- cannot know the deployment app DID, so the backfill (and the table rebuilds\n-- that drop old inline single-column UNIQUE constraints) runs through the\n-- shared runtime routine `runTenantBackfill()` (api/src/store/tenant-backfill.ts),\n-- invoked idempotently from the worker's scheduled() handler.\n--\n-- Everything below is NULL-safe before that backfill runs: SQLite treats each\n-- NULL as distinct in unique indexes, and existing single-column uniqueness\n-- (identifier / did / key / idempotency_key) guarantees no composite dupes.\n\n-- composite tenant unique keys (W1 \xA72.1, decisions D1/D3)\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_customers_tenant_did` ON `customers` (`instance_did`, `did`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_meter_events_tenant_identifier` ON `meter_events` (`instance_did`, `identifier`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_meters_tenant_event_name` ON `meters` (`instance_did`, `event_name`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_entitlements_tenant_key` ON `entitlements` (`instance_did`, `key`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_price_quotes_tenant_idem` ON `price_quotes` (`instance_did`, `idempotency_key`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_promotion_codes_tenant_code` ON `promotion_codes` (`instance_did`, `livemode`, `code`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_product_vendors_tenant_key` ON `product_vendors` (`instance_did`, `vendor_key`);\nCREATE UNIQUE INDEX IF NOT EXISTS `uq_revenue_snapshots_tenant` ON `revenue_snapshots` (`instance_did`, `timestamp`, `currency_id`, `livemode`, `period_type`);\nDROP INDEX IF EXISTS `idx_revenue_snapshots_unique`;\nDROP INDEX IF EXISTS `idx_entitlements_key`;\nDROP INDEX IF EXISTS `idx_pq_idempotency`;\n\n-- plain tenant indexes for scoped queries (Phase 3+); meter_events is served\n-- by its composite unique above (high-write table, avoid a second index)\nCREATE INDEX IF NOT EXISTS `idx_customers_instance_did` ON `customers` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_products_instance_did` ON `products` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_prices_instance_did` ON `prices` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_pricing_tables_instance_did` ON `pricing_tables` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payment_methods_instance_did` ON `payment_methods` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_checkout_sessions_instance_did` ON `checkout_sessions` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payment_intents_instance_did` ON `payment_intents` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payment_links_instance_did` ON `payment_links` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_setup_intents_instance_did` ON `setup_intents` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_price_quotes_instance_did` ON `price_quotes` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_subscriptions_instance_did` ON `subscriptions` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_subscription_items_instance_did` ON `subscription_items` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_subscription_schedules_instance_did` ON `subscription_schedules` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_invoices_instance_did` ON `invoices` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_items_instance_did` ON `invoice_items` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_refunds_instance_did` ON `refunds` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_credit_grants_instance_did` ON `credit_grants` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_credit_transactions_instance_did` ON `credit_transactions` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_meters_instance_did` ON `meters` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_usage_records_instance_did` ON `usage_records` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_coupons_instance_did` ON `coupons` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_promotion_codes_instance_did` ON `promotion_codes` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_discounts_instance_did` ON `discounts` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_entitlements_instance_did` ON `entitlements` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_entitlement_grants_instance_did` ON `entitlement_grants` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_entitlement_products_instance_did` ON `entitlement_products` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_events_instance_did` ON `events` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_webhook_endpoints_instance_did` ON `webhook_endpoints` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_webhook_attempts_instance_did` ON `webhook_attempts` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payouts_instance_did` ON `payouts` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payment_stats_instance_did` ON `payment_stats` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_revenue_snapshots_instance_did` ON `revenue_snapshots` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_auto_recharge_configs_instance_did` ON `auto_recharge_configs` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_tax_rates_instance_did` ON `tax_rates` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_settings_instance_did` ON `settings` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_payment_currencies_instance_did` ON `payment_currencies` (`instance_did`);\nCREATE INDEX IF NOT EXISTS `idx_product_vendors_instance_did` ON `product_vendors` (`instance_did`);\n" },
|
|
487
|
+
{ name: "0008_schema_parity.sql", sql: "-- Phase 11 (W2\u2032) schema parity: close the D1-lineage gaps the schema-drift guard\n-- (scripts/schema-drift-guard.ts) found versus the Umzug canonical schema.\n-- Additive only \u2014 safe to apply on a deployed D1 (no drops, no rewrites).\n\n-- events: the Umzug genesis creates `events` with api_version (NOT NULL) and\n-- metadata (JSON); the D1 0001 events table predates both, so the worker could\n-- not write them. Backfill api_version with the app constant\n-- (api/src/libs/audit.ts API_VERSION = '2023-09-05'); new rows carry the same.\nALTER TABLE `events` ADD COLUMN `api_version` VARCHAR(16) NOT NULL DEFAULT '2023-09-05';\nALTER TABLE `events` ADD COLUMN `metadata` JSON;\n\n-- Indexes present in the canonical but missing in the D1 lineage (perf parity;\n-- names match the Umzug migrations 20250904-discount / 20251007-relate-tax-rate).\nCREATE INDEX IF NOT EXISTS `idx_discounts_customer_id` ON `discounts` (`customer_id`);\nCREATE INDEX IF NOT EXISTS `idx_invoice_items_tax_rate_id` ON `invoice_items` (`tax_rate_id`);\nCREATE INDEX IF NOT EXISTS `idx_promotion_codes_verification_type_coupon_id` ON `promotion_codes` (`verification_type`, `coupon_id`);\n" },
|
|
488
|
+
{ name: "0009_remove_did_space_jobs.sql", sql: "-- The DID Space billing-mirror integration was removed (libs/did-space.ts,\n-- queues/space.ts). Rows in `jobs` with queue='did-space' can never be picked\n-- up again (the scheduled scan only matches registered queue names), so they\n-- would sit in the table forever. Delete them. Idempotent.\nDELETE FROM jobs WHERE queue = 'did-space';\n" }
|
|
489
|
+
];
|
|
490
|
+
}
|
|
491
|
+
});
|
|
492
|
+
|
|
493
|
+
// ../../blocklets/core/api/src/libs/env.ts
|
|
494
|
+
function readConfig(key) {
|
|
495
|
+
const injected = activeConfig?.[key];
|
|
496
|
+
if (injected !== void 0 && injected !== null) return String(injected);
|
|
497
|
+
const fromEnv = process.env[key];
|
|
498
|
+
return fromEnv === void 0 ? void 0 : fromEnv;
|
|
499
|
+
}
|
|
500
|
+
var import_env, activeConfig, blockletAppPid, env_default;
|
|
501
|
+
var init_env = __esm({
|
|
502
|
+
"../../blocklets/core/api/src/libs/env.ts"() {
|
|
503
|
+
"use strict";
|
|
504
|
+
import_env = require("@blocklet/sdk/lib/env");
|
|
505
|
+
blockletAppPid = () => readConfig("BLOCKLET_APP_PID");
|
|
506
|
+
env_default = {
|
|
507
|
+
...import_env.env
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
});
|
|
511
|
+
|
|
512
|
+
// ../../blocklets/core/api/src/libs/tenant.ts
|
|
513
|
+
function getDefaultInstanceDid() {
|
|
514
|
+
const did = overrideDefaultInstanceDid || blockletAppPid() || "";
|
|
515
|
+
if (!did) {
|
|
516
|
+
throw new TenantError(TENANT_CONTEXT_MISSING, "app DID is not configured for this deployment");
|
|
517
|
+
}
|
|
518
|
+
return did;
|
|
519
|
+
}
|
|
520
|
+
var TENANT_CONTEXT_MISSING, TenantError, overrideDefaultInstanceDid;
|
|
521
|
+
var init_tenant = __esm({
|
|
522
|
+
"../../blocklets/core/api/src/libs/tenant.ts"() {
|
|
523
|
+
"use strict";
|
|
524
|
+
init_env();
|
|
525
|
+
TENANT_CONTEXT_MISSING = "TENANT_CONTEXT_MISSING";
|
|
526
|
+
TenantError = class extends Error {
|
|
527
|
+
constructor(code, message) {
|
|
528
|
+
super(message);
|
|
529
|
+
this.name = "TenantError";
|
|
530
|
+
this.code = code;
|
|
531
|
+
}
|
|
532
|
+
};
|
|
533
|
+
}
|
|
534
|
+
});
|
|
535
|
+
|
|
536
|
+
// ../../blocklets/core/api/src/libs/drivers/identity.ts
|
|
537
|
+
function createDefaultIdentityDriver() {
|
|
538
|
+
return {
|
|
539
|
+
resolveInstanceDidForHost() {
|
|
540
|
+
return getDefaultInstanceDid();
|
|
541
|
+
}
|
|
542
|
+
};
|
|
543
|
+
}
|
|
544
|
+
function setIdentityDriver(driver) {
|
|
545
|
+
activeIdentityDriver = driver;
|
|
546
|
+
}
|
|
547
|
+
function getIdentityDriver() {
|
|
548
|
+
return activeIdentityDriver;
|
|
549
|
+
}
|
|
550
|
+
var activeIdentityDriver;
|
|
551
|
+
var init_identity = __esm({
|
|
552
|
+
"../../blocklets/core/api/src/libs/drivers/identity.ts"() {
|
|
553
|
+
"use strict";
|
|
554
|
+
init_tenant();
|
|
555
|
+
activeIdentityDriver = createDefaultIdentityDriver();
|
|
556
|
+
}
|
|
557
|
+
});
|
|
558
|
+
|
|
559
|
+
// ../../blocklets/core/api/src/libs/drivers/secrets.ts
|
|
560
|
+
function createDefaultSecretsDriver() {
|
|
561
|
+
return new DefaultSecretsDriver();
|
|
562
|
+
}
|
|
563
|
+
function safeUtf8(decrypted) {
|
|
564
|
+
try {
|
|
565
|
+
return decrypted.toString(CryptoJS.enc.Utf8);
|
|
566
|
+
} catch {
|
|
567
|
+
return "";
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
function derivePassword(appEk, instanceDid) {
|
|
571
|
+
return import_crypto.default.pbkdf2Sync(appEk, instanceDid, 256, 32, "sha512").toString("hex");
|
|
572
|
+
}
|
|
573
|
+
function createKeyringSecretsDriver(identity, opts) {
|
|
574
|
+
return new KeyringSecretsDriver(identity, opts);
|
|
575
|
+
}
|
|
576
|
+
function setSecretsDriver(driver) {
|
|
577
|
+
activeSecretsDriver = driver;
|
|
578
|
+
}
|
|
579
|
+
function getSecretsDriver() {
|
|
580
|
+
return activeSecretsDriver;
|
|
581
|
+
}
|
|
582
|
+
var import_crypto, CryptoJS, DefaultSecretsDriver, DEFAULT_TTL_MS, KeyringSecretsDriver, activeSecretsDriver;
|
|
583
|
+
var init_secrets = __esm({
|
|
584
|
+
"../../blocklets/core/api/src/libs/drivers/secrets.ts"() {
|
|
585
|
+
"use strict";
|
|
586
|
+
import_crypto = __toESM(require("crypto"));
|
|
587
|
+
CryptoJS = require("crypto-js");
|
|
588
|
+
DefaultSecretsDriver = class {
|
|
589
|
+
// lazily required so importing this module stays side-effect-free
|
|
590
|
+
security() {
|
|
591
|
+
return require("@blocklet/sdk/lib/security").default ?? require("@blocklet/sdk/lib/security");
|
|
592
|
+
}
|
|
593
|
+
encryptSync(_instanceDid, value) {
|
|
594
|
+
return this.security().encrypt(value);
|
|
595
|
+
}
|
|
596
|
+
decryptSync(_instanceDid, value) {
|
|
597
|
+
return this.security().decrypt(value);
|
|
598
|
+
}
|
|
599
|
+
// eslint-disable-next-line require-await -- async contract; the single key is sync
|
|
600
|
+
async encrypt(instanceDid, value) {
|
|
601
|
+
return this.encryptSync(instanceDid, value);
|
|
602
|
+
}
|
|
603
|
+
// eslint-disable-next-line require-await -- async contract; the single key is sync
|
|
604
|
+
async decrypt(instanceDid, value) {
|
|
605
|
+
return this.decryptSync(instanceDid, value);
|
|
606
|
+
}
|
|
607
|
+
async warmup() {
|
|
608
|
+
}
|
|
609
|
+
};
|
|
610
|
+
DEFAULT_TTL_MS = 10 * 60 * 1e3;
|
|
611
|
+
KeyringSecretsDriver = class {
|
|
612
|
+
constructor(identity, opts) {
|
|
613
|
+
this.cache = /* @__PURE__ */ new Map();
|
|
614
|
+
if (typeof identity.getAppEk !== "function") {
|
|
615
|
+
throw new Error("createKeyringSecretsDriver: identity driver must provide getAppEk(instanceDid)");
|
|
616
|
+
}
|
|
617
|
+
this.identity = identity;
|
|
618
|
+
this.ttlMs = opts?.ttlMs ?? DEFAULT_TTL_MS;
|
|
619
|
+
}
|
|
620
|
+
fresh(instanceDid) {
|
|
621
|
+
const entry = this.cache.get(instanceDid);
|
|
622
|
+
if (entry && entry.expiresAt > Date.now()) return entry.password;
|
|
623
|
+
return null;
|
|
624
|
+
}
|
|
625
|
+
async resolvePassword(instanceDid, force = false) {
|
|
626
|
+
if (!force) {
|
|
627
|
+
const cached = this.fresh(instanceDid);
|
|
628
|
+
if (cached) return cached;
|
|
629
|
+
}
|
|
630
|
+
const appEk = await this.identity.getAppEk(instanceDid);
|
|
631
|
+
if (!appEk) {
|
|
632
|
+
throw new Error(`secrets: no EK for tenant ${instanceDid}`);
|
|
633
|
+
}
|
|
634
|
+
const password = derivePassword(appEk, instanceDid);
|
|
635
|
+
this.cache.set(instanceDid, { password, expiresAt: Date.now() + this.ttlMs });
|
|
636
|
+
return password;
|
|
637
|
+
}
|
|
638
|
+
async warmup(instanceDid) {
|
|
639
|
+
await this.resolvePassword(instanceDid);
|
|
640
|
+
}
|
|
641
|
+
encryptSync(instanceDid, value) {
|
|
642
|
+
const password = this.fresh(instanceDid);
|
|
643
|
+
if (!password) throw new Error(`secrets: key for tenant ${instanceDid} is not warmed (call warmup first)`);
|
|
644
|
+
return CryptoJS.AES.encrypt(value, password).toString();
|
|
645
|
+
}
|
|
646
|
+
decryptSync(instanceDid, value) {
|
|
647
|
+
const password = this.fresh(instanceDid);
|
|
648
|
+
if (!password) throw new Error(`secrets: key for tenant ${instanceDid} is not warmed (call warmup first)`);
|
|
649
|
+
return safeUtf8(CryptoJS.AES.decrypt(value, password));
|
|
650
|
+
}
|
|
651
|
+
async encrypt(instanceDid, value) {
|
|
652
|
+
const password = await this.resolvePassword(instanceDid);
|
|
653
|
+
return CryptoJS.AES.encrypt(value, password).toString();
|
|
654
|
+
}
|
|
655
|
+
async decrypt(instanceDid, value) {
|
|
656
|
+
let password = await this.resolvePassword(instanceDid);
|
|
657
|
+
let plain = safeUtf8(CryptoJS.AES.decrypt(value, password));
|
|
658
|
+
if (!plain) {
|
|
659
|
+
password = await this.resolvePassword(instanceDid, true);
|
|
660
|
+
plain = safeUtf8(CryptoJS.AES.decrypt(value, password));
|
|
661
|
+
}
|
|
662
|
+
return plain;
|
|
663
|
+
}
|
|
664
|
+
};
|
|
665
|
+
activeSecretsDriver = createDefaultSecretsDriver();
|
|
666
|
+
}
|
|
667
|
+
});
|
|
668
|
+
|
|
669
|
+
// ../../blocklets/core/api/src/libs/drivers/index.ts
|
|
670
|
+
var drivers_exports = {};
|
|
671
|
+
__export(drivers_exports, {
|
|
672
|
+
DbAuthStorage: () => DbAuthStorage,
|
|
673
|
+
MemoryLock: () => MemoryLock,
|
|
674
|
+
applyPaymentCoreMigrations: () => applyPaymentCoreMigrations,
|
|
675
|
+
applySqlMigrations: () => applySqlMigrations,
|
|
676
|
+
createAuthStorage: () => createAuthStorage,
|
|
677
|
+
createCronRegistry: () => createCronRegistry,
|
|
678
|
+
createD1DbDriver: () => createD1DbDriver,
|
|
679
|
+
createD1LocksDriver: () => createD1LocksDriver,
|
|
680
|
+
createDefaultIdentityDriver: () => createDefaultIdentityDriver,
|
|
681
|
+
createDefaultSecretsDriver: () => createDefaultSecretsDriver,
|
|
682
|
+
createKeyringSecretsDriver: () => createKeyringSecretsDriver,
|
|
683
|
+
createMemoryLocksDriver: () => createMemoryLocksDriver,
|
|
684
|
+
createNodeDbDriver: () => createNodeDbDriver,
|
|
685
|
+
getCronDriver: () => getCronDriver,
|
|
686
|
+
getIdentityDriver: () => getIdentityDriver,
|
|
687
|
+
getQueueHostHooks: () => getQueueHostHooks,
|
|
688
|
+
getSecretsDriver: () => getSecretsDriver,
|
|
689
|
+
matchesCron: () => matchesCron,
|
|
690
|
+
nodeQueueHostHooks: () => nodeQueueHostHooks,
|
|
691
|
+
paymentCoreSqlMigrations: () => paymentCoreSqlMigrations,
|
|
692
|
+
scopedLockName: () => scopedLockName,
|
|
693
|
+
setCronDriver: () => setCronDriver,
|
|
694
|
+
setIdentityDriver: () => setIdentityDriver,
|
|
695
|
+
setQueueHostHooks: () => setQueueHostHooks,
|
|
696
|
+
setSecretsDriver: () => setSecretsDriver,
|
|
697
|
+
shouldRunInWindow: () => shouldRunInWindow,
|
|
698
|
+
splitStatements: () => splitStatements
|
|
699
|
+
});
|
|
700
|
+
function applyPaymentCoreMigrations(driver) {
|
|
701
|
+
return applySqlMigrations(driver, paymentCoreSqlMigrations);
|
|
702
|
+
}
|
|
703
|
+
var init_drivers = __esm({
|
|
704
|
+
"../../blocklets/core/api/src/libs/drivers/index.ts"() {
|
|
705
|
+
"use strict";
|
|
706
|
+
init_db();
|
|
707
|
+
init_locks();
|
|
708
|
+
init_auth_storage();
|
|
709
|
+
init_queue();
|
|
710
|
+
init_cron();
|
|
711
|
+
init_migrate_runner();
|
|
712
|
+
init_migrate_runner();
|
|
713
|
+
init_sql_migrations();
|
|
714
|
+
init_identity();
|
|
715
|
+
init_secrets();
|
|
716
|
+
}
|
|
717
|
+
});
|
|
718
|
+
|
|
719
|
+
// src/drivers.ts
|
|
720
|
+
var drivers_exports2 = {};
|
|
721
|
+
__export(drivers_exports2, {
|
|
722
|
+
applyPaymentCoreMigrations: () => applyPaymentCoreMigrations2,
|
|
723
|
+
applySqlMigrations: () => applySqlMigrations2,
|
|
724
|
+
createAuthStorage: () => createAuthStorage2,
|
|
725
|
+
createCronRegistry: () => createCronRegistry2,
|
|
726
|
+
createD1DbDriver: () => createD1DbDriver2,
|
|
727
|
+
createD1LocksDriver: () => createD1LocksDriver2,
|
|
728
|
+
createDefaultIdentityDriver: () => createDefaultIdentityDriver2,
|
|
729
|
+
createDefaultSecretsDriver: () => createDefaultSecretsDriver2,
|
|
730
|
+
createKeyringSecretsDriver: () => createKeyringSecretsDriver2,
|
|
731
|
+
createMemoryLocksDriver: () => createMemoryLocksDriver2,
|
|
732
|
+
createNodeDbDriver: () => createNodeDbDriver2,
|
|
733
|
+
getCronDriver: () => getCronDriver2,
|
|
734
|
+
getIdentityDriver: () => getIdentityDriver2,
|
|
735
|
+
getPaymentCoreSqlMigrations: () => getPaymentCoreSqlMigrations,
|
|
736
|
+
getQueueHostHooks: () => getQueueHostHooks2,
|
|
737
|
+
getSecretsDriver: () => getSecretsDriver2,
|
|
738
|
+
matchesCron: () => matchesCron2,
|
|
739
|
+
nodeQueueHostHooks: () => nodeQueueHostHooks2,
|
|
740
|
+
scopedLockName: () => scopedLockName2,
|
|
741
|
+
setCronDriver: () => setCronDriver2,
|
|
742
|
+
setIdentityDriver: () => setIdentityDriver2,
|
|
743
|
+
setQueueHostHooks: () => setQueueHostHooks2,
|
|
744
|
+
setSecretsDriver: () => setSecretsDriver2,
|
|
745
|
+
shouldRunInWindow: () => shouldRunInWindow2
|
|
746
|
+
});
|
|
747
|
+
module.exports = __toCommonJS(drivers_exports2);
|
|
748
|
+
function load() {
|
|
749
|
+
return init_drivers(), __toCommonJS(drivers_exports);
|
|
750
|
+
}
|
|
751
|
+
function applySqlMigrations2(driver, migrations) {
|
|
752
|
+
return load().applySqlMigrations(driver, migrations);
|
|
753
|
+
}
|
|
754
|
+
function applyPaymentCoreMigrations2(driver) {
|
|
755
|
+
return load().applyPaymentCoreMigrations(driver);
|
|
756
|
+
}
|
|
757
|
+
function getPaymentCoreSqlMigrations() {
|
|
758
|
+
return load().paymentCoreSqlMigrations;
|
|
759
|
+
}
|
|
760
|
+
function createNodeDbDriver2(sequelize) {
|
|
761
|
+
return load().createNodeDbDriver(sequelize);
|
|
762
|
+
}
|
|
763
|
+
function createD1DbDriver2(binding) {
|
|
764
|
+
return load().createD1DbDriver(binding);
|
|
765
|
+
}
|
|
766
|
+
function createMemoryLocksDriver2() {
|
|
767
|
+
return load().createMemoryLocksDriver();
|
|
768
|
+
}
|
|
769
|
+
function createD1LocksDriver2(getBinding) {
|
|
770
|
+
return load().createD1LocksDriver(getBinding);
|
|
771
|
+
}
|
|
772
|
+
function scopedLockName2(name, instanceDid, scope) {
|
|
773
|
+
return load().scopedLockName(name, instanceDid, scope);
|
|
774
|
+
}
|
|
775
|
+
function createAuthStorage2(driver) {
|
|
776
|
+
return load().createAuthStorage(driver);
|
|
777
|
+
}
|
|
778
|
+
var nodeQueueHostHooks2 = {
|
|
779
|
+
async flush() {
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
function setQueueHostHooks2(hooks) {
|
|
783
|
+
load().setQueueHostHooks(hooks);
|
|
784
|
+
}
|
|
785
|
+
function getQueueHostHooks2() {
|
|
786
|
+
return load().getQueueHostHooks();
|
|
787
|
+
}
|
|
788
|
+
function createCronRegistry2(kind) {
|
|
789
|
+
return load().createCronRegistry(kind);
|
|
790
|
+
}
|
|
791
|
+
function createDefaultIdentityDriver2() {
|
|
792
|
+
return load().createDefaultIdentityDriver();
|
|
793
|
+
}
|
|
794
|
+
function setIdentityDriver2(driver) {
|
|
795
|
+
load().setIdentityDriver(driver);
|
|
796
|
+
}
|
|
797
|
+
function getIdentityDriver2() {
|
|
798
|
+
return load().getIdentityDriver();
|
|
799
|
+
}
|
|
800
|
+
function createDefaultSecretsDriver2() {
|
|
801
|
+
return load().createDefaultSecretsDriver();
|
|
802
|
+
}
|
|
803
|
+
function createKeyringSecretsDriver2(identity, opts) {
|
|
804
|
+
return load().createKeyringSecretsDriver(identity, opts);
|
|
805
|
+
}
|
|
806
|
+
function setSecretsDriver2(driver) {
|
|
807
|
+
load().setSecretsDriver(driver);
|
|
808
|
+
}
|
|
809
|
+
function getSecretsDriver2() {
|
|
810
|
+
return load().getSecretsDriver();
|
|
811
|
+
}
|
|
812
|
+
function setCronDriver2(driver) {
|
|
813
|
+
load().setCronDriver(driver);
|
|
814
|
+
}
|
|
815
|
+
function getCronDriver2() {
|
|
816
|
+
return load().getCronDriver();
|
|
817
|
+
}
|
|
818
|
+
function matchesCron2(expr, date) {
|
|
819
|
+
return load().matchesCron(expr, date);
|
|
820
|
+
}
|
|
821
|
+
function shouldRunInWindow2(expr, date) {
|
|
822
|
+
return load().shouldRunInWindow(expr, date);
|
|
823
|
+
}
|
|
824
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
825
|
+
0 && (module.exports = {
|
|
826
|
+
applyPaymentCoreMigrations,
|
|
827
|
+
applySqlMigrations,
|
|
828
|
+
createAuthStorage,
|
|
829
|
+
createCronRegistry,
|
|
830
|
+
createD1DbDriver,
|
|
831
|
+
createD1LocksDriver,
|
|
832
|
+
createDefaultIdentityDriver,
|
|
833
|
+
createDefaultSecretsDriver,
|
|
834
|
+
createKeyringSecretsDriver,
|
|
835
|
+
createMemoryLocksDriver,
|
|
836
|
+
createNodeDbDriver,
|
|
837
|
+
getCronDriver,
|
|
838
|
+
getIdentityDriver,
|
|
839
|
+
getPaymentCoreSqlMigrations,
|
|
840
|
+
getQueueHostHooks,
|
|
841
|
+
getSecretsDriver,
|
|
842
|
+
matchesCron,
|
|
843
|
+
nodeQueueHostHooks,
|
|
844
|
+
scopedLockName,
|
|
845
|
+
setCronDriver,
|
|
846
|
+
setIdentityDriver,
|
|
847
|
+
setQueueHostHooks,
|
|
848
|
+
setSecretsDriver,
|
|
849
|
+
shouldRunInWindow
|
|
850
|
+
});
|