@porulle/core 0.13.0 → 0.15.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.
Files changed (45) hide show
  1. package/dist/auth/actor.d.ts +10 -0
  2. package/dist/auth/actor.d.ts.map +1 -0
  3. package/dist/auth/actor.js +91 -0
  4. package/dist/auth/middleware.d.ts +1 -1
  5. package/dist/auth/middleware.d.ts.map +1 -1
  6. package/dist/auth/middleware.js +5 -89
  7. package/dist/auth/setup.d.ts.map +1 -1
  8. package/dist/auth/setup.js +2 -1
  9. package/dist/config/types.d.ts +4 -2
  10. package/dist/config/types.d.ts.map +1 -1
  11. package/dist/index.d.ts +2 -1
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +1 -0
  14. package/dist/kernel/database/plugin-types.d.ts +11 -0
  15. package/dist/kernel/database/plugin-types.d.ts.map +1 -1
  16. package/dist/kernel/database/scoped-db.d.ts +12 -0
  17. package/dist/kernel/database/scoped-db.d.ts.map +1 -1
  18. package/dist/kernel/database/scoped-db.js +12 -0
  19. package/dist/kernel/plugin/manifest.d.ts +3 -0
  20. package/dist/kernel/plugin/manifest.d.ts.map +1 -1
  21. package/dist/kernel/plugin/manifest.js +35 -6
  22. package/dist/modules/search/adapter.d.ts +5 -0
  23. package/dist/modules/search/adapter.d.ts.map +1 -1
  24. package/dist/modules/search/module.d.ts.map +1 -1
  25. package/dist/modules/search/module.js +3 -1
  26. package/dist/runtime/kernel-types.d.ts +7 -0
  27. package/dist/runtime/kernel-types.d.ts.map +1 -1
  28. package/dist/runtime/kernel.d.ts +1 -0
  29. package/dist/runtime/kernel.d.ts.map +1 -1
  30. package/dist/runtime/server.d.ts.map +1 -1
  31. package/dist/runtime/server.js +33 -1
  32. package/package.json +3 -3
  33. package/src/auth/actor.ts +110 -0
  34. package/src/auth/middleware.ts +11 -99
  35. package/src/auth/setup.ts +2 -1
  36. package/src/config/types.ts +4 -2
  37. package/src/index.ts +6 -1
  38. package/src/kernel/database/plugin-types.ts +11 -0
  39. package/src/kernel/database/scoped-db.ts +12 -0
  40. package/src/kernel/plugin/manifest.ts +57 -12
  41. package/src/modules/search/adapter.ts +3 -0
  42. package/src/modules/search/module.ts +4 -1
  43. package/src/runtime/kernel-types.ts +9 -0
  44. package/src/runtime/kernel.ts +1 -0
  45. package/src/runtime/server.ts +39 -1
@@ -4,6 +4,7 @@ import type {
4
4
  } from "../config/types.js";
5
5
  import type { HookRegistry } from "../kernel/hooks/registry.js";
6
6
  import type { DatabaseAdapter } from "../kernel/database/adapter.js";
7
+ import type { PluginDb } from "../kernel/database/plugin-types.js";
7
8
  import { CatalogServiceImpl } from "../modules/catalog/service.js";
8
9
  import { InventoryService } from "../modules/inventory/service.js";
9
10
  import { MediaService } from "../modules/media/service.js";
@@ -65,6 +66,14 @@ export interface Kernel {
65
66
  logger: ReturnType<typeof createLogger>;
66
67
  }
67
68
 
69
+ export interface ConfigRouteDatabase extends DatabaseAdapter {
70
+ readonly scoped: PluginDb;
71
+ }
72
+
73
+ export type ConfigRouteKernel = Omit<Kernel, "database"> & {
74
+ database: ConfigRouteDatabase;
75
+ };
76
+
68
77
  export const KERNEL_REQUIRED_SERVICE_KEYS = [
69
78
  "catalog",
70
79
  "inventory",
@@ -27,6 +27,7 @@ import {
27
27
  } from "./kernel-types.js";
28
28
 
29
29
  export type { Kernel, WebhookDeliveryPayload };
30
+ export type { ConfigRouteKernel, ConfigRouteDatabase } from "./kernel-types.js";
30
31
  export {
31
32
  KERNEL_ALL_MODULES,
32
33
  kernelModuleInstantiationOrder,
@@ -11,6 +11,7 @@ import type { Actor } from "../auth/types.js";
11
11
  import type { AuthInstance } from "../auth/setup.js";
12
12
  import type { CommerceConfig } from "../config/types.js";
13
13
  import { authMiddleware } from "../auth/middleware.js";
14
+ import { resolveOrgIdForCommerce } from "../auth/org.js";
14
15
  import { organizationGuard } from "../auth/organization-guard.js";
15
16
  import type { DrizzleDatabase } from "../kernel/database/drizzle-db.js";
16
17
  import { CommerceCsrfError } from "../kernel/errors.js";
@@ -24,6 +25,9 @@ import { rewriteCommerceAliasRequest } from "./url-alias-rewrite.js";
24
25
  import { mapErrorToResponse } from "../kernel/error-mapper.js";
25
26
  import { assertRouteCoverage } from "../interfaces/rest/route-coverage.js";
26
27
  import { markRoutePermissionGuard } from "../interfaces/rest/utils.js";
28
+ import { isStrictOrgResolution } from "../auth/strict-org-resolution.js";
29
+ import { runWithPluginDatabaseScope } from "../kernel/database/plugin-db-context.js";
30
+ import { buildConfigRoutesKernel } from "../kernel/plugin/manifest.js";
27
31
 
28
32
  type ServerEnv = {
29
33
  Variables: {
@@ -260,10 +264,17 @@ export async function createServer(config: CommerceConfig) {
260
264
  const getClientIp = createClientIpResolver(config);
261
265
  const keyGenerator = getClientIp;
262
266
 
267
+ app.use("/api/auth/get-session", rateLimiter({
268
+ windowMs: 60 * 1000,
269
+ limit: config.rateLimits?.session ?? 120,
270
+ keyGenerator,
271
+ }));
272
+
263
273
  app.use("/api/auth/*", rateLimiter({
264
274
  windowMs: 60 * 1000,
265
275
  limit: config.rateLimits?.auth ?? 10,
266
276
  keyGenerator,
277
+ skip: (c) => c.req.path === "/api/auth/get-session",
267
278
  }));
268
279
 
269
280
  app.use("/api/auth/sign-in/email", async (c, next) => {
@@ -341,6 +352,16 @@ export async function createServer(config: CommerceConfig) {
341
352
  });
342
353
 
343
354
  app.use("*", authMiddleware(auth, config));
355
+ app.use("*", async (c, next) => {
356
+ let organizationId: string;
357
+ try {
358
+ organizationId = resolveOrgIdForCommerce(c.get("actor"), config);
359
+ } catch {
360
+ await next();
361
+ return;
362
+ }
363
+ await runWithPluginDatabaseScope(organizationId, next);
364
+ });
344
365
  app.use("*", async (c, next) => {
345
366
  c.set("auth", auth);
346
367
  await next();
@@ -360,7 +381,7 @@ export async function createServer(config: CommerceConfig) {
360
381
  app.route("/api/me", createCustomerPortalRoutes(kernel));
361
382
 
362
383
  if (config.routes) {
363
- config.routes(app, kernel, auth);
384
+ config.routes(app, buildConfigRoutesKernel(kernel), auth);
364
385
  }
365
386
 
366
387
  // OpenAPI spec — disabled in production unless explicitly enabled
@@ -500,6 +521,23 @@ export async function createServer(config: CommerceConfig) {
500
521
  }
501
522
  }
502
523
 
524
+ const defaultOrganizationId = config.auth?.defaultOrganizationId;
525
+ const hasDefaultOrganization =
526
+ typeof defaultOrganizationId === "string" && defaultOrganizationId.trim().length > 0;
527
+ if (
528
+ isStrictOrgResolution(config) &&
529
+ !hasDefaultOrganization &&
530
+ !config.auth?.storeResolver
531
+ ) {
532
+ throw new Error(
533
+ "Cannot resolve an organization for a request with no actor. Set " +
534
+ "auth.defaultOrganizationId for a single-tenant deployment, or " +
535
+ "auth.storeResolver for a multi-tenant one. To keep the previous " +
536
+ "permissive behaviour during a migration, set " +
537
+ "auth.strictOrgResolution: false (or STRICT_ORG_RESOLUTION=false).",
538
+ );
539
+ }
540
+
503
541
  assertRouteCoverage(app);
504
542
 
505
543
  const dispatchFetch = app.fetch.bind(app);