@porulle/core 0.8.0 → 0.10.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +26 -7
- package/dist/auth/setup.d.ts.map +1 -1
- package/dist/auth/setup.js +7 -5
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +3 -1
- package/dist/config/types.d.ts +13 -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/hooks/checkout-completion.d.ts.map +1 -1
- package/dist/hooks/checkout-completion.js +2 -2
- package/dist/hooks/checkout.d.ts.map +1 -1
- package/dist/hooks/checkout.js +1 -1
- 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/admin/staff.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/staff.js +37 -3
- package/dist/interfaces/rest/routes/checkout.d.ts +9 -0
- package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/checkout.js +82 -22
- package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/inventory.js +13 -0
- package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/orders.js +13 -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/orders.js +2 -2
- package/dist/interfaces/rest/schemas/responses.d.ts +85 -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/scoped-db.d.ts +2 -1
- package/dist/kernel/database/scoped-db.d.ts.map +1 -1
- package/dist/kernel/database/scoped-db.js +74 -15
- 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 +5 -0
- package/dist/kernel/plugin/manifest.d.ts.map +1 -1
- package/dist/kernel/plugin/manifest.js +9 -0
- package/dist/modules/analytics/drizzle-adapter.d.ts.map +1 -1
- package/dist/modules/analytics/drizzle-adapter.js +16 -3
- package/dist/modules/cart/service.d.ts.map +1 -1
- package/dist/modules/cart/service.js +3 -2
- 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 +49 -3
- 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/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +6 -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/schema.d.ts +17 -0
- package/dist/modules/orders/schema.d.ts.map +1 -1
- package/dist/modules/orders/schema.js +4 -0
- package/dist/modules/orders/service.d.ts +16 -2
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +226 -26
- package/dist/modules/orders/stale-order-cleanup.d.ts.map +1 -1
- package/dist/modules/orders/stale-order-cleanup.js +37 -16
- package/dist/modules/pricing/service.d.ts.map +1 -1
- package/dist/modules/pricing/service.js +5 -5
- 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/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/dist/test-utils/create-test-config.d.ts.map +1 -1
- package/dist/test-utils/create-test-config.js +2 -0
- package/dist/test-utils/order-test-helpers.d.ts +12 -0
- package/dist/test-utils/order-test-helpers.d.ts.map +1 -0
- package/dist/test-utils/order-test-helpers.js +18 -0
- package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
- package/dist/test-utils/rest-api-test-utils.js +1 -0
- package/dist/test-utils/test-actors.js +1 -1
- package/dist/testing.d.ts +1 -0
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +1 -0
- package/package.json +1 -1
- package/src/auth/middleware.ts +26 -7
- package/src/auth/setup.ts +10 -4
- package/src/config/defaults.ts +3 -1
- package/src/config/types.ts +16 -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/hooks/checkout-completion.ts +22 -16
- package/src/hooks/checkout.ts +11 -8
- package/src/index.ts +31 -1
- package/src/interfaces/rest/router.ts +2 -0
- package/src/interfaces/rest/routes/admin/staff.ts +45 -3
- package/src/interfaces/rest/routes/checkout.ts +94 -28
- package/src/interfaces/rest/routes/inventory.ts +14 -0
- package/src/interfaces/rest/routes/orders.ts +11 -0
- package/src/interfaces/rest/schemas/orders.ts +2 -2
- package/src/kernel/database/scoped-db.ts +83 -15
- 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 +15 -0
- package/src/modules/analytics/drizzle-adapter.ts +19 -3
- package/src/modules/cart/service.ts +3 -2
- package/src/modules/catalog/entity-service.ts +37 -2
- 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/customers/service.ts +6 -0
- package/src/modules/inventory/repository/index.ts +4 -4
- package/src/modules/inventory/service.ts +12 -2
- package/src/modules/orders/schema.ts +4 -0
- package/src/modules/orders/service.ts +404 -64
- package/src/modules/orders/stale-order-cleanup.ts +52 -27
- package/src/modules/pricing/service.ts +5 -6
- 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/kernel.ts +16 -2
- package/src/runtime/server.ts +22 -42
- package/src/test-utils/create-test-config.ts +2 -0
- package/src/test-utils/order-test-helpers.ts +26 -0
- package/src/test-utils/rest-api-test-utils.ts +1 -0
- package/src/test-utils/test-actors.ts +1 -1
- package/src/testing.ts +1 -0
|
@@ -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":"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) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,
|
|
1
|
+
{"version":3,"file":"create-test-config.d.ts","sourceRoot":"","sources":["../../src/test-utils/create-test-config.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAgDzD,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC,cAAc,CAAC,CAiHzB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,sBAAsB,CAC1C,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IAAE,MAAM,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAA;CAAE,CAAC,CAUnE"}
|
|
@@ -53,6 +53,7 @@ export async function createTestConfig(overrides = {}) {
|
|
|
53
53
|
provider: "postgresql",
|
|
54
54
|
},
|
|
55
55
|
auth: {
|
|
56
|
+
allowTestActor: true,
|
|
56
57
|
defaultOrganizationId: "org_default",
|
|
57
58
|
requireEmailVerification: false,
|
|
58
59
|
apiKeys: { enabled: true, defaultPermissions: ["catalog:read"] },
|
|
@@ -70,6 +71,7 @@ export async function createTestConfig(overrides = {}) {
|
|
|
70
71
|
"orders:create",
|
|
71
72
|
"orders:read",
|
|
72
73
|
"orders:update",
|
|
74
|
+
"orders:manage",
|
|
73
75
|
"cart:create",
|
|
74
76
|
"cart:update",
|
|
75
77
|
"customers:update:self",
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { Kernel } from "../runtime/kernel.js";
|
|
2
|
+
/**
|
|
3
|
+
* Mark an order as paid (captured) for tests.
|
|
4
|
+
*
|
|
5
|
+
* Refund and return flows require a paid order — a refund moves collected money,
|
|
6
|
+
* and the order primitive rejects refunds on unpaid/pending orders. There is no
|
|
7
|
+
* public "set captured amount" service (capture() needs a live payment intent),
|
|
8
|
+
* so tests set the column here through a single typed helper rather than
|
|
9
|
+
* scattering raw SQL / `as any` casts across test files.
|
|
10
|
+
*/
|
|
11
|
+
export declare function markOrderPaidForTest(kernel: Kernel, orderId: string, amountCaptured: number, paymentIntentId?: string): Promise<void>;
|
|
12
|
+
//# sourceMappingURL=order-test-helpers.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"order-test-helpers.d.ts","sourceRoot":"","sources":["../../src/test-utils/order-test-helpers.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,sBAAsB,CAAC;AAGnD;;;;;;;;GAQG;AACH,wBAAsB,oBAAoB,CACxC,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,MAAM,EACf,cAAc,EAAE,MAAM,EACtB,eAAe,CAAC,EAAE,MAAM,GACvB,OAAO,CAAC,IAAI,CAAC,CAMf"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { eq } from "drizzle-orm";
|
|
2
|
+
import { orders } from "../modules/orders/schema.js";
|
|
3
|
+
/**
|
|
4
|
+
* Mark an order as paid (captured) for tests.
|
|
5
|
+
*
|
|
6
|
+
* Refund and return flows require a paid order — a refund moves collected money,
|
|
7
|
+
* and the order primitive rejects refunds on unpaid/pending orders. There is no
|
|
8
|
+
* public "set captured amount" service (capture() needs a live payment intent),
|
|
9
|
+
* so tests set the column here through a single typed helper rather than
|
|
10
|
+
* scattering raw SQL / `as any` casts across test files.
|
|
11
|
+
*/
|
|
12
|
+
export async function markOrderPaidForTest(kernel, orderId, amountCaptured, paymentIntentId) {
|
|
13
|
+
const db = kernel.database.db;
|
|
14
|
+
await db
|
|
15
|
+
.update(orders)
|
|
16
|
+
.set({ amountCaptured, ...(paymentIntentId ? { paymentIntentId } : {}) })
|
|
17
|
+
.where(eq(orders.id, orderId));
|
|
18
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rest-api-test-utils.d.ts","sourceRoot":"","sources":["../../src/test-utils/rest-api-test-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,KAAK,SAAS,GAAG;IACf,SAAS,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAiDF;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IACT,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAqDD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAEnF;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,
|
|
1
|
+
{"version":3,"file":"rest-api-test-utils.d.ts","sourceRoot":"","sources":["../../src/test-utils/rest-api-test-utils.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAC5B,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAOpD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC;AAErD,KAAK,SAAS,GAAG;IACf,SAAS,EAAE;QACT,IAAI,EAAE,YAAY,CAAC;QACnB,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;KACrB,CAAC;CACH,CAAC;AAiDF;;GAEG;AACH,wBAAsB,gBAAgB,CACpC,SAAS,GAAE,OAAO,CAAC,cAAc,CAAM,GACtC,OAAO,CAAC;IACT,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,CAAC;IACxB,MAAM,EAAE,UAAU,CAAC,OAAO,YAAY,CAAC,CAAC;IACxC,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B,CAAC,CAqDD;AAED;;GAEG;AACH,wBAAsB,iBAAiB,CAAC,CAAC,GAAG,OAAO,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAEnF;AAED;;GAEG;AACH,eAAO,MAAM,SAAS,EAAE,KAoCvB,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,aAAa,EAAE,KAS3B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,WAAW,EAAE,KASzB,CAAC;AAEF;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE;IAClE,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,WAwBA;AAED;;GAEG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,IAAI,CAAC,SAAS,CAAC,EACvB,OAAO,EAAE;IACP,MAAM,EAAE,MAAM,CAAC;IACf,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,KAAK,CAAC,EAAE,KAAK,CAAC;CACf,qBAYF"}
|
|
@@ -28,7 +28,7 @@ export const testStaffActor = {
|
|
|
28
28
|
role: "staff",
|
|
29
29
|
permissions: [
|
|
30
30
|
"catalog:read", "catalog:create", "catalog:update",
|
|
31
|
-
"inventory:adjust", "orders:read", "orders:create", "orders:update",
|
|
31
|
+
"inventory:adjust", "orders:read", "orders:create", "orders:update", "orders:manage",
|
|
32
32
|
],
|
|
33
33
|
};
|
|
34
34
|
/** Customer with minimal read/write-own permissions. */
|
package/dist/testing.d.ts
CHANGED
|
@@ -11,5 +11,6 @@ export { createRepositoryTestHarness } from "./test-utils/create-repository-test
|
|
|
11
11
|
export { createPluginTestApp, type PluginTestApp, type TestAppEnv } from "./test-utils/create-plugin-test-app.js";
|
|
12
12
|
export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
|
|
13
13
|
export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
|
|
14
|
+
export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
|
|
14
15
|
export type { Actor } from "./auth/types.js";
|
|
15
16
|
//# sourceMappingURL=testing.d.ts.map
|
package/dist/testing.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,WAAW,EACX,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;
|
|
1
|
+
{"version":3,"file":"testing.d.ts","sourceRoot":"","sources":["../src/testing.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,EAAE,gBAAgB,EAAE,MAAM,oCAAoC,CAAC;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,4CAA4C,CAAC;AACrF,OAAO,EAAE,2BAA2B,EAAE,MAAM,gDAAgD,CAAC;AAC7F,OAAO,EAAE,mBAAmB,EAAE,KAAK,aAAa,EAAE,KAAK,UAAU,EAAE,MAAM,wCAAwC,CAAC;AAClH,OAAO,EACL,WAAW,EACX,cAAc,EAAE,cAAc,EAAE,iBAAiB,EAAE,eAAe,EAClE,WAAW,GACZ,MAAM,6BAA6B,CAAC;AACrC,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAE,MAAM,oCAAoC,CAAC;AAG1E,YAAY,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC"}
|
package/dist/testing.js
CHANGED
|
@@ -11,3 +11,4 @@ export { createRepositoryTestHarness } from "./test-utils/create-repository-test
|
|
|
11
11
|
export { createPluginTestApp } from "./test-utils/create-plugin-test-app.js";
|
|
12
12
|
export { TEST_ORG_ID, testAdminActor, testStaffActor, testCustomerActor, testNoPermActor, jsonHeaders, } from "./test-utils/test-actors.js";
|
|
13
13
|
export { beforeHook, afterHook } from "./test-utils/typed-hooks.js";
|
|
14
|
+
export { markOrderPaidForTest } from "./test-utils/order-test-helpers.js";
|
package/package.json
CHANGED
package/src/auth/middleware.ts
CHANGED
|
@@ -43,10 +43,10 @@ export function authMiddleware(
|
|
|
43
43
|
// Resolve the default org from config, falling back to deprecated constant
|
|
44
44
|
const defaultOrgId = config.auth?.defaultOrganizationId ?? DEFAULT_ORG_ID;
|
|
45
45
|
|
|
46
|
-
// Test-only actor injection: NODE_ENV === "test"
|
|
47
|
-
//
|
|
48
|
-
//
|
|
49
|
-
if (process.env.NODE_ENV === "test") {
|
|
46
|
+
// Test-only actor injection: requires NODE_ENV === "test" AND an explicit
|
|
47
|
+
// config opt-in so staging/preview deployments left as NODE_ENV=test do not
|
|
48
|
+
// silently become a full auth bypass.
|
|
49
|
+
if (process.env.NODE_ENV === "test" && config.auth?.allowTestActor) {
|
|
50
50
|
const testActorHeader = c.req.header("x-test-actor");
|
|
51
51
|
if (testActorHeader) {
|
|
52
52
|
try {
|
|
@@ -172,10 +172,29 @@ export function authMiddleware(
|
|
|
172
172
|
if (result?.valid && result.key) {
|
|
173
173
|
const apiKey = result.key as Record<string, unknown>;
|
|
174
174
|
|
|
175
|
-
// v1.5+ renamed userId → referenceId on the apikey table.
|
|
176
|
-
const userId = (apiKey.referenceId ?? "") as string;
|
|
177
175
|
const name = (apiKey.name ?? "API Key") as string;
|
|
178
|
-
|
|
176
|
+
// Read the org (and operator identity) from key metadata when present.
|
|
177
|
+
// POS shift keys carry { organizationId, operatorId } in metadata so the
|
|
178
|
+
// operator is scoped to their store WITHOUT any org membership/role
|
|
179
|
+
// (SEC-16 / R-01). Other keys fall back to the key's organizationId.
|
|
180
|
+
const rawMeta = apiKey.metadata;
|
|
181
|
+
const meta =
|
|
182
|
+
rawMeta && typeof rawMeta === "object"
|
|
183
|
+
? (rawMeta as Record<string, unknown>)
|
|
184
|
+
: typeof rawMeta === "string"
|
|
185
|
+
? (() => {
|
|
186
|
+
try {
|
|
187
|
+
return JSON.parse(rawMeta) as Record<string, unknown>;
|
|
188
|
+
} catch {
|
|
189
|
+
return null;
|
|
190
|
+
}
|
|
191
|
+
})()
|
|
192
|
+
: null;
|
|
193
|
+
const metaOrg = typeof meta?.organizationId === "string" ? meta.organizationId : undefined;
|
|
194
|
+
const orgId = (metaOrg ?? apiKey.organizationId ?? defaultOrgId) as string;
|
|
195
|
+
const userId = ((typeof meta?.operatorId === "string" ? meta.operatorId : undefined)
|
|
196
|
+
?? apiKey.referenceId
|
|
197
|
+
?? "") as string;
|
|
179
198
|
|
|
180
199
|
// Better Auth stores permissions as Record<string, string[]>
|
|
181
200
|
// (e.g. {"catalog":["read","create"]}). Flatten to the
|
package/src/auth/setup.ts
CHANGED
|
@@ -7,13 +7,13 @@ import type { CommerceConfig } from "../config/types.js";
|
|
|
7
7
|
import type { DatabaseAdapter } from "../kernel/database/adapter.js";
|
|
8
8
|
import * as authSchema from "./auth-schema.js";
|
|
9
9
|
|
|
10
|
-
type BetterAuthDbProvider = "pg"
|
|
10
|
+
type BetterAuthDbProvider = "pg";
|
|
11
11
|
|
|
12
12
|
function resolveAuthDbProvider(provider: string): BetterAuthDbProvider {
|
|
13
13
|
if (provider === "postgres" || provider === "postgresql" || provider === "pg") return "pg";
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
14
|
+
throw new Error(
|
|
15
|
+
`Unsupported auth database provider "${provider}". Only PostgreSQL is supported.`,
|
|
16
|
+
);
|
|
17
17
|
}
|
|
18
18
|
|
|
19
19
|
interface AuthEmailPayload {
|
|
@@ -91,6 +91,12 @@ export function createAuth(
|
|
|
91
91
|
}
|
|
92
92
|
: {}),
|
|
93
93
|
...(scope.keyExpiration ? { keyExpiration: scope.keyExpiration } : {}),
|
|
94
|
+
...("references" in scope && scope.references
|
|
95
|
+
? { references: scope.references as "user" | "organization" }
|
|
96
|
+
: {}),
|
|
97
|
+
...(scope.enableMetadata || scope.references === "organization"
|
|
98
|
+
? { enableMetadata: true }
|
|
99
|
+
: {}),
|
|
94
100
|
}));
|
|
95
101
|
plugins.push(apiKey(apiKeyConfigs));
|
|
96
102
|
} else if (config.auth?.apiKeys?.enabled) {
|
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",
|
|
@@ -27,7 +27,9 @@ export const defaultConfig: Partial<CommerceConfig> = {
|
|
|
27
27
|
"inventory:read",
|
|
28
28
|
"inventory:adjust",
|
|
29
29
|
"orders:read",
|
|
30
|
+
"orders:create",
|
|
30
31
|
"orders:update",
|
|
32
|
+
"orders:manage",
|
|
31
33
|
"cart:create",
|
|
32
34
|
"cart:update",
|
|
33
35
|
"cart:manage",
|
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[];
|
|
@@ -113,6 +116,10 @@ export interface ApiKeyScopeDefinition {
|
|
|
113
116
|
minExpiresIn?: number;
|
|
114
117
|
maxExpiresIn?: number;
|
|
115
118
|
};
|
|
119
|
+
/** Better Auth ownership model — POS shift keys bind to an organization. */
|
|
120
|
+
references?: "user" | "organization";
|
|
121
|
+
/** Allow metadata on keys minted under this scope (e.g. operatorId on POS shift keys). */
|
|
122
|
+
enableMetadata?: boolean;
|
|
116
123
|
}
|
|
117
124
|
|
|
118
125
|
export interface AuthConfig {
|
|
@@ -214,6 +221,11 @@ export interface AuthConfig {
|
|
|
214
221
|
* Appended to the core plugin list (organization, bearer, jwt, etc.).
|
|
215
222
|
*/
|
|
216
223
|
extraAuthPlugins?: unknown[];
|
|
224
|
+
/**
|
|
225
|
+
* When true (and NODE_ENV === "test"), the `x-test-actor` header may inject
|
|
226
|
+
* a trusted actor for integration tests. Default false.
|
|
227
|
+
*/
|
|
228
|
+
allowTestActor?: boolean;
|
|
217
229
|
}
|
|
218
230
|
|
|
219
231
|
export interface CartConfig {
|
|
@@ -344,8 +356,9 @@ export interface CommerceConfig {
|
|
|
344
356
|
analytics?: AnalyticsConfig;
|
|
345
357
|
search?: SearchConfig;
|
|
346
358
|
jobs?: {
|
|
347
|
-
adapter?:
|
|
359
|
+
adapter?: ExecutionEngine;
|
|
348
360
|
tasks?: TaskDefinition[];
|
|
361
|
+
processingOrder?: JobProcessingOrder;
|
|
349
362
|
autorun?: {
|
|
350
363
|
enabled: boolean;
|
|
351
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" },
|
|
@@ -13,14 +13,14 @@ interface InventoryServiceLike {
|
|
|
13
13
|
quantity: number;
|
|
14
14
|
orderId: string;
|
|
15
15
|
performedBy: string;
|
|
16
|
-
}): Promise<{ ok: boolean; error?: { message: string } }>;
|
|
16
|
+
}, actor?: unknown): Promise<{ ok: boolean; error?: { message: string } }>;
|
|
17
17
|
release(input: {
|
|
18
18
|
entityId: string;
|
|
19
19
|
variantId?: string;
|
|
20
20
|
quantity: number;
|
|
21
21
|
orderId: string;
|
|
22
22
|
performedBy: string;
|
|
23
|
-
}): Promise<unknown>;
|
|
23
|
+
}, actor?: unknown): Promise<unknown>;
|
|
24
24
|
}
|
|
25
25
|
|
|
26
26
|
interface PaymentsServiceLike {
|
|
@@ -80,13 +80,16 @@ export const reserveInventoryStep: Step<
|
|
|
80
80
|
const performedBy = ctx.hook.actor?.userId ?? "system";
|
|
81
81
|
|
|
82
82
|
for (const item of data.lineItems) {
|
|
83
|
-
const result = await inventory.reserve(
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
83
|
+
const result = await inventory.reserve(
|
|
84
|
+
{
|
|
85
|
+
entityId: item.entityId,
|
|
86
|
+
...(item.variantId != null ? { variantId: item.variantId } : {}),
|
|
87
|
+
quantity: item.quantity,
|
|
88
|
+
orderId: data.checkoutId,
|
|
89
|
+
performedBy,
|
|
90
|
+
},
|
|
91
|
+
ctx.hook.actor,
|
|
92
|
+
);
|
|
90
93
|
|
|
91
94
|
if (!result.ok) {
|
|
92
95
|
return Err(
|
|
@@ -112,13 +115,16 @@ export const reserveInventoryStep: Step<
|
|
|
112
115
|
const performedBy = ctx.hook.actor?.userId ?? "system";
|
|
113
116
|
|
|
114
117
|
for (const r of reservations) {
|
|
115
|
-
await inventory.release(
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
118
|
+
await inventory.release(
|
|
119
|
+
{
|
|
120
|
+
entityId: r.entityId,
|
|
121
|
+
...(r.variantId != null ? { variantId: r.variantId } : {}),
|
|
122
|
+
quantity: r.quantity,
|
|
123
|
+
orderId: r.orderId,
|
|
124
|
+
performedBy,
|
|
125
|
+
},
|
|
126
|
+
ctx.hook.actor,
|
|
127
|
+
);
|
|
122
128
|
}
|
|
123
129
|
},
|
|
124
130
|
};
|
package/src/hooks/checkout.ts
CHANGED
|
@@ -566,16 +566,19 @@ export const reserveInventory: AfterHook<OrderResult> = async ({ result, context
|
|
|
566
566
|
quantity: number;
|
|
567
567
|
orderId: string;
|
|
568
568
|
performedBy: string;
|
|
569
|
-
}): Promise<unknown>;
|
|
569
|
+
}, actor?: unknown): Promise<unknown>;
|
|
570
570
|
};
|
|
571
571
|
for (const lineItem of result.lineItems ?? []) {
|
|
572
|
-
await inventory.reserve(
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
572
|
+
await inventory.reserve(
|
|
573
|
+
{
|
|
574
|
+
entityId: lineItem.entityId,
|
|
575
|
+
...(lineItem.variantId != null ? { variantId: lineItem.variantId } : {}),
|
|
576
|
+
quantity: lineItem.quantity,
|
|
577
|
+
orderId: result.id,
|
|
578
|
+
performedBy: context.actor?.userId ?? "system",
|
|
579
|
+
},
|
|
580
|
+
context.actor,
|
|
581
|
+
);
|
|
579
582
|
}
|
|
580
583
|
};
|
|
581
584
|
|
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 {
|