@porulle/core 0.9.0 → 0.10.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/config/defaults.js +1 -1
- package/dist/config/types.d.ts +4 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/generated/plugin-manifest.d.ts +3 -0
- package/dist/generated/plugin-manifest.d.ts.map +1 -1
- package/dist/generated/plugin-manifest.js +1 -0
- package/dist/index.d.ts +5 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/interfaces/rest/router.d.ts.map +1 -1
- package/dist/interfaces/rest/router.js +2 -0
- package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/checkout.js +1 -0
- package/dist/interfaces/rest/schemas/catalog.d.ts +391 -0
- package/dist/interfaces/rest/schemas/catalog.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/responses.d.ts +51 -0
- package/dist/interfaces/rest/schemas/responses.d.ts.map +1 -1
- package/dist/interfaces/rest/schemas/search.d.ts +17 -0
- package/dist/interfaces/rest/schemas/search.d.ts.map +1 -1
- package/dist/kernel/database/adapter.d.ts +8 -0
- package/dist/kernel/database/adapter.d.ts.map +1 -1
- package/dist/kernel/database/migrate.d.ts +1 -1
- package/dist/kernel/database/migrate.d.ts.map +1 -1
- package/dist/kernel/database/migrate.js +5 -2
- package/dist/kernel/database/scoped-db.d.ts.map +1 -1
- package/dist/kernel/database/scoped-db.js +21 -23
- package/dist/kernel/errors.d.ts +12 -0
- package/dist/kernel/errors.d.ts.map +1 -1
- package/dist/kernel/errors.js +16 -0
- package/dist/kernel/jobs/adapter.d.ts +27 -8
- package/dist/kernel/jobs/adapter.d.ts.map +1 -1
- package/dist/kernel/jobs/adapter.js +1 -2
- package/dist/kernel/jobs/drizzle-adapter.d.ts +13 -3
- package/dist/kernel/jobs/drizzle-adapter.d.ts.map +1 -1
- package/dist/kernel/jobs/drizzle-adapter.js +46 -5
- package/dist/kernel/jobs/runner.d.ts +2 -1
- package/dist/kernel/jobs/runner.d.ts.map +1 -1
- package/dist/kernel/jobs/runner.js +100 -15
- package/dist/kernel/jobs/types.d.ts +13 -0
- package/dist/kernel/jobs/types.d.ts.map +1 -1
- package/dist/kernel/plugin/manifest.d.ts +2 -0
- package/dist/kernel/plugin/manifest.d.ts.map +1 -1
- package/dist/kernel/plugin/manifest.js +9 -0
- package/dist/modules/catalog/entity-service.d.ts +1 -0
- package/dist/modules/catalog/entity-service.d.ts.map +1 -1
- package/dist/modules/catalog/entity-service.js +15 -1
- package/dist/modules/catalog/repository/index.d.ts +2 -2
- package/dist/modules/catalog/repository/index.d.ts.map +1 -1
- package/dist/modules/catalog/repository/index.js +9 -1
- package/dist/modules/catalog/schema.d.ts +51 -0
- package/dist/modules/catalog/schema.d.ts.map +1 -1
- package/dist/modules/catalog/schema.js +12 -1
- package/dist/modules/catalog/schemas.d.ts +3 -1
- package/dist/modules/catalog/schemas.d.ts.map +1 -1
- package/dist/modules/channels/adapter.d.ts +117 -0
- package/dist/modules/channels/adapter.d.ts.map +1 -0
- package/dist/modules/channels/adapter.js +3 -0
- package/dist/modules/inventory/repository/index.js +4 -4
- package/dist/modules/inventory/service.d.ts.map +1 -1
- package/dist/modules/inventory/service.js +7 -3
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +7 -4
- package/dist/modules/orders/stale-order-cleanup.d.ts.map +1 -1
- package/dist/modules/orders/stale-order-cleanup.js +25 -16
- package/dist/modules/promotions/repository/index.d.ts +1 -1
- package/dist/modules/promotions/repository/index.d.ts.map +1 -1
- package/dist/modules/promotions/repository/index.js +6 -3
- package/dist/modules/promotions/service.d.ts +1 -0
- package/dist/modules/promotions/service.d.ts.map +1 -1
- package/dist/modules/promotions/service.js +1 -1
- package/dist/modules/webhooks/repository/index.d.ts +1 -1
- package/dist/modules/webhooks/repository/index.d.ts.map +1 -1
- package/dist/modules/webhooks/repository/index.js +16 -10
- package/dist/runtime/commerce.d.ts.map +1 -1
- package/dist/runtime/commerce.js +9 -0
- package/dist/runtime/kernel.d.ts.map +1 -1
- package/dist/runtime/kernel.js +14 -2
- package/dist/runtime/server.d.ts +1 -4
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/runtime/server.js +16 -34
- package/package.json +3 -3
- package/src/config/defaults.ts +1 -1
- package/src/config/types.ts +7 -3
- package/src/generated/plugin-capabilities.d.ts +1 -0
- package/src/generated/plugin-manifest.ts +1 -0
- package/src/generated/plugin-repositories.d.ts +1 -0
- package/src/index.ts +31 -1
- package/src/interfaces/rest/router.ts +2 -0
- package/src/interfaces/rest/routes/checkout.ts +1 -0
- package/src/kernel/database/adapter.ts +8 -0
- package/src/kernel/database/migrate.ts +8 -2
- package/src/kernel/database/scoped-db.ts +25 -26
- package/src/kernel/errors.ts +20 -0
- package/src/kernel/jobs/adapter.ts +39 -8
- package/src/kernel/jobs/drizzle-adapter.ts +72 -9
- package/src/kernel/jobs/runner.ts +194 -72
- package/src/kernel/jobs/types.ts +25 -0
- package/src/kernel/plugin/manifest.ts +12 -0
- package/src/modules/catalog/entity-service.ts +9 -1
- package/src/modules/catalog/repository/index.ts +13 -3
- package/src/modules/catalog/schema.ts +33 -18
- package/src/modules/catalog/schemas.ts +3 -1
- package/src/modules/channels/adapter.ts +139 -0
- package/src/modules/inventory/repository/index.ts +4 -4
- package/src/modules/inventory/service.ts +12 -2
- package/src/modules/orders/service.ts +8 -12
- package/src/modules/orders/stale-order-cleanup.ts +35 -24
- package/src/modules/promotions/repository/index.ts +6 -2
- package/src/modules/promotions/service.ts +2 -0
- package/src/modules/webhooks/repository/index.ts +16 -14
- package/src/runtime/commerce.ts +10 -0
- package/src/runtime/kernel.ts +16 -2
- package/src/runtime/server.ts +22 -42
|
@@ -14,6 +14,7 @@ function context(actor, services, database, tx = null) {
|
|
|
14
14
|
tx,
|
|
15
15
|
logger: createLogger("orders"),
|
|
16
16
|
services,
|
|
17
|
+
...(services.jobs ? { jobs: services.jobs } : {}),
|
|
17
18
|
context: { moduleName: "orders" },
|
|
18
19
|
database: { db: database.db },
|
|
19
20
|
});
|
|
@@ -425,8 +426,9 @@ export class OrderService {
|
|
|
425
426
|
}, actor, ctx);
|
|
426
427
|
if (!releaseResult.ok) {
|
|
427
428
|
const err = toCommerceError(releaseResult.error);
|
|
428
|
-
|
|
429
|
-
|
|
429
|
+
// Tolerate a missing inventory record (nothing to release); surface
|
|
430
|
+
// any other inventory error. Check the typed code, not the message.
|
|
431
|
+
if (err.code !== "INVENTORY_RECORD_NOT_FOUND") {
|
|
430
432
|
return Err(err);
|
|
431
433
|
}
|
|
432
434
|
}
|
|
@@ -495,8 +497,9 @@ export class OrderService {
|
|
|
495
497
|
}, actor, ctx);
|
|
496
498
|
if (!releaseResult.ok) {
|
|
497
499
|
const err = toCommerceError(releaseResult.error);
|
|
498
|
-
|
|
499
|
-
|
|
500
|
+
// Tolerate a missing inventory record (nothing to release); surface
|
|
501
|
+
// any other inventory error. Check the typed code, not the message.
|
|
502
|
+
if (err.code !== "INVENTORY_RECORD_NOT_FOUND") {
|
|
500
503
|
return Err(err);
|
|
501
504
|
}
|
|
502
505
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stale-order-cleanup.d.ts","sourceRoot":"","sources":["../../../src/modules/orders/stale-order-cleanup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAejE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,
|
|
1
|
+
{"version":3,"file":"stale-order-cleanup.d.ts","sourceRoot":"","sources":["../../../src/modules/orders/stale-order-cleanup.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAejE;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,qBAAqB,EAAE,cAAc,CAChD;IAAE,cAAc,CAAC,EAAE,MAAM,CAAA;CAAE,EAC3B;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,EAAE,CAAA;CAAE,CA6D/C,CAAC"}
|
|
@@ -36,25 +36,34 @@ export const staleOrderCleanupTask = {
|
|
|
36
36
|
async handler({ input, ctx }) {
|
|
37
37
|
const thresholdHours = input.thresholdHours ?? 48;
|
|
38
38
|
const cutoff = new Date(Date.now() - thresholdHours * 60 * 60 * 1000);
|
|
39
|
-
// Find stale pending orders
|
|
40
|
-
const staleOrders = await ctx.db
|
|
41
|
-
.select()
|
|
42
|
-
.from(orders)
|
|
43
|
-
.where(and(eq(orders.status, "pending"), lt(orders.placedAt, cutoff)));
|
|
44
39
|
const cancelledIds = [];
|
|
45
40
|
// Cancel each stale order via the service (triggers inventory release + payment refund)
|
|
46
41
|
const orderService = ctx.services.orders;
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
42
|
+
// This is a cross-org system sweep, but the row reads stay org-scoped: first
|
|
43
|
+
// enumerate the orgs that have stale orders (id-only projection), then read
|
|
44
|
+
// each org's stale orders under an explicit organizationId predicate. No
|
|
45
|
+
// query returns another tenant's order rows.
|
|
46
|
+
const staleOrgs = await ctx.db
|
|
47
|
+
.selectDistinct({ organizationId: orders.organizationId })
|
|
48
|
+
.from(orders)
|
|
49
|
+
.where(and(eq(orders.status, "pending"), lt(orders.placedAt, cutoff)));
|
|
50
|
+
for (const { organizationId } of staleOrgs) {
|
|
51
|
+
const staleOrders = await ctx.db
|
|
52
|
+
.select()
|
|
53
|
+
.from(orders)
|
|
54
|
+
.where(and(eq(orders.organizationId, organizationId), eq(orders.status, "pending"), lt(orders.placedAt, cutoff)));
|
|
55
|
+
for (const order of staleOrders) {
|
|
56
|
+
try {
|
|
57
|
+
await orderService.cancel(order.id, systemActorForOrg(order.organizationId), `Auto-cancelled: pending for >${thresholdHours}h`);
|
|
58
|
+
cancelledIds.push(order.id);
|
|
59
|
+
ctx.logger.info(`Stale order ${order.orderNumber} auto-cancelled`, {
|
|
60
|
+
orderId: order.id,
|
|
61
|
+
placedAt: order.placedAt,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch (error) {
|
|
65
|
+
ctx.logger.error(`Failed to cancel stale order ${order.orderNumber}`, { error });
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
}
|
|
60
69
|
return {
|
|
@@ -28,7 +28,7 @@ export declare class PromotionsRepository {
|
|
|
28
28
|
findUsageById(id: string, ctx?: TxContext): Promise<PromotionUsage | undefined>;
|
|
29
29
|
findUsagesByPromotionId(promotionId: string, ctx?: TxContext): Promise<PromotionUsage[]>;
|
|
30
30
|
findUsagesByCustomerId(customerId: string, ctx?: TxContext): Promise<PromotionUsage[]>;
|
|
31
|
-
createUsage(data: PromotionUsageInsert, ctx?: TxContext): Promise<PromotionUsage>;
|
|
31
|
+
createUsage(data: PromotionUsageInsert, orgId: string, ctx?: TxContext): Promise<PromotionUsage>;
|
|
32
32
|
countUsages(promotionId: string, ctx?: TxContext): Promise<number>;
|
|
33
33
|
countUsagesByCustomer(promotionId: string, customerId: string, ctx?: TxContext): Promise<number>;
|
|
34
34
|
isUsageLimitReached(orgId: string, promotionId: string, ctx?: TxContext): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/promotions/repository/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,UAAU,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAG3D,MAAM,MAAM,SAAS,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AACvD,MAAM,MAAM,eAAe,GAAG,OAAO,UAAU,CAAC,YAAY,CAAC;AAC7D,MAAM,MAAM,cAAc,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AACjE,MAAM,MAAM,oBAAoB,GAAG,OAAO,eAAe,CAAC,YAAY,CAAC;AAEvE;;;;;GAKG;AACH,qBAAa,oBAAoB;IACnB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,eAAe;IAEhD,OAAO,CAAC,KAAK;IAQP,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IASpF,UAAU,CACd,KAAK,EAAE,MAAM,EACb,IAAI,EAAE,MAAM,EACZ,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAc3B,OAAO,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAS7D,UAAU,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAkBhE,aAAa,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,EAAE,CAAC;IAmBnE,MAAM,CAAC,IAAI,EAAE,eAAe,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC;IAMlE,MAAM,CACV,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAC,EAC1C,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAU3B,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IASrD,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAIrE,UAAU,CACd,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,SAAS,GAAG,SAAS,CAAC;IAQ3B,aAAa,CACjB,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC;IAShC,uBAAuB,CAC3B,WAAW,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,cAAc,EAAE,CAAC;IAQtB,sBAAsB,CAC1B,UAAU,EAAE,MAAM,EAClB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,cAAc,EAAE,CAAC;IAQtB,WAAW,CACf,IAAI,EAAE,oBAAoB,EAC1B,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/promotions/repository/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -112,16 +112,19 @@ export class PromotionsRepository {
|
|
|
112
112
|
.from(promotionUsages)
|
|
113
113
|
.where(eq(promotionUsages.customerId, customerId));
|
|
114
114
|
}
|
|
115
|
-
async createUsage(data, ctx) {
|
|
115
|
+
async createUsage(data, orgId, ctx) {
|
|
116
116
|
const db = this.getDb(ctx);
|
|
117
117
|
// Atomic guard: use INSERT ... SELECT WHERE count < limit to prevent
|
|
118
118
|
// race conditions between concurrent checkouts using the same coupon.
|
|
119
119
|
// A plain count-then-insert has a TOCTOU gap; this single statement
|
|
120
120
|
// ensures the insert only succeeds if the limit has not been reached.
|
|
121
|
+
// Both reads are scoped by organizationId: these are raw/lock queries that
|
|
122
|
+
// bypass the scoped-db proxy, so a promotionId from another tenant must
|
|
123
|
+
// resolve to no row rather than reading/locking a foreign promotion.
|
|
121
124
|
const promo = await db
|
|
122
125
|
.select({ usageLimitTotal: promotions.usageLimitTotal })
|
|
123
126
|
.from(promotions)
|
|
124
|
-
.where(eq(promotions.id, data.promotionId));
|
|
127
|
+
.where(and(eq(promotions.id, data.promotionId), eq(promotions.organizationId, orgId)));
|
|
125
128
|
const limit = promo[0]?.usageLimitTotal;
|
|
126
129
|
if (limit != null) {
|
|
127
130
|
// Atomic guard: lock the promotion row and check usage count in the
|
|
@@ -131,7 +134,7 @@ export class PromotionsRepository {
|
|
|
131
134
|
// SELECT ... FOR UPDATE acquires a row-level lock that serializes
|
|
132
135
|
// concurrent callers. If the caller is already inside a transaction
|
|
133
136
|
// (ctx.tx), the lock is held until that transaction commits.
|
|
134
|
-
await db.execute(sql `SELECT id FROM promotions WHERE id = ${data.promotionId} FOR UPDATE`);
|
|
137
|
+
await db.execute(sql `SELECT id FROM promotions WHERE id = ${data.promotionId} AND organization_id = ${orgId} FOR UPDATE`);
|
|
135
138
|
const currentCount = await this.countUsages(data.promotionId, ctx);
|
|
136
139
|
if (currentCount >= limit) {
|
|
137
140
|
throw new Error(`Promotion usage limit reached (${currentCount}/${limit})`);
|
|
@@ -85,6 +85,7 @@ export declare class PromotionService {
|
|
|
85
85
|
applyPromotions(context: PromotionEvaluationContext, ctx?: TxContext): Promise<Result<PromotionApplicationResult>>;
|
|
86
86
|
recordUsage(input: {
|
|
87
87
|
promotions: AppliedPromotion[];
|
|
88
|
+
organizationId: string;
|
|
88
89
|
customerId?: string;
|
|
89
90
|
orderId?: string;
|
|
90
91
|
}, ctx?: TxContext): Promise<Result<PromotionUsage[]>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/promotions/service.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"service.d.ts","sourceRoot":"","sources":["../../../src/modules/promotions/service.ts"],"names":[],"mappings":"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"}
|
|
@@ -29,7 +29,7 @@ export declare class WebhooksRepository {
|
|
|
29
29
|
limit?: number;
|
|
30
30
|
}, ctx?: TxContext): Promise<WebhookDelivery[]>;
|
|
31
31
|
findPendingDeliveries(ctx?: TxContext): Promise<WebhookDelivery[]>;
|
|
32
|
-
findFailedDeliveries(endpointId?: string, ctx?: TxContext): Promise<WebhookDelivery[]>;
|
|
32
|
+
findFailedDeliveries(orgId: string, endpointId?: string, ctx?: TxContext): Promise<WebhookDelivery[]>;
|
|
33
33
|
createDelivery(data: WebhookDeliveryInsert, ctx?: TxContext): Promise<WebhookDelivery>;
|
|
34
34
|
updateDelivery(id: string, data: Partial<Omit<WebhookDeliveryInsert, "id">>, ctx?: TxContext): Promise<WebhookDelivery | undefined>;
|
|
35
35
|
markDelivered(id: string, statusCode: number, ctx?: TxContext): Promise<WebhookDelivery | undefined>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/webhooks/repository/index.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wCAAwC,CAAC;AACxE,OAAO,KAAK,EACV,eAAe,EAEhB,MAAM,wCAAwC,CAAC;AAChD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,cAAc,CAAC;AAGnE,MAAM,MAAM,eAAe,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAC;AACnE,MAAM,MAAM,qBAAqB,GAAG,OAAO,gBAAgB,CAAC,YAAY,CAAC;AACzE,MAAM,MAAM,eAAe,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAC;AACpE,MAAM,MAAM,qBAAqB,GAAG,OAAO,iBAAiB,CAAC,YAAY,CAAC;AAE1E;;;;;GAKG;AACH,qBAAa,kBAAkB;IACjB,OAAO,CAAC,QAAQ,CAAC,EAAE;gBAAF,EAAE,EAAE,eAAe;IAEhD,OAAO,CAAC,KAAK;IAaP,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAcjC,gBAAgB,CACpB,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,EAAE,CAAC;IAQvB,mBAAmB,CACvB,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,EAAE,CAAC;IAavB,qBAAqB,CACzB,SAAS,EAAE,MAAM,EACjB,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,EAAE,CAAC;IASvB,cAAc,CAClB,IAAI,EAAE,qBAAqB,EAC3B,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,CAAC;IAMrB,cAAc,CAClB,EAAE,EAAE,MAAM,EACV,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC,EAChD,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAUjC,cAAc,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,OAAO,CAAC;IAS7D,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAIjC,kBAAkB,CACtB,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IAQjC,gBAAgB,CACpB,EAAE,EAAE,MAAM,EACV,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,GAAG,SAAS,CAAC;IASjC,0BAA0B,CAC9B,UAAU,EAAE,MAAM,EAClB,OAAO,CAAC,EAAE;QAAE,KAAK,CAAC,EAAE,MAAM,CAAA;KAAE,EAC5B,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,EAAE,CAAC;IAgBvB,qBAAqB,CAAC,GAAG,CAAC,EAAE,SAAS,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;IAoBlE,oBAAoB,CACxB,UAAU,CAAC,EAAE,MAAM,EACnB,GAAG,CAAC,EAAE,SAAS,GACd,OAAO,CAAC,eAAe,EAAE,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/modules/webhooks/repository/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { eq, and, lte, isNull, or, desc, sql } from "drizzle-orm";
|
|
1
|
+
import { eq, and, lte, isNull, or, desc, sql, inArray } from "drizzle-orm";
|
|
2
2
|
import { webhookEndpoints, webhookDeliveries } from "../schema.js";
|
|
3
3
|
/**
|
|
4
4
|
* WebhooksRepository provides type-safe database operations for webhooks.
|
|
@@ -113,19 +113,25 @@ export class WebhooksRepository {
|
|
|
113
113
|
.where(and(isNull(webhookDeliveries.deliveredAt), isNull(webhookDeliveries.failedAt), or(isNull(webhookDeliveries.nextRetryAt), lte(webhookDeliveries.nextRetryAt, now))))
|
|
114
114
|
.orderBy(webhookDeliveries.createdAt);
|
|
115
115
|
}
|
|
116
|
-
async findFailedDeliveries(endpointId, ctx) {
|
|
116
|
+
async findFailedDeliveries(orgId, endpointId, ctx) {
|
|
117
117
|
const db = this.getDb(ctx);
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
// webhook_deliveries has no organizationId column — org lives on the parent
|
|
119
|
+
// endpoint. Scope failed deliveries to endpoints owned by orgId so this can
|
|
120
|
+
// never read another tenant's deliveries.
|
|
121
|
+
const orgEndpointIds = db
|
|
122
|
+
.select({ id: webhookEndpoints.id })
|
|
123
|
+
.from(webhookEndpoints)
|
|
124
|
+
.where(eq(webhookEndpoints.organizationId, orgId));
|
|
125
|
+
const conditions = [
|
|
126
|
+
sql `${webhookDeliveries.failedAt} IS NOT NULL`,
|
|
127
|
+
inArray(webhookDeliveries.endpointId, orgEndpointIds),
|
|
128
|
+
];
|
|
129
|
+
if (endpointId)
|
|
130
|
+
conditions.push(eq(webhookDeliveries.endpointId, endpointId));
|
|
125
131
|
return db
|
|
126
132
|
.select()
|
|
127
133
|
.from(webhookDeliveries)
|
|
128
|
-
.where(
|
|
134
|
+
.where(and(...conditions))
|
|
129
135
|
.orderBy(desc(webhookDeliveries.failedAt));
|
|
130
136
|
}
|
|
131
137
|
async createDelivery(data, ctx) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../src/runtime/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"commerce.d.ts","sourceRoot":"","sources":["../../src/runtime/commerce.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAK1C,OAAO,EAAc,KAAK,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACjE,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAkB,KAAK,gBAAgB,EAAwB,MAAM,wBAAwB,CAAC;AAErG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoDG;AACH,MAAM,WAAW,gBAAgB;IAC/B,0EAA0E;IAC1E,GAAG,EAAE,gBAAgB,CAAC;IAEtB,8DAA8D;IAC9D,MAAM,EAAE,MAAM,CAAC;IAEf,mDAAmD;IACnD,EAAE,EAAE,OAAO,CAAC;IAEZ,yDAAyD;IACzD,IAAI,EAAE,YAAY,CAAC;IAEnB,aAAa;IACb,MAAM,EAAE,MAAM,CAAC;IAEf;;;;;;;;;;;;OAYG;IACH,SAAS,CAAC,KAAK,EAAE,KAAK,GAAG,gBAAgB,CAAC;IAE1C;;;;;;;;;;OAUG;IACH,eAAe,CAAC,EAAE,EAAE,OAAO,EAAE,KAAK,CAAC,EAAE,KAAK,GAAG,IAAI,GAAG,gBAAgB,CAAC;CACtE;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,cAAc,CAClC,MAAM,EAAE,cAAc,GACrB,OAAO,CAAC,gBAAgB,CAAC,CA6C3B"}
|
package/dist/runtime/commerce.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { createKernel } from "./kernel.js";
|
|
2
|
+
import { pushSchema } from "../kernel/database/migrate.js";
|
|
2
3
|
import { ensureDefaultOrg, setBootDefaultOrgId } from "../auth/org.js";
|
|
3
4
|
import { setBootStrictOrgResolution } from "../auth/strict-org-resolution.js";
|
|
4
5
|
import { createAuth } from "../auth/setup.js";
|
|
@@ -17,6 +18,14 @@ import { createLocalAPI } from "../kernel/local-api.js";
|
|
|
17
18
|
*/
|
|
18
19
|
export async function createCommerce(config) {
|
|
19
20
|
const kernel = createKernel(config);
|
|
21
|
+
// Zero-migration adapters (PGlite) push core schema at construction, but a
|
|
22
|
+
// plugin's own tables live in `config.customSchemas`, which only exist after
|
|
23
|
+
// plugins run in `defineConfig` — i.e. after the adapter was constructed.
|
|
24
|
+
// Create them now so plugin routes have their tables. Guarded on both signals
|
|
25
|
+
// so plugin-less stores and migration-managed adapters (Postgres) are untouched.
|
|
26
|
+
if (config.databaseAdapter?.autoMigrate && config.customSchemas?.length) {
|
|
27
|
+
await pushSchema(kernel.database.db, config);
|
|
28
|
+
}
|
|
20
29
|
setBootStrictOrgResolution(config.auth?.strictOrgResolution === true);
|
|
21
30
|
// Register the config-driven org ID so resolveOrgId() can use it
|
|
22
31
|
// without requiring every service to have config access.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"kernel.d.ts","sourceRoot":"","sources":["../../src/runtime/kernel.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAqBzD,OAAO,EAGL,KAAK,MAAM,EACX,KAAK,sBAAsB,EAC5B,MAAM,mBAAmB,CAAC;AAE3B,YAAY,EAAE,MAAM,EAAE,sBAAsB,EAAE,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,8BAA8B,GAC/B,MAAM,qBAAqB,CAAC;AAE7B,wBAAgB,YAAY,CAAC,MAAM,EAAE,cAAc,GAAG,MAAM,CA0I3D"}
|
package/dist/runtime/kernel.js
CHANGED
|
@@ -44,8 +44,20 @@ export function createKernel(config) {
|
|
|
44
44
|
serviceContainer.database = database;
|
|
45
45
|
const db = database.db;
|
|
46
46
|
const jobsTaskMap = new Map((config.jobs?.tasks ?? []).map((t) => [t.slug, t]));
|
|
47
|
-
const
|
|
48
|
-
|
|
47
|
+
const jobsEngine = config.jobs?.adapter ?? new DrizzleJobsAdapter(db);
|
|
48
|
+
const jobLogger = {
|
|
49
|
+
info: (message, data) => logger.info(message, data),
|
|
50
|
+
warn: (message, data) => logger.warn(message, data),
|
|
51
|
+
error: (message, data) => logger.error(message, data),
|
|
52
|
+
};
|
|
53
|
+
jobsEngine.register({
|
|
54
|
+
tasks: jobsTaskMap,
|
|
55
|
+
context: { logger: jobLogger, db, services: serviceContainer },
|
|
56
|
+
...(config.jobs?.processingOrder !== undefined
|
|
57
|
+
? { processingOrder: config.jobs.processingOrder }
|
|
58
|
+
: {}),
|
|
59
|
+
});
|
|
60
|
+
serviceContainer.jobs = jobsEngine;
|
|
49
61
|
const topoGraph = kernelModulesForTopoSort();
|
|
50
62
|
const order = topoSortModules(topoGraph);
|
|
51
63
|
const moduleKeys = Object.keys(KERNEL_ALL_MODULES);
|
package/dist/runtime/server.d.ts
CHANGED
|
@@ -32,10 +32,7 @@ export declare function createServer(config: CommerceConfig): Promise<{
|
|
|
32
32
|
kernel: import("./kernel-types.js").Kernel;
|
|
33
33
|
logger: Logger;
|
|
34
34
|
commerce: CommerceInstance;
|
|
35
|
-
runJobs: (queue?: string, limit?: number) => Promise<
|
|
36
|
-
processed: number;
|
|
37
|
-
failed: number;
|
|
38
|
-
}>;
|
|
35
|
+
runJobs: (queue?: string, limit?: number) => Promise<import("../kernel/jobs/adapter.js").RunJobsResult>;
|
|
39
36
|
}>;
|
|
40
37
|
export {};
|
|
41
38
|
//# sourceMappingURL=server.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/runtime/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQhD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/runtime/server.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQhD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOzD,OAAO,EAAgB,KAAK,MAAM,EAAE,MAAM,aAAa,CAAC;AACxD,OAAO,EAAkB,KAAK,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAItE,KAAK,SAAS,GAAG;IACf,SAAS,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;QACpB,SAAS,EAAE,MAAM,CAAC;QAClB,MAAM,EAAE,MAAM,CAAC;KAChB,CAAC;CACH,CAAC;AAEF;;;;;;;GAOG;AACH,wBAAgB,aAAa,IAAI,OAAO,CAMvC;AAeD;;;;;GAKG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,cAAc;;;;;sBAyVxB,MAAM,UAAU,MAAM;GA2FtD"}
|
package/dist/runtime/server.js
CHANGED
|
@@ -345,41 +345,15 @@ export async function createServer(config) {
|
|
|
345
345
|
// 1. autorun: in-process polling (long-running servers)
|
|
346
346
|
// 2. GET /api/jobs/run: cron endpoint (serverless — Vercel, Cloudflare)
|
|
347
347
|
// 3. runPendingJobs() export (custom worker process)
|
|
348
|
-
const
|
|
349
|
-
|
|
350
|
-
const taskMap = new Map();
|
|
351
|
-
for (const task of config.jobs?.tasks ?? []) {
|
|
352
|
-
const t = task;
|
|
353
|
-
taskMap.set(t.slug ?? t.name ?? "", task);
|
|
354
|
-
}
|
|
355
|
-
const jobLogger = {
|
|
356
|
-
info: (msg, data) => logger.info(data != null ? { data } : {}, msg),
|
|
357
|
-
warn: (msg, data) => logger.warn(data != null ? { data } : {}, msg),
|
|
358
|
-
error: (msg, data) => logger.error(data != null ? { data } : {}, msg),
|
|
359
|
-
};
|
|
360
|
-
let lastStaleJobReaperAt = 0;
|
|
361
|
-
const maybeRunStaleJobReaper = async () => {
|
|
362
|
-
const interval = getJobsReaperIntervalMs();
|
|
363
|
-
const now = Date.now();
|
|
364
|
-
if (now - lastStaleJobReaperAt < interval)
|
|
365
|
-
return;
|
|
366
|
-
lastStaleJobReaperAt = now;
|
|
367
|
-
try {
|
|
368
|
-
await runStaleJobReaper(kernel.database.db, getJobReapThresholdMs(), jobLogger);
|
|
369
|
-
}
|
|
370
|
-
catch (err) {
|
|
371
|
-
logger.error({ err }, "Stale job reaper failed");
|
|
372
|
-
}
|
|
373
|
-
};
|
|
348
|
+
const jobsEngine = kernel.services
|
|
349
|
+
.jobs;
|
|
374
350
|
const runJobs = async (queue, limit) => {
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
351
|
+
if (jobsEngine.execution.mode !== "pull") {
|
|
352
|
+
throw new Error("The configured push execution engine is driven by its native runtime and cannot be polled with runJobs().");
|
|
353
|
+
}
|
|
354
|
+
return jobsEngine.execution.run({
|
|
379
355
|
queue: queue ?? "default",
|
|
380
356
|
limit: limit ?? 10,
|
|
381
|
-
logger: jobLogger,
|
|
382
|
-
services: kernel.services,
|
|
383
357
|
});
|
|
384
358
|
};
|
|
385
359
|
// Strategy 1: Built-in cron endpoint for serverless deployments.
|
|
@@ -405,6 +379,9 @@ export async function createServer(config) {
|
|
|
405
379
|
// Strategy 2: In-process polling for long-running servers (ECS, Cloud Run, Docker).
|
|
406
380
|
// Enable via config.jobs.autorun.enabled = true
|
|
407
381
|
if (config.jobs?.autorun?.enabled) {
|
|
382
|
+
if (jobsEngine.execution.mode !== "pull") {
|
|
383
|
+
throw new Error("jobs.autorun is only valid for pull execution engines. Serve the configured push engine through its native runtime.");
|
|
384
|
+
}
|
|
408
385
|
const intervalMs = config.jobs.autorun.intervalMs ?? 10_000;
|
|
409
386
|
const jobInterval = setInterval(async () => {
|
|
410
387
|
try {
|
|
@@ -420,8 +397,13 @@ export async function createServer(config) {
|
|
|
420
397
|
logger.info({ intervalMs }, "Job queue autorun started (in-process polling)");
|
|
421
398
|
}
|
|
422
399
|
else {
|
|
423
|
-
|
|
424
|
-
"
|
|
400
|
+
if (jobsEngine.execution.mode === "push") {
|
|
401
|
+
logger.info("Push job engine registered. Serve it through its native runtime.");
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
logger.info("Job queue autorun disabled. Use GET /api/jobs/run for serverless cron, " +
|
|
405
|
+
"or set config.jobs.autorun.enabled = true for in-process polling.");
|
|
406
|
+
}
|
|
425
407
|
}
|
|
426
408
|
const dispatchFetch = app.fetch.bind(app);
|
|
427
409
|
app.fetch = ((input, env, executionCtx) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@porulle/core",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.10.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -56,8 +56,8 @@
|
|
|
56
56
|
"eslint": "^9.39.1",
|
|
57
57
|
"typescript": "5.9.2",
|
|
58
58
|
"vitest": "^3.2.4",
|
|
59
|
-
"@porulle/
|
|
60
|
-
"@porulle/
|
|
59
|
+
"@porulle/eslint-config": "0.1.0",
|
|
60
|
+
"@porulle/typescript-config": "0.1.0"
|
|
61
61
|
},
|
|
62
62
|
"publishConfig": {
|
|
63
63
|
"access": "public"
|
package/src/config/defaults.ts
CHANGED
|
@@ -17,7 +17,7 @@ export const defaultConfig: Partial<CommerceConfig> = {
|
|
|
17
17
|
},
|
|
18
18
|
roles: {
|
|
19
19
|
owner: { permissions: ["*:*"] },
|
|
20
|
-
admin: { permissions: ["*:*", "compensation:admin"] },
|
|
20
|
+
admin: { permissions: ["*:*", "catalog:sync", "compensation:admin"] },
|
|
21
21
|
manager: {
|
|
22
22
|
permissions: [
|
|
23
23
|
"catalog:create",
|
package/src/config/types.ts
CHANGED
|
@@ -8,8 +8,11 @@ import type { AuthInstance } from "../auth/setup.js";
|
|
|
8
8
|
import type { DatabaseAdapter } from "../kernel/database/adapter.js";
|
|
9
9
|
import type { TaxAdapter } from "../modules/tax/adapter.js";
|
|
10
10
|
import type { SearchAdapter } from "../modules/search/adapter.js";
|
|
11
|
-
import type {
|
|
12
|
-
import type {
|
|
11
|
+
import type { ExecutionEngine } from "../kernel/jobs/adapter.js";
|
|
12
|
+
import type {
|
|
13
|
+
JobProcessingOrder,
|
|
14
|
+
TaskDefinition,
|
|
15
|
+
} from "../kernel/jobs/types.js";
|
|
13
16
|
|
|
14
17
|
export interface RoleDefinition {
|
|
15
18
|
permissions: string[];
|
|
@@ -353,8 +356,9 @@ export interface CommerceConfig {
|
|
|
353
356
|
analytics?: AnalyticsConfig;
|
|
354
357
|
search?: SearchConfig;
|
|
355
358
|
jobs?: {
|
|
356
|
-
adapter?:
|
|
359
|
+
adapter?: ExecutionEngine;
|
|
357
360
|
tasks?: TaskDefinition[];
|
|
361
|
+
processingOrder?: JobProcessingOrder;
|
|
358
362
|
autorun?: {
|
|
359
363
|
enabled: boolean;
|
|
360
364
|
intervalMs?: number;
|
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
|
|
5
5
|
export const resolvedPluginManifest = [
|
|
6
6
|
{ id: "appointments", directory: "plugin-appointments" },
|
|
7
|
+
{ id: "channel-connector", directory: "plugin-channel-connector" },
|
|
7
8
|
{ id: "gift-cards", directory: "plugin-gift-cards" },
|
|
8
9
|
{ id: "layaway", directory: "plugin-layaway" },
|
|
9
10
|
{ id: "loyalty", directory: "plugin-loyalty" },
|
package/src/index.ts
CHANGED
|
@@ -32,6 +32,7 @@ export type { Kernel } from "./runtime/kernel.js";
|
|
|
32
32
|
|
|
33
33
|
export type { Actor } from "./auth/types.js";
|
|
34
34
|
export { resolveOrgId, ensureDefaultOrg, DEFAULT_ORG_ID } from "./auth/org.js";
|
|
35
|
+
export { createSystemActor } from "./auth/system-actor.js";
|
|
35
36
|
export { OrganizationService } from "./modules/organization/service.js";
|
|
36
37
|
export { createScopedDb } from "./kernel/database/scoped-db.js";
|
|
37
38
|
export type { ScopedOrganizationId } from "./kernel/database/scoped-db.js";
|
|
@@ -61,7 +62,15 @@ export type {
|
|
|
61
62
|
export { runBeforeHooks, runAfterHooks } from "./kernel/hooks/executor.js";
|
|
62
63
|
export { createHookContext } from "./kernel/hooks/create-context.js";
|
|
63
64
|
export type { CreateHookContextArgs } from "./kernel/hooks/create-context.js";
|
|
64
|
-
export type {
|
|
65
|
+
export type {
|
|
66
|
+
JobsAdapter,
|
|
67
|
+
EnqueueOptions,
|
|
68
|
+
ExecutionDriver,
|
|
69
|
+
ExecutionEngine,
|
|
70
|
+
ExecutionEngineSetup,
|
|
71
|
+
RunJobsOptions,
|
|
72
|
+
RunJobsResult,
|
|
73
|
+
} from "./kernel/jobs/adapter.js";
|
|
65
74
|
export { NullJobsAdapter } from "./kernel/jobs/adapter.js";
|
|
66
75
|
export { DrizzleJobsAdapter } from "./kernel/jobs/drizzle-adapter.js";
|
|
67
76
|
export { runPendingJobs } from "./kernel/jobs/runner.js";
|
|
@@ -71,6 +80,9 @@ export type {
|
|
|
71
80
|
TaskContext,
|
|
72
81
|
TaskJobMeta,
|
|
73
82
|
TaskRetryConfig,
|
|
83
|
+
JobProcessingOrder,
|
|
84
|
+
JobProcessingOrderField,
|
|
85
|
+
JobProcessingOrderRecord,
|
|
74
86
|
} from "./kernel/jobs/types.js";
|
|
75
87
|
export { BUILTIN_JOB_TASK_SLUGS } from "./kernel/jobs/types.js";
|
|
76
88
|
export {
|
|
@@ -127,6 +139,24 @@ export type {
|
|
|
127
139
|
PaymentRefund,
|
|
128
140
|
PaymentWebhookEvent,
|
|
129
141
|
} from "./modules/payments/adapter.js";
|
|
142
|
+
export { defineChannelConnector } from "./modules/channels/adapter.js";
|
|
143
|
+
export type {
|
|
144
|
+
ChannelCatalogItem,
|
|
145
|
+
ChannelCatalogPage,
|
|
146
|
+
ChannelCatalogVariant,
|
|
147
|
+
ChannelConnector,
|
|
148
|
+
ChannelConnectorCapabilities,
|
|
149
|
+
ChannelInventoryLevel,
|
|
150
|
+
ChannelOrderLine,
|
|
151
|
+
ChannelOrderSlice,
|
|
152
|
+
ChannelConnectorError,
|
|
153
|
+
ChannelOrderStatus,
|
|
154
|
+
ChannelPushOrderResult,
|
|
155
|
+
ChannelRefundResult,
|
|
156
|
+
ChannelReservation,
|
|
157
|
+
ChannelStore,
|
|
158
|
+
ChannelWebhookEvent,
|
|
159
|
+
} from "./modules/channels/adapter.js";
|
|
130
160
|
export type { StorageAdapter } from "./modules/media/adapter.js";
|
|
131
161
|
export { noopStorageAdapter } from "./modules/media/noop-adapter.js";
|
|
132
162
|
export type {
|
|
@@ -286,6 +286,7 @@ export function checkoutRoutes(kernel: Kernel) {
|
|
|
286
286
|
if (order.ok && (processed.appliedPromotions?.length ?? 0) > 0) {
|
|
287
287
|
await kernel.services.promotions.recordUsage({
|
|
288
288
|
promotions: processed.appliedPromotions ?? [],
|
|
289
|
+
organizationId: order.value.organizationId,
|
|
289
290
|
orderId: order.value.id,
|
|
290
291
|
...(customerUuid !== undefined
|
|
291
292
|
? { customerId: customerUuid }
|
|
@@ -10,6 +10,14 @@ export interface DatabaseAdapter<TDatabase = unknown, TTransaction = unknown> {
|
|
|
10
10
|
provider: string;
|
|
11
11
|
db: TDatabase;
|
|
12
12
|
transaction<T>(fn: (tx: TTransaction) => Promise<T>): Promise<T>;
|
|
13
|
+
/**
|
|
14
|
+
* Zero-migration adapters (e.g. PGlite) set this so the runtime pushes any
|
|
15
|
+
* plugin-declared tables (`config.customSchemas`) at boot. Plugin schemas
|
|
16
|
+
* only exist after plugins run in `defineConfig` — i.e. after this adapter was
|
|
17
|
+
* constructed — so the adapter cannot create them itself. Omit/false when the
|
|
18
|
+
* consumer manages migrations (e.g. production Postgres via drizzle-kit).
|
|
19
|
+
*/
|
|
20
|
+
autoMigrate?: boolean;
|
|
13
21
|
}
|
|
14
22
|
|
|
15
23
|
export interface DatabaseConnectionFactoryInput {
|
|
@@ -103,7 +103,10 @@ export function getSchemaFiles(): string[] {
|
|
|
103
103
|
* Drizzle instance bound to your database. `drizzle-kit` must be available
|
|
104
104
|
* (it is the standard schema tool); a clear error is thrown if it is not.
|
|
105
105
|
*/
|
|
106
|
-
export async function pushSchema(
|
|
106
|
+
export async function pushSchema(
|
|
107
|
+
drizzleInstance: unknown,
|
|
108
|
+
config?: CommerceConfig,
|
|
109
|
+
): Promise<void> {
|
|
107
110
|
const require = createRequire(import.meta.url);
|
|
108
111
|
let drizzleKit: {
|
|
109
112
|
pushSchema(
|
|
@@ -118,7 +121,10 @@ export async function pushSchema(drizzleInstance: unknown): Promise<void> {
|
|
|
118
121
|
"pushSchema() requires `drizzle-kit` to be installed. Add it to your project: bun add -d drizzle-kit",
|
|
119
122
|
);
|
|
120
123
|
}
|
|
124
|
+
// With a config, push the merged core + plugin schema so plugin-declared
|
|
125
|
+
// tables are created too; without one, push core only (backward compatible).
|
|
126
|
+
const schemaToApply = config ? buildSchema(config) : getSchema();
|
|
121
127
|
// drizzle-kit needs the native driver result shape; unwrap a normalized db.
|
|
122
|
-
const { apply } = await drizzleKit.pushSchema(
|
|
128
|
+
const { apply } = await drizzleKit.pushSchema(schemaToApply, unwrapDb(drizzleInstance));
|
|
123
129
|
await apply();
|
|
124
130
|
}
|