@porulle/core 0.63.0 → 0.65.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/adapters/email-render.d.ts +18 -0
- package/dist/adapters/email-render.d.ts.map +1 -0
- package/dist/adapters/email-render.js +37 -0
- package/dist/auth/actor.d.ts.map +1 -1
- package/dist/auth/actor.js +11 -0
- package/dist/auth/auth-failure.d.ts +0 -2
- package/dist/auth/auth-failure.d.ts.map +1 -1
- package/dist/auth/auth-failure.js +0 -4
- package/dist/auth/middleware.d.ts +0 -1
- package/dist/auth/middleware.d.ts.map +1 -1
- package/dist/auth/middleware.js +7 -6
- package/dist/auth/permissions.d.ts +2 -0
- package/dist/auth/permissions.d.ts.map +1 -1
- package/dist/auth/permissions.js +8 -6
- package/dist/auth/role-authority.d.ts +0 -1
- package/dist/auth/role-authority.d.ts.map +1 -1
- package/dist/auth/role-authority.js +1 -8
- package/dist/auth/setup.d.ts.map +1 -1
- package/dist/auth/setup.js +8 -0
- package/dist/auth/strict-org-resolution.d.ts +8 -1
- package/dist/auth/strict-org-resolution.d.ts.map +1 -1
- package/dist/auth/strict-org-resolution.js +9 -19
- package/dist/auth/system-actor.d.ts +3 -2
- package/dist/auth/system-actor.d.ts.map +1 -1
- package/dist/auth/system-actor.js +3 -3
- package/dist/config/defaults.d.ts.map +1 -1
- package/dist/config/defaults.js +3 -20
- package/dist/config/define-config.d.ts +2 -2
- package/dist/config/define-config.d.ts.map +1 -1
- package/dist/config/define-config.js +3 -2
- package/dist/config/types.d.ts +13 -3
- package/dist/config/types.d.ts.map +1 -1
- package/dist/hooks/checkout.d.ts +2 -15
- package/dist/hooks/checkout.d.ts.map +1 -1
- package/dist/hooks/checkout.js +2 -51
- package/dist/index.d.ts +11 -19
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -12
- package/dist/interfaces/rest/router.js +3 -3
- package/dist/interfaces/rest/routes/admin/compensation-failures.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/compensation-failures.js +5 -5
- package/dist/interfaces/rest/routes/admin/entity-field-definitions.js +5 -5
- package/dist/interfaces/rest/routes/admin/staff.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/admin/staff.js +2 -3
- package/dist/interfaces/rest/routes/analytics.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/analytics.js +2 -2
- package/dist/interfaces/rest/routes/carts.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/carts.js +12 -12
- package/dist/interfaces/rest/routes/catalog.js +37 -37
- package/dist/interfaces/rest/routes/checkout.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/checkout.js +9 -10
- package/dist/interfaces/rest/routes/customers.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/customers.js +12 -12
- package/dist/interfaces/rest/routes/documents.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/documents.js +9 -9
- package/dist/interfaces/rest/routes/inventory.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/inventory.js +8 -8
- package/dist/interfaces/rest/routes/media.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/media.js +5 -5
- package/dist/interfaces/rest/routes/orders.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/orders.js +32 -32
- package/dist/interfaces/rest/routes/payments.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/payments.js +2 -2
- package/dist/interfaces/rest/routes/pricing.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/pricing.js +8 -8
- package/dist/interfaces/rest/routes/promotions.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/promotions.js +7 -7
- package/dist/interfaces/rest/routes/search.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/search.js +3 -3
- package/dist/interfaces/rest/routes/settings.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/settings.js +4 -4
- package/dist/interfaces/rest/routes/shipping.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/shipping.js +9 -9
- package/dist/interfaces/rest/routes/tax.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/tax.js +9 -9
- package/dist/interfaces/rest/routes/webhooks.d.ts.map +1 -1
- package/dist/interfaces/rest/routes/webhooks.js +4 -4
- package/dist/interfaces/rest/utils.d.ts +1 -1
- package/dist/interfaces/rest/utils.d.ts.map +1 -1
- package/dist/interfaces/rest/utils.js +4 -13
- package/dist/jobs.d.ts +1 -0
- package/dist/jobs.d.ts.map +1 -1
- package/dist/jobs.js +1 -0
- package/dist/kernel/database/adapter.d.ts +9 -0
- package/dist/kernel/database/adapter.d.ts.map +1 -1
- package/dist/kernel/database/adapter.js +1 -1
- package/dist/kernel/database/migrate.d.ts +0 -4
- package/dist/kernel/database/migrate.d.ts.map +1 -1
- package/dist/kernel/database/migrate.js +2 -14
- package/dist/kernel/database/pglite-transaction.d.ts +28 -0
- package/dist/kernel/database/pglite-transaction.d.ts.map +1 -0
- package/dist/kernel/database/pglite-transaction.js +52 -0
- package/dist/kernel/database/tx-context.d.ts +0 -1
- package/dist/kernel/database/tx-context.d.ts.map +1 -1
- package/dist/kernel/database/tx-context.js +2 -14
- package/dist/kernel/database/unique-violation.d.ts +3 -0
- package/dist/kernel/database/unique-violation.d.ts.map +1 -0
- package/dist/kernel/database/unique-violation.js +9 -0
- package/dist/kernel/error-mapper.d.ts.map +1 -1
- package/dist/kernel/error-mapper.js +1 -0
- 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/hooks/create-context.d.ts +18 -9
- package/dist/kernel/hooks/create-context.d.ts.map +1 -1
- package/dist/kernel/hooks/create-context.js +24 -3
- package/dist/kernel/hooks/registry.d.ts +0 -19
- package/dist/kernel/hooks/registry.d.ts.map +1 -1
- package/dist/kernel/hooks/registry.js +0 -32
- package/dist/kernel/jobs/drizzle-adapter.d.ts.map +1 -1
- package/dist/kernel/jobs/drizzle-adapter.js +3 -10
- package/dist/kernel/jobs/prepare-enqueue.d.ts +20 -0
- package/dist/kernel/jobs/prepare-enqueue.d.ts.map +1 -0
- package/dist/kernel/jobs/prepare-enqueue.js +24 -0
- package/dist/kernel/jobs/types.d.ts +0 -4
- package/dist/kernel/jobs/types.d.ts.map +1 -1
- package/dist/kernel/jobs/types.js +0 -4
- package/dist/kernel/local-api.d.ts +0 -33
- package/dist/kernel/local-api.d.ts.map +1 -1
- package/dist/kernel/local-api.js +0 -36
- package/dist/kernel/plugin/manifest.d.ts +3 -5
- package/dist/kernel/plugin/manifest.d.ts.map +1 -1
- package/dist/modules/analytics/service.d.ts +0 -6
- package/dist/modules/analytics/service.d.ts.map +1 -1
- package/dist/modules/analytics/service.js +0 -32
- package/dist/modules/cart/service.d.ts.map +1 -1
- package/dist/modules/cart/service.js +5 -17
- package/dist/modules/catalog/entity-service.d.ts.map +1 -1
- package/dist/modules/catalog/entity-service.js +9 -17
- package/dist/modules/catalog/import-service.d.ts.map +1 -1
- package/dist/modules/catalog/import-service.js +4 -13
- package/dist/modules/catalog/service.d.ts +1 -81
- package/dist/modules/catalog/service.d.ts.map +1 -1
- package/dist/modules/catalog/service.js +1 -8
- package/dist/modules/customers/service.d.ts.map +1 -1
- package/dist/modules/customers/service.js +5 -17
- package/dist/modules/documents/render.d.ts +0 -3
- package/dist/modules/documents/render.d.ts.map +1 -1
- package/dist/modules/documents/render.js +2 -17
- package/dist/modules/fulfillment/service.d.ts.map +1 -1
- package/dist/modules/fulfillment/service.js +8 -26
- package/dist/modules/inventory/service.d.ts.map +1 -1
- package/dist/modules/inventory/service.js +3 -20
- package/dist/modules/media/service.d.ts.map +1 -1
- package/dist/modules/media/service.js +2 -10
- package/dist/modules/orders/quote.d.ts.map +1 -1
- package/dist/modules/orders/quote.js +1 -2
- package/dist/modules/orders/service.d.ts.map +1 -1
- package/dist/modules/orders/service.js +4 -17
- package/dist/modules/pricing/service.d.ts.map +1 -1
- package/dist/modules/pricing/service.js +7 -18
- package/dist/modules/promotions/service.d.ts.map +1 -1
- package/dist/modules/promotions/service.js +4 -16
- package/dist/modules/tax/service.d.ts +1 -3
- package/dist/modules/tax/service.d.ts.map +1 -1
- package/dist/modules/tax/service.js +16 -52
- package/dist/modules/webhooks/hook.d.ts.map +1 -1
- package/dist/modules/webhooks/hook.js +3 -2
- package/dist/modules/webhooks/service.d.ts.map +1 -1
- package/dist/modules/webhooks/service.js +1 -50
- package/dist/runtime/commerce.d.ts.map +1 -1
- package/dist/runtime/commerce.js +4 -11
- package/dist/runtime/kernel-modules.d.ts +38 -1799
- package/dist/runtime/kernel-modules.d.ts.map +1 -1
- package/dist/runtime/kernel-modules.js +160 -66
- package/dist/runtime/kernel-types.d.ts +3 -15
- package/dist/runtime/kernel-types.d.ts.map +1 -1
- package/dist/runtime/kernel-types.js +0 -10
- package/dist/runtime/kernel.d.ts +2 -3
- package/dist/runtime/kernel.d.ts.map +1 -1
- package/dist/runtime/kernel.js +10 -51
- package/dist/runtime/server.d.ts +1 -1
- package/dist/runtime/server.d.ts.map +1 -1
- package/dist/test-utils/create-pglite-adapter.d.ts.map +1 -1
- package/dist/test-utils/create-pglite-adapter.js +5 -62
- package/dist/test-utils/create-plugin-test-app.d.ts.map +1 -1
- package/dist/test-utils/create-plugin-test-app.js +13 -32
- package/dist/test-utils/rest-api-test-utils.d.ts +0 -12
- package/dist/test-utils/rest-api-test-utils.d.ts.map +1 -1
- package/dist/test-utils/rest-api-test-utils.js +3 -70
- package/dist/test-utils/test-actors.d.ts +9 -0
- package/dist/test-utils/test-actors.d.ts.map +1 -1
- package/dist/test-utils/test-actors.js +62 -0
- package/dist/testing.d.ts +1 -4
- package/dist/testing.d.ts.map +1 -1
- package/dist/testing.js +1 -4
- package/dist/utils/escape-html.d.ts +3 -0
- package/dist/utils/escape-html.d.ts.map +1 -0
- package/dist/utils/escape-html.js +9 -0
- package/dist/utils/id.d.ts +0 -1
- package/dist/utils/id.d.ts.map +1 -1
- package/dist/utils/id.js +0 -3
- package/dist/utils/logger.d.ts +1 -1
- package/dist/utils/logger.d.ts.map +1 -1
- package/dist/utils/logger.js +1 -1
- package/dist/utils/money.d.ts +13 -0
- package/dist/utils/money.d.ts.map +1 -0
- package/dist/utils/money.js +58 -0
- package/package.json +5 -6
- package/src/adapters/email-render.ts +63 -0
- package/src/auth/actor.ts +14 -0
- package/src/auth/auth-failure.ts +0 -5
- package/src/auth/middleware.ts +7 -6
- package/src/auth/permissions.ts +12 -6
- package/src/auth/role-authority.ts +1 -10
- package/src/auth/setup.ts +11 -0
- package/src/auth/strict-org-resolution.ts +9 -16
- package/src/auth/system-actor.ts +3 -3
- package/src/config/defaults.ts +3 -20
- package/src/config/define-config.ts +5 -4
- package/src/config/types.ts +13 -2
- package/src/hooks/checkout.ts +2 -86
- package/src/index.ts +9 -36
- package/src/interfaces/rest/router.ts +3 -3
- package/src/interfaces/rest/routes/admin/compensation-failures.ts +5 -5
- package/src/interfaces/rest/routes/admin/entity-field-definitions.ts +5 -5
- package/src/interfaces/rest/routes/admin/staff.ts +2 -3
- package/src/interfaces/rest/routes/analytics.ts +2 -2
- package/src/interfaces/rest/routes/carts.ts +12 -12
- package/src/interfaces/rest/routes/catalog.ts +37 -37
- package/src/interfaces/rest/routes/checkout.ts +8 -10
- package/src/interfaces/rest/routes/customers.ts +12 -12
- package/src/interfaces/rest/routes/documents.ts +9 -9
- package/src/interfaces/rest/routes/inventory.ts +8 -8
- package/src/interfaces/rest/routes/media.ts +5 -5
- package/src/interfaces/rest/routes/orders.ts +32 -32
- package/src/interfaces/rest/routes/payments.ts +2 -2
- package/src/interfaces/rest/routes/pricing.ts +8 -8
- package/src/interfaces/rest/routes/promotions.ts +7 -7
- package/src/interfaces/rest/routes/search.ts +3 -3
- package/src/interfaces/rest/routes/settings.ts +4 -4
- package/src/interfaces/rest/routes/shipping.ts +9 -9
- package/src/interfaces/rest/routes/tax.ts +9 -9
- package/src/interfaces/rest/routes/webhooks.ts +4 -4
- package/src/interfaces/rest/utils.ts +4 -14
- package/src/jobs.ts +2 -1
- package/src/kernel/database/adapter.ts +1 -1
- package/src/kernel/database/migrate.ts +2 -17
- package/src/kernel/database/pglite-transaction.ts +61 -0
- package/src/kernel/database/tx-context.ts +2 -20
- package/src/kernel/database/unique-violation.ts +7 -0
- package/src/kernel/error-mapper.ts +1 -0
- package/src/kernel/errors.ts +18 -0
- package/src/kernel/hooks/create-context.ts +38 -8
- package/src/kernel/hooks/registry.ts +0 -37
- package/src/kernel/jobs/drizzle-adapter.ts +4 -15
- package/src/kernel/jobs/prepare-enqueue.ts +42 -0
- package/src/kernel/jobs/types.ts +0 -5
- package/src/kernel/local-api.ts +0 -44
- package/src/kernel/plugin/manifest.ts +3 -5
- package/src/modules/analytics/service.ts +0 -36
- package/src/modules/cart/service.ts +6 -29
- package/src/modules/catalog/entity-service.ts +9 -19
- package/src/modules/catalog/import-service.ts +4 -11
- package/src/modules/catalog/service.ts +2 -286
- package/src/modules/customers/service.ts +6 -27
- package/src/modules/documents/render.ts +2 -19
- package/src/modules/fulfillment/service.ts +8 -27
- package/src/modules/inventory/service.ts +3 -21
- package/src/modules/media/service.ts +2 -8
- package/src/modules/orders/quote.ts +1 -2
- package/src/modules/orders/service.ts +5 -30
- package/src/modules/pricing/service.ts +12 -30
- package/src/modules/promotions/service.ts +5 -28
- package/src/modules/tax/service.ts +20 -48
- package/src/modules/webhooks/hook.ts +3 -2
- package/src/modules/webhooks/service.ts +1 -42
- package/src/runtime/commerce.ts +4 -11
- package/src/runtime/kernel-modules.ts +191 -67
- package/src/runtime/kernel-types.ts +3 -26
- package/src/runtime/kernel.ts +11 -66
- package/src/runtime/server.ts +1 -3
- package/src/test-utils/create-pglite-adapter.ts +5 -67
- package/src/test-utils/create-plugin-test-app.ts +13 -52
- package/src/test-utils/rest-api-test-utils.ts +3 -70
- package/src/test-utils/test-actors.ts +66 -0
- package/src/testing.ts +1 -3
- package/src/utils/escape-html.ts +9 -0
- package/src/utils/id.ts +0 -4
- package/src/utils/logger.ts +1 -1
- package/src/utils/money.ts +62 -0
- package/dist/auth/access.d.ts +0 -101
- package/dist/auth/access.d.ts.map +0 -1
- package/dist/auth/access.js +0 -128
- package/dist/generated/plugin-manifest.d.ts +0 -51
- package/dist/generated/plugin-manifest.d.ts.map +0 -1
- package/dist/generated/plugin-manifest.js +0 -21
- package/dist/kernel/factory/repository-factory.d.ts +0 -71
- package/dist/kernel/factory/repository-factory.d.ts.map +0 -1
- package/dist/kernel/factory/repository-factory.js +0 -138
- package/dist/kernel/http-error.d.ts +0 -30
- package/dist/kernel/http-error.d.ts.map +0 -1
- package/dist/kernel/http-error.js +0 -35
- package/dist/kernel/jobs/builtin-job-tasks.d.ts +0 -3
- package/dist/kernel/jobs/builtin-job-tasks.d.ts.map +0 -1
- package/dist/kernel/jobs/builtin-job-tasks.js +0 -6
- package/dist/kernel/module/define.d.ts +0 -21
- package/dist/kernel/module/define.d.ts.map +0 -1
- package/dist/kernel/module/define.js +0 -3
- package/dist/kernel/module/index.d.ts +0 -4
- package/dist/kernel/module/index.d.ts.map +0 -1
- package/dist/kernel/module/index.js +0 -2
- package/dist/kernel/module/topo-sort.d.ts +0 -7
- package/dist/kernel/module/topo-sort.d.ts.map +0 -1
- package/dist/kernel/module/topo-sort.js +0 -89
- package/dist/kernel/query/executor.d.ts +0 -21
- package/dist/kernel/query/executor.d.ts.map +0 -1
- package/dist/kernel/query/executor.js +0 -128
- package/dist/kernel/query/registry.d.ts +0 -33
- package/dist/kernel/query/registry.d.ts.map +0 -1
- package/dist/kernel/query/registry.js +0 -20
- package/dist/kernel/service-registry.d.ts +0 -109
- package/dist/kernel/service-registry.d.ts.map +0 -1
- package/dist/kernel/service-registry.js +0 -26
- package/dist/modules/analytics/hooks.d.ts +0 -13
- package/dist/modules/analytics/hooks.d.ts.map +0 -1
- package/dist/modules/analytics/hooks.js +0 -12
- package/dist/modules/analytics/module.d.ts +0 -3
- package/dist/modules/analytics/module.d.ts.map +0 -1
- package/dist/modules/analytics/module.js +0 -24
- package/dist/modules/analytics/repository/index.d.ts +0 -5
- package/dist/modules/analytics/repository/index.d.ts.map +0 -1
- package/dist/modules/analytics/repository/index.js +0 -1
- package/dist/modules/audit/index.d.ts +0 -2
- package/dist/modules/audit/index.d.ts.map +0 -1
- package/dist/modules/audit/index.js +0 -1
- package/dist/modules/audit/module.d.ts +0 -180
- package/dist/modules/audit/module.d.ts.map +0 -1
- package/dist/modules/audit/module.js +0 -8
- package/dist/modules/cart/access.d.ts +0 -11
- package/dist/modules/cart/access.d.ts.map +0 -1
- package/dist/modules/cart/access.js +0 -18
- package/dist/modules/cart/module.d.ts +0 -14
- package/dist/modules/cart/module.d.ts.map +0 -1
- package/dist/modules/cart/module.js +0 -17
- package/dist/modules/catalog/module.d.ts +0 -26
- package/dist/modules/catalog/module.d.ts.map +0 -1
- package/dist/modules/catalog/module.js +0 -33
- package/dist/modules/customers/index.d.ts +0 -2
- package/dist/modules/customers/index.d.ts.map +0 -1
- package/dist/modules/customers/index.js +0 -1
- package/dist/modules/customers/module.d.ts +0 -563
- package/dist/modules/customers/module.d.ts.map +0 -1
- package/dist/modules/customers/module.js +0 -20
- package/dist/modules/documents/module.d.ts +0 -7
- package/dist/modules/documents/module.d.ts.map +0 -1
- package/dist/modules/documents/module.js +0 -13
- package/dist/modules/fulfillment/module.d.ts +0 -13
- package/dist/modules/fulfillment/module.d.ts.map +0 -1
- package/dist/modules/fulfillment/module.js +0 -23
- package/dist/modules/inventory/module.d.ts +0 -13
- package/dist/modules/inventory/module.d.ts.map +0 -1
- package/dist/modules/inventory/module.js +0 -20
- package/dist/modules/media/index.d.ts +0 -2
- package/dist/modules/media/index.d.ts.map +0 -1
- package/dist/modules/media/index.js +0 -1
- package/dist/modules/media/module.d.ts +0 -360
- package/dist/modules/media/module.d.ts.map +0 -1
- package/dist/modules/media/module.js +0 -24
- package/dist/modules/orders/module.d.ts +0 -25
- package/dist/modules/orders/module.d.ts.map +0 -1
- package/dist/modules/orders/module.js +0 -33
- package/dist/modules/organization/index.d.ts +0 -2
- package/dist/modules/organization/index.d.ts.map +0 -1
- package/dist/modules/organization/index.js +0 -1
- package/dist/modules/organization/module.d.ts +0 -205
- package/dist/modules/organization/module.d.ts.map +0 -1
- package/dist/modules/organization/module.js +0 -8
- package/dist/modules/payments/module.d.ts +0 -3
- package/dist/modules/payments/module.d.ts.map +0 -1
- package/dist/modules/payments/module.js +0 -7
- package/dist/modules/payments/repository/index.d.ts +0 -5
- package/dist/modules/payments/repository/index.d.ts.map +0 -1
- package/dist/modules/payments/repository/index.js +0 -1
- package/dist/modules/pricing/index.d.ts +0 -2
- package/dist/modules/pricing/index.d.ts.map +0 -1
- package/dist/modules/pricing/index.js +0 -1
- package/dist/modules/pricing/module.d.ts +0 -14
- package/dist/modules/pricing/module.d.ts.map +0 -1
- package/dist/modules/pricing/module.js +0 -17
- package/dist/modules/promotions/module.d.ts +0 -14
- package/dist/modules/promotions/module.d.ts.map +0 -1
- package/dist/modules/promotions/module.js +0 -19
- package/dist/modules/search/module.d.ts +0 -8
- package/dist/modules/search/module.d.ts.map +0 -1
- package/dist/modules/search/module.js +0 -22
- package/dist/modules/search/repository/index.d.ts +0 -5
- package/dist/modules/search/repository/index.d.ts.map +0 -1
- package/dist/modules/search/repository/index.js +0 -1
- package/dist/modules/settings/module.d.ts +0 -6
- package/dist/modules/settings/module.d.ts.map +0 -1
- package/dist/modules/settings/module.js +0 -12
- package/dist/modules/shipping/module.d.ts +0 -12
- package/dist/modules/shipping/module.d.ts.map +0 -1
- package/dist/modules/shipping/module.js +0 -14
- package/dist/modules/tax/module.d.ts +0 -7
- package/dist/modules/tax/module.d.ts.map +0 -1
- package/dist/modules/tax/module.js +0 -13
- package/dist/modules/webhooks/index.d.ts +0 -2
- package/dist/modules/webhooks/index.d.ts.map +0 -1
- package/dist/modules/webhooks/index.js +0 -1
- package/dist/modules/webhooks/module.d.ts +0 -403
- package/dist/modules/webhooks/module.d.ts.map +0 -1
- package/dist/modules/webhooks/module.js +0 -16
- package/dist/test-utils/create-repository-test-harness.d.ts +0 -8
- package/dist/test-utils/create-repository-test-harness.d.ts.map +0 -1
- package/dist/test-utils/create-repository-test-harness.js +0 -7
- package/dist/test-utils/create-test-plugin-context.d.ts +0 -38
- package/dist/test-utils/create-test-plugin-context.d.ts.map +0 -1
- package/dist/test-utils/create-test-plugin-context.js +0 -39
- package/dist/test-utils/typed-hooks.d.ts +0 -44
- package/dist/test-utils/typed-hooks.d.ts.map +0 -1
- package/dist/test-utils/typed-hooks.js +0 -36
- package/dist/types/commerce-types.d.ts +0 -34
- package/dist/types/commerce-types.d.ts.map +0 -1
- package/dist/types/commerce-types.js +0 -1
- package/src/auth/access.ts +0 -187
- package/src/generated/plugin-capabilities.d.ts +0 -21
- package/src/generated/plugin-manifest.ts +0 -24
- package/src/generated/plugin-repositories.d.ts +0 -21
- package/src/kernel/factory/repository-factory.ts +0 -244
- package/src/kernel/http-error.ts +0 -44
- package/src/kernel/jobs/builtin-job-tasks.ts +0 -17
- package/src/kernel/module/define.ts +0 -36
- package/src/kernel/module/index.ts +0 -3
- package/src/kernel/module/topo-sort.ts +0 -99
- package/src/kernel/query/executor.ts +0 -184
- package/src/kernel/query/registry.ts +0 -46
- package/src/kernel/service-registry.ts +0 -76
- package/src/modules/analytics/hooks.ts +0 -11
- package/src/modules/analytics/module.ts +0 -35
- package/src/modules/analytics/repository/index.ts +0 -5
- package/src/modules/audit/index.ts +0 -1
- package/src/modules/audit/module.ts +0 -11
- package/src/modules/cart/access.ts +0 -27
- package/src/modules/cart/module.ts +0 -32
- package/src/modules/catalog/module.ts +0 -80
- package/src/modules/customers/index.ts +0 -1
- package/src/modules/customers/module.ts +0 -29
- package/src/modules/documents/module.ts +0 -21
- package/src/modules/fulfillment/module.ts +0 -44
- package/src/modules/inventory/module.ts +0 -37
- package/src/modules/media/index.ts +0 -1
- package/src/modules/media/module.ts +0 -27
- package/src/modules/orders/module.ts +0 -67
- package/src/modules/organization/index.ts +0 -1
- package/src/modules/organization/module.ts +0 -11
- package/src/modules/payments/module.ts +0 -14
- package/src/modules/payments/repository/index.ts +0 -5
- package/src/modules/pricing/index.ts +0 -1
- package/src/modules/pricing/module.ts +0 -32
- package/src/modules/promotions/module.ts +0 -34
- package/src/modules/search/module.ts +0 -32
- package/src/modules/search/repository/index.ts +0 -5
- package/src/modules/settings/module.ts +0 -20
- package/src/modules/shipping/module.ts +0 -27
- package/src/modules/tax/module.ts +0 -21
- package/src/modules/webhooks/index.ts +0 -1
- package/src/modules/webhooks/module.ts +0 -24
- package/src/test-utils/create-repository-test-harness.ts +0 -16
- package/src/test-utils/create-test-plugin-context.ts +0 -66
- package/src/test-utils/typed-hooks.ts +0 -55
- package/src/types/commerce-types.ts +0 -34
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { OpenAPIHono } from "@hono/zod-openapi";
|
|
2
2
|
import type { Kernel } from "../../../runtime/kernel.js";
|
|
3
3
|
import { createWebhookEndpointRoute, listWebhookEndpointsRoute, deleteWebhookEndpointRoute } from "../schemas/webhooks.js";
|
|
4
|
-
import { type AppEnv,
|
|
4
|
+
import { type AppEnv, errorBody, mapErrorToStatus, requirePerm } from "../utils.js";
|
|
5
5
|
|
|
6
6
|
export function webhookRoutes(kernel: Kernel) {
|
|
7
7
|
const router = new OpenAPIHono<AppEnv>();
|
|
@@ -18,7 +18,7 @@ export function webhookRoutes(kernel: Kernel) {
|
|
|
18
18
|
const actor = c.get("actor");
|
|
19
19
|
const result = await kernel.services.webhooks.createEndpoint(body, actor);
|
|
20
20
|
if (!result.ok) {
|
|
21
|
-
return c.json(
|
|
21
|
+
return c.json(errorBody(result.error), mapErrorToStatus(result.error));
|
|
22
22
|
}
|
|
23
23
|
return c.json({ data: result.value }, 201);
|
|
24
24
|
});
|
|
@@ -27,7 +27,7 @@ export function webhookRoutes(kernel: Kernel) {
|
|
|
27
27
|
router.openapi(listWebhookEndpointsRoute, async (c) => {
|
|
28
28
|
const result = await kernel.services.webhooks.listEndpoints(c.get("actor"));
|
|
29
29
|
if (!result.ok) {
|
|
30
|
-
return c.json(
|
|
30
|
+
return c.json(errorBody(result.error), mapErrorToStatus(result.error));
|
|
31
31
|
}
|
|
32
32
|
const sanitized = result.value.map(({ secret: _secret, ...rest }) => rest);
|
|
33
33
|
return c.json({ data: sanitized });
|
|
@@ -40,7 +40,7 @@ export function webhookRoutes(kernel: Kernel) {
|
|
|
40
40
|
c.get("actor"),
|
|
41
41
|
);
|
|
42
42
|
if (!result.ok) {
|
|
43
|
-
return c.json(
|
|
43
|
+
return c.json(errorBody(result.error), mapErrorToStatus(result.error));
|
|
44
44
|
}
|
|
45
45
|
return c.json({ data: { deleted: true } });
|
|
46
46
|
});
|
|
@@ -5,6 +5,7 @@ import type { Actor } from "../../auth/types.js";
|
|
|
5
5
|
import {
|
|
6
6
|
AUTHENTICATION_REQUIRED_MESSAGE,
|
|
7
7
|
isUnauthenticatedActor,
|
|
8
|
+
hasPermissionFromList,
|
|
8
9
|
} from "../../auth/permissions.js";
|
|
9
10
|
|
|
10
11
|
export const ROUTE_PERMISSION_GUARD = Symbol("porulle.routePermissionGuard");
|
|
@@ -72,7 +73,7 @@ export function parseInclude(value?: string): Set<string> {
|
|
|
72
73
|
* Map an error to a safe client response. Internal errors are sanitized
|
|
73
74
|
* to prevent leaking SQL, schema, or stack trace details.
|
|
74
75
|
*/
|
|
75
|
-
export function
|
|
76
|
+
export function errorBody(error: unknown): { error: { code: string; message: string } } {
|
|
76
77
|
const ce = toCommerceError(error);
|
|
77
78
|
if (ce.code === "INTERNAL_ERROR") {
|
|
78
79
|
// Sanitize internal errors -- do not expose raw messages to clients
|
|
@@ -91,14 +92,7 @@ export { mapErrorToStatus };
|
|
|
91
92
|
export function requirePerm(permission: string) {
|
|
92
93
|
const middleware = async (c: PermissionContext, next: () => Promise<void>) => {
|
|
93
94
|
const actor = c.get("actor");
|
|
94
|
-
|
|
95
|
-
if (perms.includes(permission) || perms.includes("*:*")) {
|
|
96
|
-
await next();
|
|
97
|
-
return;
|
|
98
|
-
}
|
|
99
|
-
// Check resource-level wildcard (e.g., "catalog:*" matches "catalog:create")
|
|
100
|
-
const [resource] = permission.split(":");
|
|
101
|
-
if (resource && perms.includes(`${resource}:*`)) {
|
|
95
|
+
if (hasPermissionFromList(actor?.permissions ?? [], permission)) {
|
|
102
96
|
await next();
|
|
103
97
|
return;
|
|
104
98
|
}
|
|
@@ -114,11 +108,7 @@ export function requireAnyPerm(permissions: readonly string[]) {
|
|
|
114
108
|
const middleware = async (c: PermissionContext, next: () => Promise<void>) => {
|
|
115
109
|
const actor = c.get("actor");
|
|
116
110
|
const granted = actor?.permissions ?? [];
|
|
117
|
-
const allowed = permissions.some((permission) =>
|
|
118
|
-
granted.includes(permission) ||
|
|
119
|
-
granted.includes("*:*") ||
|
|
120
|
-
granted.includes(`${permission.split(":")[0]}:*`),
|
|
121
|
-
);
|
|
111
|
+
const allowed = permissions.some((permission) => hasPermissionFromList(granted, permission));
|
|
122
112
|
if (allowed) {
|
|
123
113
|
await next();
|
|
124
114
|
return;
|
package/src/jobs.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
// Leaf entry for execution engines that run outside Node (Cloudflare Workers):
|
|
2
|
-
// only the job types and the
|
|
2
|
+
// only the job types and the runtime helpers engines share, none of the server runtime.
|
|
3
3
|
export type {
|
|
4
4
|
JobInstanceStatus,
|
|
5
5
|
TaskContext,
|
|
@@ -10,6 +10,7 @@ export type {
|
|
|
10
10
|
} from "./kernel/jobs/types.js";
|
|
11
11
|
export { TaskNonRetryableError } from "./kernel/jobs/types.js";
|
|
12
12
|
export { createPassThroughTaskStep } from "./kernel/jobs/step.js";
|
|
13
|
+
export { prepareEnqueue, type PreparedEnqueue } from "./kernel/jobs/prepare-enqueue.js";
|
|
13
14
|
export type {
|
|
14
15
|
EnqueueOptions,
|
|
15
16
|
ExecutionEngine,
|
|
@@ -54,7 +54,7 @@ export function unwrapDb<T>(db: T): T {
|
|
|
54
54
|
* on the `{ rows }` drivers. We intercept only `execute`; every other method
|
|
55
55
|
* is bound to the real driver instance so its internals are untouched.
|
|
56
56
|
*/
|
|
57
|
-
function normalizeExecuteShape<T extends object>(db: T): T {
|
|
57
|
+
export function normalizeExecuteShape<T extends object>(db: T): T {
|
|
58
58
|
return new Proxy(db, {
|
|
59
59
|
get(target, prop, receiver) {
|
|
60
60
|
if (prop === RAW_DB) return target;
|
|
@@ -64,19 +64,6 @@ export function buildSchema(config?: CommerceConfig): Record<string, unknown> {
|
|
|
64
64
|
return merged;
|
|
65
65
|
}
|
|
66
66
|
|
|
67
|
-
/**
|
|
68
|
-
* Returns a list of all schema table names defined by the commerce engine.
|
|
69
|
-
*/
|
|
70
|
-
export function getTableNames(): string[] {
|
|
71
|
-
return Object.entries(schema)
|
|
72
|
-
.filter(
|
|
73
|
-
([_, value]) =>
|
|
74
|
-
value != null &&
|
|
75
|
-
typeof value === "object" &&
|
|
76
|
-
"getSQL" in (value as object),
|
|
77
|
-
)
|
|
78
|
-
.map(([key]) => key);
|
|
79
|
-
}
|
|
80
67
|
|
|
81
68
|
/**
|
|
82
69
|
* Returns the absolute filesystem path(s) of the combined schema module for
|
|
@@ -121,10 +108,8 @@ export async function pushSchema(
|
|
|
121
108
|
"pushSchema() requires `drizzle-kit` to be installed. Add it to your project: bun add -d drizzle-kit",
|
|
122
109
|
);
|
|
123
110
|
}
|
|
124
|
-
//
|
|
125
|
-
// tables are created too; without one, push core only (backward compatible).
|
|
126
|
-
const schemaToApply = config ? buildSchema(config) : getSchema();
|
|
111
|
+
// Core plus any plugin-declared tables in `config.customSchemas`.
|
|
127
112
|
// drizzle-kit needs the native driver result shape; unwrap a normalized db.
|
|
128
|
-
const { apply } = await drizzleKit.pushSchema(
|
|
113
|
+
const { apply } = await drizzleKit.pushSchema(buildSchema(config), unwrapDb(drizzleInstance));
|
|
129
114
|
await apply();
|
|
130
115
|
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { AsyncLocalStorage } from "node:async_hooks";
|
|
2
|
+
|
|
3
|
+
/** The one PGlite capability a transaction needs: run a statement on the connection. */
|
|
4
|
+
export interface PGliteExec {
|
|
5
|
+
exec(statement: string): Promise<unknown>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `DatabaseAdapter.transaction` for a PGlite instance.
|
|
10
|
+
*
|
|
11
|
+
* Drizzle's own `transaction()` can hang on PGlite, so this drives
|
|
12
|
+
* BEGIN/COMMIT/ROLLBACK directly and hands the body the same `db` handle.
|
|
13
|
+
*
|
|
14
|
+
* PGlite is a single connection, so two bodies awaiting concurrently would
|
|
15
|
+
* otherwise interleave their statements between one BEGIN and one COMMIT —
|
|
16
|
+
* the second BEGIN is a no-op Postgres only warns about — and share a snapshot,
|
|
17
|
+
* each other's row locks and each other's rollback. Bodies are queued instead,
|
|
18
|
+
* which is what a connection pool does to two transactions competing for the
|
|
19
|
+
* same rows.
|
|
20
|
+
*
|
|
21
|
+
* Only a call made from INSIDE a running body joins it (without savepoints that
|
|
22
|
+
* is the only sound reading of a nested call). "Inside" is decided by the async
|
|
23
|
+
* context the call runs in, never by whether some transaction happens to be
|
|
24
|
+
* open: an unrelated request that arrives mid-body queues behind it.
|
|
25
|
+
*/
|
|
26
|
+
export function createPGliteTransaction(pg: PGliteExec, db: unknown): {
|
|
27
|
+
transaction<T>(fn: (tx: unknown) => Promise<T>): Promise<T>;
|
|
28
|
+
/** Whether a transaction body is executing right now. */
|
|
29
|
+
inTransaction(): boolean;
|
|
30
|
+
} {
|
|
31
|
+
// Each transaction gets its own token; a call joins only when it runs inside
|
|
32
|
+
// the body of the transaction that is open right now (work a body started
|
|
33
|
+
// but did not await may outlive it, and must not join a closed transaction).
|
|
34
|
+
const body = new AsyncLocalStorage<object>();
|
|
35
|
+
let queue: Promise<unknown> = Promise.resolve();
|
|
36
|
+
let current: object | null = null;
|
|
37
|
+
|
|
38
|
+
async function transaction<T>(fn: (tx: unknown) => Promise<T>): Promise<T> {
|
|
39
|
+
const caller = body.getStore();
|
|
40
|
+
if (caller !== undefined && caller === current) return fn(db);
|
|
41
|
+
const run = queue.then(async () => {
|
|
42
|
+
await pg.exec("BEGIN");
|
|
43
|
+
const token = {};
|
|
44
|
+
current = token;
|
|
45
|
+
try {
|
|
46
|
+
const result = await body.run(token, () => fn(db));
|
|
47
|
+
await pg.exec("COMMIT");
|
|
48
|
+
return result;
|
|
49
|
+
} catch (error) {
|
|
50
|
+
await pg.exec("ROLLBACK");
|
|
51
|
+
throw error;
|
|
52
|
+
} finally {
|
|
53
|
+
current = null;
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
queue = run.catch(() => undefined);
|
|
57
|
+
return run;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return { transaction, inTransaction: () => current !== null };
|
|
61
|
+
}
|
|
@@ -43,29 +43,11 @@ export async function withTransaction<TDb, TTx, TResult>(
|
|
|
43
43
|
});
|
|
44
44
|
}
|
|
45
45
|
|
|
46
|
-
export function reuseOrCreateTxContext<TTx>(
|
|
47
|
-
tx: TTx,
|
|
48
|
-
options: WithTransactionOptions,
|
|
49
|
-
existing?: TxContext<TTx> | null,
|
|
50
|
-
): TxContext<TTx> {
|
|
51
|
-
if (existing) {
|
|
52
|
-
return existing;
|
|
53
|
-
}
|
|
54
|
-
return createTxContext(tx, options);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
function hookContextFromWriteContext(ctx?: CatalogWriteContext): Record<string, unknown> | undefined {
|
|
58
|
-
return ctx?.hookContext;
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
function isTransactionalWriteContext<TTx>(ctx: CatalogWriteContext<TTx>): ctx is TxContext<TTx> {
|
|
62
|
-
return "tx" in ctx && ctx.tx != null;
|
|
63
|
-
}
|
|
64
46
|
|
|
65
47
|
export function resolveWriteContextHookContext(ctx?: CatalogWriteContext): Record<string, unknown> | undefined {
|
|
66
|
-
return
|
|
48
|
+
return ctx?.hookContext;
|
|
67
49
|
}
|
|
68
50
|
|
|
69
51
|
export function isWriteContextTransactional<TTx>(ctx?: CatalogWriteContext<TTx>): ctx is TxContext<TTx> {
|
|
70
|
-
return ctx != null &&
|
|
52
|
+
return ctx != null && "tx" in ctx && ctx.tx != null;
|
|
71
53
|
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Whether a database error (or any error it wraps) is a Postgres unique violation (23505). */
|
|
2
|
+
export function isUniqueViolation(error: unknown): boolean {
|
|
3
|
+
if (error == null || typeof error !== "object") return false;
|
|
4
|
+
const value = error as { code?: unknown; cause?: unknown };
|
|
5
|
+
if (value.code === "23505") return true;
|
|
6
|
+
return isUniqueViolation(value.cause);
|
|
7
|
+
}
|
package/src/kernel/errors.ts
CHANGED
|
@@ -70,6 +70,24 @@ export class CommerceReauthRequiredError extends Error implements CommerceError
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
+
/**
|
|
74
|
+
* Raised for a signed-in member whose role is listed in
|
|
75
|
+
* `auth.twoFactor.requiredForRoles` but who has not enabled two-factor
|
|
76
|
+
* authentication. The client discriminates on `code === "TWO_FACTOR_REQUIRED"`
|
|
77
|
+
* to send the member to enrolment (`/api/auth/two-factor/enable`) rather than
|
|
78
|
+
* treating it as a plain refusal.
|
|
79
|
+
*/
|
|
80
|
+
export class CommerceTwoFactorRequiredError extends Error implements CommerceError {
|
|
81
|
+
code = "TWO_FACTOR_REQUIRED" as const;
|
|
82
|
+
constructor(
|
|
83
|
+
message: string,
|
|
84
|
+
public details?: unknown,
|
|
85
|
+
) {
|
|
86
|
+
super(message);
|
|
87
|
+
this.name = "CommerceTwoFactorRequiredError";
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
73
91
|
export class CommerceForbiddenError extends Error implements CommerceError {
|
|
74
92
|
code = "FORBIDDEN" as const;
|
|
75
93
|
constructor(
|
|
@@ -5,6 +5,7 @@ import type { JobsAdapter } from "../jobs/adapter.js";
|
|
|
5
5
|
import { NullJobsAdapter } from "../jobs/adapter.js";
|
|
6
6
|
import type { PluginDb } from "../database/plugin-types.js";
|
|
7
7
|
import type { HookContext, HookOrigin, Logger, ServiceContainer } from "./types.js";
|
|
8
|
+
import { createConsoleLogger } from "../../utils/logger.js";
|
|
8
9
|
|
|
9
10
|
export interface CreateHookContextArgs {
|
|
10
11
|
actor: Actor | null;
|
|
@@ -16,12 +17,7 @@ export interface CreateHookContextArgs {
|
|
|
16
17
|
origin?: HookOrigin;
|
|
17
18
|
jobs?: JobsAdapter;
|
|
18
19
|
db?: PluginDb;
|
|
19
|
-
/** Prefer this over {@link CreateHookContextArgs.kernel}. */
|
|
20
20
|
database?: { db: PluginDb };
|
|
21
|
-
/**
|
|
22
|
-
* @deprecated Pass {@link CreateHookContextArgs.database} or {@link CreateHookContextArgs.db} instead.
|
|
23
|
-
*/
|
|
24
|
-
kernel?: { database: { db: PluginDb } };
|
|
25
21
|
commerceConfig?: CommerceConfig | null;
|
|
26
22
|
}
|
|
27
23
|
|
|
@@ -32,11 +28,11 @@ const nullJobs = new NullJobsAdapter();
|
|
|
32
28
|
*/
|
|
33
29
|
export function createHookContext(args: CreateHookContextArgs): HookContext {
|
|
34
30
|
const db =
|
|
35
|
-
args.db ?? args.database?.db ??
|
|
31
|
+
args.db ?? args.database?.db ?? null;
|
|
36
32
|
|
|
37
33
|
if (db == null) {
|
|
38
34
|
throw new Error(
|
|
39
|
-
"createHookContext requires a database: pass `db
|
|
35
|
+
"createHookContext requires a database: pass `db` or `database: { db }`.",
|
|
40
36
|
);
|
|
41
37
|
}
|
|
42
38
|
|
|
@@ -48,8 +44,42 @@ export function createHookContext(args: CreateHookContextArgs): HookContext {
|
|
|
48
44
|
context: args.context ?? {},
|
|
49
45
|
requestId: args.requestId ?? randomUUID(),
|
|
50
46
|
origin: args.origin ?? "rest",
|
|
51
|
-
|
|
47
|
+
// The kernel installs its engine as `services.jobs` before any module is
|
|
48
|
+
// built, so a context that names no engine still enqueues for real. The
|
|
49
|
+
// null adapter is for a context with no kernel behind it at all.
|
|
50
|
+
jobs: args.jobs ?? (args.services.jobs as JobsAdapter | undefined) ?? nullJobs,
|
|
52
51
|
db,
|
|
53
52
|
...(args.commerceConfig !== undefined ? { commerceConfig: args.commerceConfig } : {}),
|
|
54
53
|
};
|
|
55
54
|
}
|
|
55
|
+
|
|
56
|
+
/** What a core module service already holds that its hook context is built from. */
|
|
57
|
+
export interface ModuleHookDeps {
|
|
58
|
+
services: ServiceContainer;
|
|
59
|
+
database: { db: unknown };
|
|
60
|
+
config: CommerceConfig;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* The hook context a core module hands its hooks. Every module builds it the
|
|
65
|
+
* same way — its name as `context.moduleName` (which webhook event names are
|
|
66
|
+
* derived from), a logger scoped to it, the kernel's services (and through them
|
|
67
|
+
* the jobs engine), the database and the config — so none can leave a field out.
|
|
68
|
+
*/
|
|
69
|
+
export function createModuleHookContext(
|
|
70
|
+
moduleName: string,
|
|
71
|
+
deps: ModuleHookDeps,
|
|
72
|
+
actor: Actor | null,
|
|
73
|
+
tx: unknown = null,
|
|
74
|
+
options: { logScope?: string; context?: Record<string, unknown> } = {},
|
|
75
|
+
): HookContext {
|
|
76
|
+
return createHookContext({
|
|
77
|
+
actor,
|
|
78
|
+
tx,
|
|
79
|
+
logger: createConsoleLogger(options.logScope ?? moduleName),
|
|
80
|
+
services: deps.services,
|
|
81
|
+
context: { moduleName, ...options.context },
|
|
82
|
+
database: { db: deps.database.db as PluginDb },
|
|
83
|
+
commerceConfig: deps.config,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
@@ -33,7 +33,6 @@ type HookEntry = {
|
|
|
33
33
|
export class HookRegistry {
|
|
34
34
|
private registry = new Map<string, HookEntry>();
|
|
35
35
|
private inTransactionHandlers = new WeakSet<HookHandler>();
|
|
36
|
-
private logger?: { error: (obj: Record<string, unknown>, msg: string) => void };
|
|
37
36
|
|
|
38
37
|
registerConfigHooks(hookName: string, handlers: HookHandler[]): void {
|
|
39
38
|
this.ensureEntry(hookName);
|
|
@@ -55,11 +54,6 @@ export class HookRegistry {
|
|
|
55
54
|
this.registry.get(hookName)!.prepended.push(handler);
|
|
56
55
|
}
|
|
57
56
|
|
|
58
|
-
prependInTransaction(hookName: string, handler: HookHandler): void {
|
|
59
|
-
this.inTransactionHandlers.add(handler);
|
|
60
|
-
this.prepend(hookName, handler);
|
|
61
|
-
}
|
|
62
|
-
|
|
63
57
|
runsInTransaction(handler: HookHandler): boolean {
|
|
64
58
|
return this.inTransactionHandlers.has(handler);
|
|
65
59
|
}
|
|
@@ -70,37 +64,6 @@ export class HookRegistry {
|
|
|
70
64
|
return [...entry.prepended, ...entry.configured, ...entry.appended];
|
|
71
65
|
}
|
|
72
66
|
|
|
73
|
-
/**
|
|
74
|
-
* Emit a plugin event to all registered listeners.
|
|
75
|
-
*
|
|
76
|
-
* Unlike the before/after hook pattern (which transforms data through
|
|
77
|
-
* a pipeline), emit is fire-and-forget notification. Errors in handlers
|
|
78
|
-
* are caught and logged but do not propagate to the emitter.
|
|
79
|
-
*
|
|
80
|
-
* Usage:
|
|
81
|
-
* kernel.hooks.emit("production.afterComplete", { orderId, quantity });
|
|
82
|
-
*
|
|
83
|
-
* Any plugin can listen:
|
|
84
|
-
* hooks: () => [{ key: "production.afterComplete", handler: async (payload) => { ... } }]
|
|
85
|
-
*/
|
|
86
|
-
setLogger(logger: { error: (obj: Record<string, unknown>, msg: string) => void }): void {
|
|
87
|
-
this.logger = logger;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
async emit(key: string, payload: unknown): Promise<void> {
|
|
91
|
-
const handlers = this.resolve(key);
|
|
92
|
-
for (const handler of handlers) {
|
|
93
|
-
try {
|
|
94
|
-
await (handler as (payload: unknown) => unknown)(payload);
|
|
95
|
-
} catch (err) {
|
|
96
|
-
this.logger?.error(
|
|
97
|
-
{ err, hookKey: key },
|
|
98
|
-
`Event handler failed for "${key}"`,
|
|
99
|
-
);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
67
|
private ensureEntry(hookName: string): void {
|
|
105
68
|
if (!this.registry.has(hookName)) {
|
|
106
69
|
this.registry.set(hookName, {
|
|
@@ -7,8 +7,9 @@ import type {
|
|
|
7
7
|
ExecutionEngineSetup,
|
|
8
8
|
RunJobsOptions,
|
|
9
9
|
} from "./adapter.js";
|
|
10
|
-
import {
|
|
10
|
+
import { CommerceNotFoundError } from "../errors.js";
|
|
11
11
|
import { commerceJobs } from "./schema.js";
|
|
12
|
+
import { prepareEnqueue } from "./prepare-enqueue.js";
|
|
12
13
|
import { runPendingJobs } from "./runner.js";
|
|
13
14
|
import {
|
|
14
15
|
getJobReapThresholdMs,
|
|
@@ -79,17 +80,8 @@ export class DrizzleJobsAdapter implements ExecutionEngine {
|
|
|
79
80
|
input: Record<string, unknown>,
|
|
80
81
|
options: EnqueueOptions,
|
|
81
82
|
): Promise<string> {
|
|
82
|
-
const organizationId =
|
|
83
|
-
|
|
84
|
-
throw new OrgResolutionError(
|
|
85
|
-
"Jobs enqueue requires a non-empty organizationId.",
|
|
86
|
-
);
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
const task = this.tasks.get(taskSlug);
|
|
90
|
-
const concurrencyKey =
|
|
91
|
-
options.concurrencyKey ?? task?.concurrency?.key(input);
|
|
92
|
-
const supersedes = options.supersedes ?? task?.concurrency?.supersedes;
|
|
83
|
+
const { organizationId, concurrencyKey, supersedes, maxAttempts } =
|
|
84
|
+
prepareEnqueue(this.tasks, taskSlug, input, options);
|
|
93
85
|
|
|
94
86
|
// If supersedes is set, delete existing pending jobs with the same concurrency key
|
|
95
87
|
if (concurrencyKey && supersedes) {
|
|
@@ -105,9 +97,6 @@ export class DrizzleJobsAdapter implements ExecutionEngine {
|
|
|
105
97
|
);
|
|
106
98
|
}
|
|
107
99
|
|
|
108
|
-
// Look up task definition for default retry config
|
|
109
|
-
const maxAttempts = options.maxAttempts ?? task?.retries?.attempts ?? 1;
|
|
110
|
-
|
|
111
100
|
const rows = await this.db
|
|
112
101
|
.insert(commerceJobs)
|
|
113
102
|
.values({
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { OrgResolutionError } from "../errors.js";
|
|
2
|
+
import type { EnqueueOptions } from "./adapter.js";
|
|
3
|
+
import type { TaskDefinition } from "./types.js";
|
|
4
|
+
|
|
5
|
+
export interface PreparedEnqueue {
|
|
6
|
+
task: TaskDefinition;
|
|
7
|
+
organizationId: string;
|
|
8
|
+
concurrencyKey: string | undefined;
|
|
9
|
+
/** At most one running job per concurrency key. */
|
|
10
|
+
exclusive: boolean;
|
|
11
|
+
/** A newer enqueue replaces a pending one with the same concurrency key. */
|
|
12
|
+
supersedes: boolean;
|
|
13
|
+
maxAttempts: number;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The validation and defaulting every execution engine applies before it hands
|
|
18
|
+
* a job to its backend: the task must be registered, the organization must be
|
|
19
|
+
* non-blank, and concurrency/retry settings come from the task unless the
|
|
20
|
+
* enqueue call overrides them.
|
|
21
|
+
*/
|
|
22
|
+
export function prepareEnqueue(
|
|
23
|
+
tasks: ReadonlyMap<string, TaskDefinition>,
|
|
24
|
+
taskSlug: string,
|
|
25
|
+
input: Record<string, unknown>,
|
|
26
|
+
options: EnqueueOptions,
|
|
27
|
+
): PreparedEnqueue {
|
|
28
|
+
const task = tasks.get(taskSlug);
|
|
29
|
+
if (!task) throw new Error(`Unknown task slug: ${taskSlug}`);
|
|
30
|
+
const organizationId = options.organizationId.trim();
|
|
31
|
+
if (!organizationId) {
|
|
32
|
+
throw new OrgResolutionError("Jobs enqueue requires a non-empty organizationId.");
|
|
33
|
+
}
|
|
34
|
+
return {
|
|
35
|
+
task,
|
|
36
|
+
organizationId,
|
|
37
|
+
concurrencyKey: options.concurrencyKey ?? task.concurrency?.key(input),
|
|
38
|
+
exclusive: Boolean(task.concurrency && task.concurrency.exclusive !== false),
|
|
39
|
+
supersedes: Boolean(options.supersedes ?? task.concurrency?.supersedes),
|
|
40
|
+
maxAttempts: options.maxAttempts ?? task.retries?.attempts ?? 1,
|
|
41
|
+
};
|
|
42
|
+
}
|
package/src/kernel/jobs/types.ts
CHANGED
|
@@ -1,11 +1,6 @@
|
|
|
1
1
|
import type { Logger, ServiceContainer } from "../hooks/types.js";
|
|
2
2
|
import type { DrizzleDatabase } from "../database/drizzle-db.js";
|
|
3
3
|
|
|
4
|
-
export const BUILTIN_JOB_TASK_SLUGS = {
|
|
5
|
-
webhookDeliver: "webhooks/deliver",
|
|
6
|
-
staleJobReaper: "jobs/reap-stale",
|
|
7
|
-
} as const;
|
|
8
|
-
|
|
9
4
|
export interface TaskContext {
|
|
10
5
|
logger: Logger;
|
|
11
6
|
db: DrizzleDatabase;
|
package/src/kernel/local-api.ts
CHANGED
|
@@ -142,47 +142,3 @@ export function createLocalAPI(
|
|
|
142
142
|
},
|
|
143
143
|
});
|
|
144
144
|
}
|
|
145
|
-
|
|
146
|
-
// ─── Legacy Class API (backward compat) ─────────────────────────────────────
|
|
147
|
-
|
|
148
|
-
/**
|
|
149
|
-
* @deprecated Use `createLocalAPI(kernel, { actor, tx })` instead.
|
|
150
|
-
* Kept for backward compatibility with existing hook code.
|
|
151
|
-
*/
|
|
152
|
-
export class LocalAPI {
|
|
153
|
-
private _proxy: CommerceLocalAPI;
|
|
154
|
-
|
|
155
|
-
constructor(
|
|
156
|
-
ctx: { actor: Actor | null; tx: unknown; requestId: string },
|
|
157
|
-
kernel: Kernel,
|
|
158
|
-
) {
|
|
159
|
-
this._proxy = createLocalAPI(kernel, {
|
|
160
|
-
actor: ctx.actor,
|
|
161
|
-
tx: ctx.tx,
|
|
162
|
-
requestId: ctx.requestId,
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
get orders() { return this._proxy.orders; }
|
|
167
|
-
get catalog() { return this._proxy.catalog; }
|
|
168
|
-
get cart() { return this._proxy.cart; }
|
|
169
|
-
get inventory() { return this._proxy.inventory; }
|
|
170
|
-
get customers() { return this._proxy.customers; }
|
|
171
|
-
get pricing() { return this._proxy.pricing; }
|
|
172
|
-
get promotions() { return this._proxy.promotions; }
|
|
173
|
-
get media() { return this._proxy.media; }
|
|
174
|
-
get shipping() { return this._proxy.shipping; }
|
|
175
|
-
get search() { return this._proxy.search; }
|
|
176
|
-
get webhooks() { return this._proxy.webhooks; }
|
|
177
|
-
get fulfillment() { return this._proxy.fulfillment; }
|
|
178
|
-
get payments() { return this._proxy.payments; }
|
|
179
|
-
get analytics() { return this._proxy.analytics; }
|
|
180
|
-
get tax() { return this._proxy.tax; }
|
|
181
|
-
get audit() { return this._proxy.audit; }
|
|
182
|
-
get organization() { return this._proxy.organization; }
|
|
183
|
-
|
|
184
|
-
/** Resolve a service by name from `kernel.services`. */
|
|
185
|
-
service(name: string) {
|
|
186
|
-
return (this._proxy as Record<string, unknown>)[name];
|
|
187
|
-
}
|
|
188
|
-
}
|
|
@@ -18,14 +18,12 @@ import type {
|
|
|
18
18
|
PluginPermission,
|
|
19
19
|
} from "../../config/types.js";
|
|
20
20
|
import type { TaskDefinition } from "../jobs/types.js";
|
|
21
|
+
import type { Logger } from "../hooks/types.js";
|
|
21
22
|
|
|
22
23
|
// ─── Plugin Logger ────────────────────────────────────────────────────
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
warn(message: string, data?: unknown): void;
|
|
27
|
-
error(message: string, data?: unknown): void;
|
|
28
|
-
}
|
|
25
|
+
/** The logger a plugin receives — the same shape every hook and job gets. */
|
|
26
|
+
export type PluginLogger = Logger;
|
|
29
27
|
|
|
30
28
|
// ─── Plugin Registration Types ────────────────────────────────────────
|
|
31
29
|
|
|
@@ -93,33 +93,6 @@ export class AnalyticsService {
|
|
|
93
93
|
return this.deps.adapter.query(params, scope);
|
|
94
94
|
}
|
|
95
95
|
|
|
96
|
-
async getDashboard(name: string, scope: AnalyticsScope): Promise<Result<AnalyticsQueryResult>> {
|
|
97
|
-
const normalized = name.trim().toLowerCase();
|
|
98
|
-
|
|
99
|
-
if (normalized === "revenue" || normalized === "revenue-overview") {
|
|
100
|
-
return this.query({
|
|
101
|
-
measures: ["Orders.revenue", "Orders.count"],
|
|
102
|
-
timeDimensions: [{
|
|
103
|
-
dimension: "Orders.placedAt",
|
|
104
|
-
granularity: "month",
|
|
105
|
-
dateRange: "this month",
|
|
106
|
-
}],
|
|
107
|
-
order: { "Orders.placedAt": "asc" },
|
|
108
|
-
}, scope);
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
if (normalized === "inventory" || normalized === "inventory-health") {
|
|
112
|
-
return this.query({
|
|
113
|
-
measures: ["Inventory.totalAvailable", "Inventory.lowStockCount"],
|
|
114
|
-
dimensions: ["Inventory.warehouseId"],
|
|
115
|
-
order: { "Inventory.totalAvailable": "desc" },
|
|
116
|
-
}, scope);
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
return Err(
|
|
120
|
-
new CommerceValidationError(`Unknown analytics dashboard: ${name}`),
|
|
121
|
-
);
|
|
122
|
-
}
|
|
123
96
|
|
|
124
97
|
/** The canned retail reports pack (issue #48). */
|
|
125
98
|
listReports(): Array<{ name: string; description: string }> {
|
|
@@ -161,15 +134,6 @@ export class AnalyticsService {
|
|
|
161
134
|
});
|
|
162
135
|
}
|
|
163
136
|
|
|
164
|
-
async meta(): Promise<Result<{ measures: string[]; dimensions: string[]; segments: string[] }>> {
|
|
165
|
-
const meta = await this.getMeta();
|
|
166
|
-
if (!meta.ok) return meta;
|
|
167
|
-
return Ok({
|
|
168
|
-
measures: meta.value.measures,
|
|
169
|
-
dimensions: meta.value.dimensions,
|
|
170
|
-
segments: meta.value.segments,
|
|
171
|
-
});
|
|
172
|
-
}
|
|
173
137
|
|
|
174
138
|
// ─── Private ─────────────────────────────────────────────────────────────
|
|
175
139
|
|