@open-mercato/core 0.6.7-develop.6795.1.8a3f27921c → 0.6.7-develop.6814.1.0627c7e9f1
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/.turbo/turbo-build.log +1 -1
- package/dist/generated/entities/customer_deal_person_link/index.js +2 -0
- package/dist/generated/entities/customer_deal_person_link/index.js.map +2 -2
- package/dist/generated/entities/customer_user_invitation/index.js +2 -0
- package/dist/generated/entities/customer_user_invitation/index.js.map +2 -2
- package/dist/generated/entity-fields-registry.js +2 -0
- package/dist/generated/entity-fields-registry.js.map +2 -2
- package/dist/modules/business_rules/api/openmercato-call-options/route.js +85 -0
- package/dist/modules/business_rules/api/openmercato-call-options/route.js.map +7 -0
- package/dist/modules/business_rules/api/rules/route.js +71 -4
- package/dist/modules/business_rules/api/rules/route.js.map +2 -2
- package/dist/modules/business_rules/components/ActionBuilder.js +47 -4
- package/dist/modules/business_rules/components/ActionBuilder.js.map +3 -3
- package/dist/modules/business_rules/components/ActionRow.js +106 -16
- package/dist/modules/business_rules/components/ActionRow.js.map +2 -2
- package/dist/modules/business_rules/components/utils/actionValidation.js +6 -0
- package/dist/modules/business_rules/components/utils/actionValidation.js.map +2 -2
- package/dist/modules/business_rules/lib/action-executor.js +148 -0
- package/dist/modules/business_rules/lib/action-executor.js.map +2 -2
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js +5 -0
- package/dist/modules/business_rules/lib/openmercato-call-options-types.js.map +7 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js +231 -0
- package/dist/modules/business_rules/lib/openmercato-call-options.js.map +7 -0
- package/dist/modules/business_rules/lib/rule-engine.js +5 -1
- package/dist/modules/business_rules/lib/rule-engine.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js +11 -1
- package/dist/modules/communication_channels/api/post/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js +11 -6
- package/dist/modules/communication_channels/api/post/webhooks/gmail/route.js.map +2 -2
- package/dist/modules/configs/lib/upgrade-actions.js +12 -0
- package/dist/modules/configs/lib/upgrade-actions.js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users/[id].js +10 -1
- package/dist/modules/customer_accounts/api/admin/users/[id].js.map +2 -2
- package/dist/modules/customer_accounts/api/admin/users-invite.js +61 -4
- package/dist/modules/customer_accounts/api/admin/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js +20 -2
- package/dist/modules/customer_accounts/api/portal/users-invite.js.map +2 -2
- package/dist/modules/customer_accounts/data/entities.js +3 -0
- package/dist/modules/customer_accounts/data/entities.js.map +2 -2
- package/dist/modules/customer_accounts/data/validators.js +1 -0
- package/dist/modules/customer_accounts/data/validators.js.map +2 -2
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js +26 -0
- package/dist/modules/customer_accounts/emails/CustomerInvitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js +29 -3
- package/dist/modules/customer_accounts/lib/customerEntityOwnership.js.map +2 -2
- package/dist/modules/customer_accounts/lib/customerUrl.js +19 -10
- package/dist/modules/customer_accounts/lib/customerUrl.js.map +2 -2
- package/dist/modules/customer_accounts/lib/invitationEmail.js +35 -0
- package/dist/modules/customer_accounts/lib/invitationEmail.js.map +7 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js +13 -0
- package/dist/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.js.map +7 -0
- package/dist/modules/customer_accounts/services/customerInvitationService.js +32 -2
- package/dist/modules/customer_accounts/services/customerInvitationService.js.map +2 -2
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js +47 -7
- package/dist/modules/customer_accounts/subscribers/autoLinkCrm.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js +2 -2
- package/dist/modules/customer_accounts/widgets/injection/account-status/widget.client.js.map +2 -2
- package/dist/modules/customer_accounts/widgets/injection-table.js +1 -1
- package/dist/modules/customer_accounts/widgets/injection-table.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js +4 -2
- package/dist/modules/customers/api/deals/[id]/people/route.js.map +2 -2
- package/dist/modules/customers/api/deals/[id]/route.js +7 -3
- package/dist/modules/customers/api/deals/[id]/route.js.map +2 -2
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js +11 -1
- package/dist/modules/customers/backend/customers/companies-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/deals/[id]/page.js +14 -8
- package/dist/modules/customers/backend/customers/deals/[id]/page.js.map +2 -2
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js +21 -6
- package/dist/modules/customers/backend/customers/people-v2/[id]/page.js.map +2 -2
- package/dist/modules/customers/commands/deals.js +48 -10
- package/dist/modules/customers/commands/deals.js.map +2 -2
- package/dist/modules/customers/commands/people.js +2 -0
- package/dist/modules/customers/commands/people.js.map +2 -2
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js +26 -6
- package/dist/modules/customers/components/detail/CompanyDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/DealDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/DealDetailTabs.js.map +2 -2
- package/dist/modules/customers/components/detail/PersonDetailTabs.js +30 -8
- package/dist/modules/customers/components/detail/PersonDetailTabs.js.map +2 -2
- package/dist/modules/customers/data/entities.js +8 -0
- package/dist/modules/customers/data/entities.js.map +2 -2
- package/dist/modules/customers/data/validators.js +2 -1
- package/dist/modules/customers/data/validators.js.map +2 -2
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js +15 -0
- package/dist/modules/customers/migrations/Migration20260723210000_customers.js.map +7 -0
- package/dist/modules/entities/api/entity-settings.js +59 -9
- package/dist/modules/entities/api/entity-settings.js.map +2 -2
- package/dist/modules/entities/backend/config/settings/page.js +10 -0
- package/dist/modules/entities/backend/config/settings/page.js.map +7 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js +36 -0
- package/dist/modules/entities/backend/config/settings/page.meta.js.map +7 -0
- package/dist/modules/entities/backend/entities/user/create/page.js +16 -7
- package/dist/modules/entities/backend/entities/user/create/page.js.map +2 -2
- package/dist/modules/entities/components/EntitySettingsManager.js +136 -0
- package/dist/modules/entities/components/EntitySettingsManager.js.map +7 -0
- package/dist/modules/inbox_ops/api/webhook/inbound.js +14 -10
- package/dist/modules/inbox_ops/api/webhook/inbound.js.map +2 -2
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/payment_gateways/api/webhook/[provider]/route.js.map +2 -2
- package/dist/modules/payment_gateways/data/entities.js +4 -0
- package/dist/modules/payment_gateways/data/entities.js.map +2 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js +12 -2
- package/dist/modules/payment_gateways/lib/gateway-service.js.map +2 -2
- package/dist/modules/payment_gateways/lib/session-idempotency.js +33 -0
- package/dist/modules/payment_gateways/lib/session-idempotency.js.map +2 -2
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js +18 -0
- package/dist/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.js.map +7 -0
- package/dist/modules/payment_gateways/setup.js +47 -0
- package/dist/modules/payment_gateways/setup.js.map +2 -2
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js +50 -0
- package/dist/modules/payment_gateways/workers/session-initialization-prune.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js +134 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.js.map +7 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js +11 -0
- package/dist/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.js.map +7 -0
- package/dist/modules/portal/lib/navigation.js +7 -0
- package/dist/modules/portal/lib/navigation.js.map +7 -0
- package/dist/modules/query_index/lib/engine.js +43 -0
- package/dist/modules/query_index/lib/engine.js.map +2 -2
- package/dist/modules/query_index/lib/search-tokens.js +15 -5
- package/dist/modules/query_index/lib/search-tokens.js.map +2 -2
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js +11 -1
- package/dist/modules/shipping_carriers/api/webhook/[provider]/route.js.map +2 -2
- package/generated/entities/customer_deal_person_link/index.ts +1 -0
- package/generated/entities/customer_user_invitation/index.ts +1 -0
- package/generated/entity-fields-registry.ts +2 -0
- package/package.json +7 -7
- package/src/modules/business_rules/api/openmercato-call-options/route.ts +94 -0
- package/src/modules/business_rules/api/rules/route.ts +92 -4
- package/src/modules/business_rules/components/ActionBuilder.tsx +54 -5
- package/src/modules/business_rules/components/ActionRow.tsx +156 -18
- package/src/modules/business_rules/components/utils/actionValidation.ts +6 -0
- package/src/modules/business_rules/i18n/de.json +12 -0
- package/src/modules/business_rules/i18n/en.json +12 -0
- package/src/modules/business_rules/i18n/es.json +12 -0
- package/src/modules/business_rules/i18n/pl.json +12 -0
- package/src/modules/business_rules/lib/action-executor.ts +198 -0
- package/src/modules/business_rules/lib/openmercato-call-options-types.ts +31 -0
- package/src/modules/business_rules/lib/openmercato-call-options.ts +297 -0
- package/src/modules/business_rules/lib/rule-engine.ts +4 -0
- package/src/modules/communication_channels/api/post/webhook/[provider]/route.ts +11 -1
- package/src/modules/communication_channels/api/post/webhooks/gmail/route.ts +17 -11
- package/src/modules/configs/lib/upgrade-actions.ts +14 -0
- package/src/modules/customer_accounts/api/admin/users/[id].ts +16 -1
- package/src/modules/customer_accounts/api/admin/users-invite.ts +78 -3
- package/src/modules/customer_accounts/api/portal/users-invite.ts +22 -1
- package/src/modules/customer_accounts/data/entities.ts +3 -0
- package/src/modules/customer_accounts/data/validators.ts +1 -0
- package/src/modules/customer_accounts/emails/CustomerInvitationEmail.tsx +45 -0
- package/src/modules/customer_accounts/i18n/de.json +6 -0
- package/src/modules/customer_accounts/i18n/en.json +6 -0
- package/src/modules/customer_accounts/i18n/es.json +6 -0
- package/src/modules/customer_accounts/i18n/pl.json +6 -0
- package/src/modules/customer_accounts/lib/customerEntityOwnership.ts +68 -2
- package/src/modules/customer_accounts/lib/customerUrl.ts +27 -11
- package/src/modules/customer_accounts/lib/invitationEmail.ts +42 -0
- package/src/modules/customer_accounts/migrations/.snapshot-open-mercato.json +16 -0
- package/src/modules/customer_accounts/migrations/Migration20260723120000_customer_accounts.ts +13 -0
- package/src/modules/customer_accounts/services/customerInvitationService.ts +56 -3
- package/src/modules/customer_accounts/subscribers/autoLinkCrm.ts +75 -8
- package/src/modules/customer_accounts/widgets/injection/account-status/widget.client.tsx +2 -2
- package/src/modules/customer_accounts/widgets/injection-table.ts +4 -1
- package/src/modules/customers/api/deals/[id]/people/route.ts +3 -0
- package/src/modules/customers/api/deals/[id]/route.ts +10 -2
- package/src/modules/customers/backend/customers/companies-v2/[id]/page.tsx +12 -1
- package/src/modules/customers/backend/customers/deals/[id]/hooks/types.ts +1 -0
- package/src/modules/customers/backend/customers/deals/[id]/page.tsx +15 -9
- package/src/modules/customers/backend/customers/people-v2/[id]/page.tsx +24 -6
- package/src/modules/customers/commands/deals.ts +50 -9
- package/src/modules/customers/commands/people.ts +3 -0
- package/src/modules/customers/components/detail/CompanyDetailTabs.tsx +30 -7
- package/src/modules/customers/components/detail/DealDetailTabs.tsx +34 -9
- package/src/modules/customers/components/detail/PersonDetailTabs.tsx +34 -9
- package/src/modules/customers/data/entities.ts +9 -1
- package/src/modules/customers/data/validators.ts +1 -0
- package/src/modules/customers/i18n/de.json +1 -0
- package/src/modules/customers/i18n/en.json +1 -0
- package/src/modules/customers/i18n/es.json +1 -0
- package/src/modules/customers/i18n/pl.json +1 -0
- package/src/modules/customers/migrations/.snapshot-open-mercato.json +27 -1
- package/src/modules/customers/migrations/Migration20260723210000_customers.ts +15 -0
- package/src/modules/entities/api/entity-settings.ts +66 -22
- package/src/modules/entities/backend/config/settings/page.meta.ts +34 -0
- package/src/modules/entities/backend/config/settings/page.tsx +12 -0
- package/src/modules/entities/backend/entities/user/create/page.tsx +16 -7
- package/src/modules/entities/components/EntitySettingsManager.tsx +160 -0
- package/src/modules/entities/i18n/de.json +9 -0
- package/src/modules/entities/i18n/en.json +9 -0
- package/src/modules/entities/i18n/es.json +9 -0
- package/src/modules/entities/i18n/pl.json +9 -0
- package/src/modules/inbox_ops/api/webhook/inbound.ts +14 -12
- package/src/modules/payment_gateways/api/webhook/[provider]/route.ts +13 -1
- package/src/modules/payment_gateways/data/entities.ts +5 -0
- package/src/modules/payment_gateways/i18n/de.json +5 -1
- package/src/modules/payment_gateways/i18n/en.json +5 -1
- package/src/modules/payment_gateways/i18n/es.json +5 -1
- package/src/modules/payment_gateways/i18n/pl.json +5 -1
- package/src/modules/payment_gateways/lib/gateway-service.ts +12 -2
- package/src/modules/payment_gateways/lib/session-idempotency.ts +36 -0
- package/src/modules/payment_gateways/migrations/.snapshot-open-mercato.json +10 -1
- package/src/modules/payment_gateways/migrations/Migration20260803103035_payment_gateways.ts +17 -0
- package/src/modules/payment_gateways/setup.ts +62 -0
- package/src/modules/payment_gateways/workers/session-initialization-prune.ts +63 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.meta.ts +9 -0
- package/src/modules/portal/frontend/[orgSlug]/portal/invite/page.tsx +164 -0
- package/src/modules/portal/i18n/de.json +18 -0
- package/src/modules/portal/i18n/en.json +18 -0
- package/src/modules/portal/i18n/es.json +18 -0
- package/src/modules/portal/i18n/pl.json +18 -0
- package/src/modules/portal/lib/navigation.ts +3 -0
- package/src/modules/query_index/lib/engine.ts +52 -0
- package/src/modules/query_index/lib/search-tokens.ts +16 -4
- package/src/modules/shipping_carriers/api/webhook/[provider]/route.ts +11 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { NextResponse } from "next/server";
|
|
2
|
+
import { z } from "zod";
|
|
3
|
+
import { getAuthFromRequest } from "@open-mercato/shared/lib/auth/server";
|
|
4
|
+
import { createRequestContainer } from "@open-mercato/shared/lib/di/container";
|
|
5
|
+
import {
|
|
6
|
+
getCurrentOpenMercatoEndpointOptions,
|
|
7
|
+
listOpenMercatoApiKeyOptions
|
|
8
|
+
} from "../../lib/openmercato-call-options.js";
|
|
9
|
+
const roleOptionSchema = z.object({
|
|
10
|
+
id: z.string(),
|
|
11
|
+
name: z.string().nullable()
|
|
12
|
+
});
|
|
13
|
+
const endpointOptionSchema = z.object({
|
|
14
|
+
id: z.string(),
|
|
15
|
+
path: z.string(),
|
|
16
|
+
method: z.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
17
|
+
label: z.string(),
|
|
18
|
+
summary: z.string().nullable(),
|
|
19
|
+
operationId: z.string().nullable()
|
|
20
|
+
});
|
|
21
|
+
const apiKeyOptionSchema = z.object({
|
|
22
|
+
id: z.string(),
|
|
23
|
+
name: z.string(),
|
|
24
|
+
keyPrefix: z.string(),
|
|
25
|
+
organizationId: z.string().nullable(),
|
|
26
|
+
organizationName: z.string().nullable(),
|
|
27
|
+
roles: z.array(roleOptionSchema)
|
|
28
|
+
});
|
|
29
|
+
const optionsResponseSchema = z.object({
|
|
30
|
+
endpoints: z.array(endpointOptionSchema),
|
|
31
|
+
apiKeys: z.array(apiKeyOptionSchema)
|
|
32
|
+
});
|
|
33
|
+
const errorResponseSchema = z.object({
|
|
34
|
+
error: z.string()
|
|
35
|
+
});
|
|
36
|
+
const metadata = {
|
|
37
|
+
GET: { requireAuth: true, requireFeatures: ["business_rules.manage", "api_keys.create"] }
|
|
38
|
+
};
|
|
39
|
+
async function GET(req) {
|
|
40
|
+
const auth = await getAuthFromRequest(req);
|
|
41
|
+
if (!auth) {
|
|
42
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
43
|
+
}
|
|
44
|
+
if (!auth.tenantId) {
|
|
45
|
+
return NextResponse.json({ error: "Tenant context required" }, { status: 400 });
|
|
46
|
+
}
|
|
47
|
+
const container = await createRequestContainer();
|
|
48
|
+
const em = container.resolve("em");
|
|
49
|
+
const [endpoints, apiKeys] = await Promise.all([
|
|
50
|
+
getCurrentOpenMercatoEndpointOptions(),
|
|
51
|
+
listOpenMercatoApiKeyOptions(em, {
|
|
52
|
+
tenantId: auth.tenantId,
|
|
53
|
+
organizationId: auth.orgId ?? null
|
|
54
|
+
})
|
|
55
|
+
]);
|
|
56
|
+
return NextResponse.json({ endpoints, apiKeys });
|
|
57
|
+
}
|
|
58
|
+
const openApi = {
|
|
59
|
+
tag: "Business Rules",
|
|
60
|
+
summary: "List OpenMercato call action options",
|
|
61
|
+
methods: {
|
|
62
|
+
GET: {
|
|
63
|
+
summary: "List OpenMercato call action options",
|
|
64
|
+
description: "Returns executable Open Mercato API endpoint options and safe API key profile metadata for business-rule actions.",
|
|
65
|
+
responses: [
|
|
66
|
+
{
|
|
67
|
+
status: 200,
|
|
68
|
+
description: "OpenMercato call options",
|
|
69
|
+
schema: optionsResponseSchema
|
|
70
|
+
}
|
|
71
|
+
],
|
|
72
|
+
errors: [
|
|
73
|
+
{ status: 400, description: "Tenant context missing", schema: errorResponseSchema },
|
|
74
|
+
{ status: 401, description: "Unauthorized", schema: errorResponseSchema },
|
|
75
|
+
{ status: 403, description: "Missing required features", schema: errorResponseSchema }
|
|
76
|
+
]
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
export {
|
|
81
|
+
GET,
|
|
82
|
+
metadata,
|
|
83
|
+
openApi
|
|
84
|
+
};
|
|
85
|
+
//# sourceMappingURL=route.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/modules/business_rules/api/openmercato-call-options/route.ts"],
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport {\n getCurrentOpenMercatoEndpointOptions,\n listOpenMercatoApiKeyOptions,\n} from '../../lib/openmercato-call-options'\n\nconst roleOptionSchema = z.object({\n id: z.string(),\n name: z.string().nullable(),\n})\n\nconst endpointOptionSchema = z.object({\n id: z.string(),\n path: z.string(),\n method: z.enum(['GET', 'POST', 'PUT', 'PATCH', 'DELETE']),\n label: z.string(),\n summary: z.string().nullable(),\n operationId: z.string().nullable(),\n})\n\nconst apiKeyOptionSchema = z.object({\n id: z.string(),\n name: z.string(),\n keyPrefix: z.string(),\n organizationId: z.string().nullable(),\n organizationName: z.string().nullable(),\n roles: z.array(roleOptionSchema),\n})\n\nconst optionsResponseSchema = z.object({\n endpoints: z.array(endpointOptionSchema),\n apiKeys: z.array(apiKeyOptionSchema),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nexport const metadata = {\n GET: { requireAuth: true, requireFeatures: ['business_rules.manage', 'api_keys.create'] },\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n if (!auth.tenantId) {\n return NextResponse.json({ error: 'Tenant context required' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const [endpoints, apiKeys] = await Promise.all([\n getCurrentOpenMercatoEndpointOptions(),\n listOpenMercatoApiKeyOptions(em, {\n tenantId: auth.tenantId,\n organizationId: auth.orgId ?? null,\n }),\n ])\n\n return NextResponse.json({ endpoints, apiKeys })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Business Rules',\n summary: 'List OpenMercato call action options',\n methods: {\n GET: {\n summary: 'List OpenMercato call action options',\n description:\n 'Returns executable Open Mercato API endpoint options and safe API key profile metadata for business-rule actions.',\n responses: [\n {\n status: 200,\n description: 'OpenMercato call options',\n schema: optionsResponseSchema,\n },\n ],\n errors: [\n { status: 400, description: 'Tenant context missing', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 403, description: 'Missing required features', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "AAAA,SAAS,oBAAoB;AAC7B,SAAS,SAAS;AAGlB,SAAS,0BAA0B;AACnC,SAAS,8BAA8B;AACvC;AAAA,EACE;AAAA,EACA;AAAA,OACK;AAEP,MAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO,EAAE,SAAS;AAC5B,CAAC;AAED,MAAM,uBAAuB,EAAE,OAAO;AAAA,EACpC,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,QAAQ,EAAE,KAAK,CAAC,OAAO,QAAQ,OAAO,SAAS,QAAQ,CAAC;AAAA,EACxD,OAAO,EAAE,OAAO;AAAA,EAChB,SAAS,EAAE,OAAO,EAAE,SAAS;AAAA,EAC7B,aAAa,EAAE,OAAO,EAAE,SAAS;AACnC,CAAC;AAED,MAAM,qBAAqB,EAAE,OAAO;AAAA,EAClC,IAAI,EAAE,OAAO;AAAA,EACb,MAAM,EAAE,OAAO;AAAA,EACf,WAAW,EAAE,OAAO;AAAA,EACpB,gBAAgB,EAAE,OAAO,EAAE,SAAS;AAAA,EACpC,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,OAAO,EAAE,MAAM,gBAAgB;AACjC,CAAC;AAED,MAAM,wBAAwB,EAAE,OAAO;AAAA,EACrC,WAAW,EAAE,MAAM,oBAAoB;AAAA,EACvC,SAAS,EAAE,MAAM,kBAAkB;AACrC,CAAC;AAED,MAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,OAAO,EAAE,OAAO;AAClB,CAAC;AAEM,MAAM,WAAW;AAAA,EACtB,KAAK,EAAE,aAAa,MAAM,iBAAiB,CAAC,yBAAyB,iBAAiB,EAAE;AAC1F;AAEA,eAAsB,IAAI,KAAc;AACtC,QAAM,OAAO,MAAM,mBAAmB,GAAG;AACzC,MAAI,CAAC,MAAM;AACT,WAAO,aAAa,KAAK,EAAE,OAAO,eAAe,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EACrE;AAEA,MAAI,CAAC,KAAK,UAAU;AAClB,WAAO,aAAa,KAAK,EAAE,OAAO,0BAA0B,GAAG,EAAE,QAAQ,IAAI,CAAC;AAAA,EAChF;AAEA,QAAM,YAAY,MAAM,uBAAuB;AAC/C,QAAM,KAAK,UAAU,QAAQ,IAAI;AAEjC,QAAM,CAAC,WAAW,OAAO,IAAI,MAAM,QAAQ,IAAI;AAAA,IAC7C,qCAAqC;AAAA,IACrC,6BAA6B,IAAI;AAAA,MAC/B,UAAU,KAAK;AAAA,MACf,gBAAgB,KAAK,SAAS;AAAA,IAChC,CAAC;AAAA,EACH,CAAC;AAED,SAAO,aAAa,KAAK,EAAE,WAAW,QAAQ,CAAC;AACjD;AAEO,MAAM,UAA2B;AAAA,EACtC,KAAK;AAAA,EACL,SAAS;AAAA,EACT,SAAS;AAAA,IACP,KAAK;AAAA,MACH,SAAS;AAAA,MACT,aACE;AAAA,MACF,WAAW;AAAA,QACT;AAAA,UACE,QAAQ;AAAA,UACR,aAAa;AAAA,UACb,QAAQ;AAAA,QACV;AAAA,MACF;AAAA,MACA,QAAQ;AAAA,QACN,EAAE,QAAQ,KAAK,aAAa,0BAA0B,QAAQ,oBAAoB;AAAA,QAClF,EAAE,QAAQ,KAAK,aAAa,gBAAgB,QAAQ,oBAAoB;AAAA,QACxE,EAAE,QAAQ,KAAK,aAAa,6BAA6B,QAAQ,oBAAoB;AAAA,MACvF;AAAA,IACF;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -18,6 +18,7 @@ import {
|
|
|
18
18
|
invalidateBusinessRuleDiscoveryCache,
|
|
19
19
|
resolveBusinessRuleDiscoveryCache
|
|
20
20
|
} from "../../lib/rule-engine.js";
|
|
21
|
+
import { validateOpenMercatoCallActions } from "../../lib/openmercato-call-options.js";
|
|
21
22
|
import { createLogger } from "@open-mercato/shared/lib/logger";
|
|
22
23
|
const logger = createLogger("business_rules").child({ component: "rules-api" });
|
|
23
24
|
const querySchema = z.looseObject({
|
|
@@ -74,6 +75,27 @@ const routeMetadata = {
|
|
|
74
75
|
DELETE: { requireAuth: true, requireFeatures: ["business_rules.manage"] }
|
|
75
76
|
};
|
|
76
77
|
const metadata = routeMetadata;
|
|
78
|
+
function hasOpenMercatoCallAction(actions) {
|
|
79
|
+
return Array.isArray(actions) && actions.some((action) => action && typeof action === "object" && action.type === "CALL_OPEN_MERCATO");
|
|
80
|
+
}
|
|
81
|
+
async function requireOpenMercatoCallConfiguratorAccess(container, auth) {
|
|
82
|
+
if (!auth.sub) {
|
|
83
|
+
return NextResponse.json(
|
|
84
|
+
{ error: "Forbidden", requiredFeatures: ["api_keys.create"] },
|
|
85
|
+
{ status: 403 }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
const rbac = container.resolve("rbacService");
|
|
89
|
+
const allowed = await rbac?.userHasAllFeatures?.(auth.sub, ["api_keys.create"], {
|
|
90
|
+
tenantId: auth.tenantId ?? null,
|
|
91
|
+
organizationId: auth.orgId ?? null
|
|
92
|
+
});
|
|
93
|
+
if (allowed) return null;
|
|
94
|
+
return NextResponse.json(
|
|
95
|
+
{ error: "Forbidden", requiredFeatures: ["api_keys.create"] },
|
|
96
|
+
{ status: 403 }
|
|
97
|
+
);
|
|
98
|
+
}
|
|
77
99
|
async function GET(req) {
|
|
78
100
|
const auth = await getAuthFromRequest(req);
|
|
79
101
|
if (!auth) {
|
|
@@ -160,6 +182,11 @@ async function POST(req) {
|
|
|
160
182
|
if (!auth) {
|
|
161
183
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
162
184
|
}
|
|
185
|
+
if (!auth.tenantId || !auth.orgId) {
|
|
186
|
+
return NextResponse.json({ error: "Tenant and organization context required" }, { status: 400 });
|
|
187
|
+
}
|
|
188
|
+
const tenantId = auth.tenantId;
|
|
189
|
+
const organizationId = auth.orgId;
|
|
163
190
|
const container = await createRequestContainer();
|
|
164
191
|
const em = container.resolve("em");
|
|
165
192
|
const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container));
|
|
@@ -171,8 +198,8 @@ async function POST(req) {
|
|
|
171
198
|
}
|
|
172
199
|
const payload = {
|
|
173
200
|
...body,
|
|
174
|
-
tenantId
|
|
175
|
-
organizationId
|
|
201
|
+
tenantId,
|
|
202
|
+
organizationId,
|
|
176
203
|
createdBy: auth.sub ?? auth.email ?? null
|
|
177
204
|
};
|
|
178
205
|
const { t } = await resolveTranslations();
|
|
@@ -182,6 +209,23 @@ async function POST(req) {
|
|
|
182
209
|
const errors = parsed.error.issues.map((e) => `${e.path.join(".")}: ${e.message}`);
|
|
183
210
|
return NextResponse.json({ error: `Validation failed: ${errors.join(", ")}` }, { status: 400 });
|
|
184
211
|
}
|
|
212
|
+
if (hasOpenMercatoCallAction(parsed.data.successActions) || hasOpenMercatoCallAction(parsed.data.failureActions)) {
|
|
213
|
+
const accessError = await requireOpenMercatoCallConfiguratorAccess(container, auth);
|
|
214
|
+
if (accessError) return accessError;
|
|
215
|
+
}
|
|
216
|
+
const actionErrors = [
|
|
217
|
+
...await validateOpenMercatoCallActions(em, parsed.data.successActions, {
|
|
218
|
+
tenantId,
|
|
219
|
+
organizationId
|
|
220
|
+
}),
|
|
221
|
+
...await validateOpenMercatoCallActions(em, parsed.data.failureActions, {
|
|
222
|
+
tenantId,
|
|
223
|
+
organizationId
|
|
224
|
+
})
|
|
225
|
+
];
|
|
226
|
+
if (actionErrors.length > 0) {
|
|
227
|
+
return NextResponse.json({ error: `Validation failed: ${actionErrors.join(", ")}` }, { status: 400 });
|
|
228
|
+
}
|
|
185
229
|
const data = {
|
|
186
230
|
...parsed.data,
|
|
187
231
|
conditionExpression: parsed.data.conditionExpression ?? null
|
|
@@ -204,6 +248,11 @@ async function PUT(req) {
|
|
|
204
248
|
if (!auth) {
|
|
205
249
|
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
206
250
|
}
|
|
251
|
+
if (!auth.tenantId || !auth.orgId) {
|
|
252
|
+
return NextResponse.json({ error: "Tenant and organization context required" }, { status: 400 });
|
|
253
|
+
}
|
|
254
|
+
const tenantId = auth.tenantId;
|
|
255
|
+
const organizationId = auth.orgId;
|
|
207
256
|
const container = await createRequestContainer();
|
|
208
257
|
const em = container.resolve("em");
|
|
209
258
|
const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container));
|
|
@@ -232,13 +281,31 @@ async function PUT(req) {
|
|
|
232
281
|
}
|
|
233
282
|
const rule = await em.findOne(BusinessRule, {
|
|
234
283
|
id: parsed.data.id,
|
|
235
|
-
tenantId
|
|
236
|
-
organizationId
|
|
284
|
+
tenantId,
|
|
285
|
+
organizationId,
|
|
237
286
|
deletedAt: null
|
|
238
287
|
});
|
|
239
288
|
if (!rule) {
|
|
240
289
|
return NextResponse.json({ error: "Rule not found" }, { status: 404 });
|
|
241
290
|
}
|
|
291
|
+
const touchesOpenMercatoCall = hasOpenMercatoCallAction(parsed.data.successActions) || hasOpenMercatoCallAction(parsed.data.failureActions) || hasOpenMercatoCallAction(rule.successActions) || hasOpenMercatoCallAction(rule.failureActions);
|
|
292
|
+
if (touchesOpenMercatoCall) {
|
|
293
|
+
const accessError = await requireOpenMercatoCallConfiguratorAccess(container, auth);
|
|
294
|
+
if (accessError) return accessError;
|
|
295
|
+
}
|
|
296
|
+
const actionErrors = [
|
|
297
|
+
...await validateOpenMercatoCallActions(em, parsed.data.successActions, {
|
|
298
|
+
tenantId,
|
|
299
|
+
organizationId
|
|
300
|
+
}),
|
|
301
|
+
...await validateOpenMercatoCallActions(em, parsed.data.failureActions, {
|
|
302
|
+
tenantId,
|
|
303
|
+
organizationId
|
|
304
|
+
})
|
|
305
|
+
];
|
|
306
|
+
if (actionErrors.length > 0) {
|
|
307
|
+
return NextResponse.json({ error: `Validation failed: ${actionErrors.join(", ")}` }, { status: 400 });
|
|
308
|
+
}
|
|
242
309
|
try {
|
|
243
310
|
await enforceCommandOptimisticLockWithGuards(container, {
|
|
244
311
|
resourceKind: "business_rules.rule",
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../../src/modules/business_rules/api/rules/route.ts"],
|
|
4
|
-
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { BusinessRule } from '../../data/entities'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport {\n createBusinessRuleSchema,\n updateBusinessRuleSchema,\n createLocalizedBusinessRuleSchema,\n createLocalizedUpdateBusinessRuleSchema,\n businessRuleFilterSchema,\n ruleTypeSchema,\n} from '../../data/validators'\nimport {\n invalidateBusinessRuleDiscoveryCache,\n resolveBusinessRuleDiscoveryCache,\n} from '../../lib/rule-engine'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('business_rules').child({ component: 'rules-api' })\n\nconst querySchema = z.looseObject({\n id: z.uuid().optional(),\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n ruleId: z.string().optional(),\n ruleType: ruleTypeSchema.optional(),\n entityType: z.string().optional(),\n eventType: z.string().optional(),\n enabled: z.coerce.boolean().optional(),\n ruleCategory: z.string().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional().default('desc'),\n})\n\nconst ruleListItemSchema = z.object({\n id: z.string().uuid(),\n ruleId: z.string(),\n ruleName: z.string(),\n description: z.string().nullable(),\n ruleType: ruleTypeSchema,\n ruleCategory: z.string().nullable(),\n entityType: z.string(),\n eventType: z.string().nullable(),\n enabled: z.boolean(),\n priority: z.number(),\n version: z.number(),\n effectiveFrom: z.string().nullable(),\n effectiveTo: z.string().nullable(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nconst ruleListResponseSchema = z.object({\n items: z.array(ruleListItemSchema),\n total: z.number().int().nonnegative(),\n totalPages: z.number().int().positive(),\n})\n\nconst ruleCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst okResponseSchema = z.object({\n ok: z.literal(true),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['business_rules.view'] },\n POST: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = querySchema.safeParse({\n id: url.searchParams.get('id') || undefined,\n page: url.searchParams.get('page') || undefined,\n pageSize: url.searchParams.get('pageSize') || undefined,\n search: url.searchParams.get('search') || undefined,\n ruleId: url.searchParams.get('ruleId') || undefined,\n ruleType: url.searchParams.get('ruleType') || undefined,\n entityType: url.searchParams.get('entityType') || undefined,\n eventType: url.searchParams.get('eventType') || undefined,\n enabled: url.searchParams.get('enabled') || undefined,\n ruleCategory: url.searchParams.get('ruleCategory') || undefined,\n sortField: url.searchParams.get('sortField') || undefined,\n sortDir: url.searchParams.get('sortDir') || undefined,\n })\n\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query parameters' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { id, page, pageSize, search, ruleId, ruleType, entityType, eventType, enabled, ruleCategory, sortField, sortDir } = parsed.data\n\n const filters: Record<string, any> = {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n }\n\n if (id) filters.id = id\n if (ruleId) filters.ruleId = { $ilike: `%${escapeLikePattern(ruleId)}%` }\n if (search) filters.ruleName = { $ilike: `%${escapeLikePattern(search)}%` }\n if (ruleType) filters.ruleType = ruleType\n if (entityType) filters.entityType = entityType\n if (eventType) filters.eventType = eventType\n if (enabled !== undefined) filters.enabled = enabled\n if (ruleCategory) filters.ruleCategory = ruleCategory\n\n const sortFieldMap: Record<string, string> = {\n ruleId: 'ruleId',\n ruleName: 'ruleName',\n ruleType: 'ruleType',\n entityType: 'entityType',\n priority: 'priority',\n createdAt: 'createdAt',\n updatedAt: 'updatedAt',\n }\n\n const orderByField = sortField && sortFieldMap[sortField] ? sortFieldMap[sortField] : 'priority'\n const orderBy = { [orderByField]: sortDir, ruleId: 'asc' as const }\n\n const [rows, count] = await em.findAndCount(\n BusinessRule,\n filters,\n {\n limit: pageSize,\n offset: (page - 1) * pageSize,\n orderBy,\n }\n )\n\n const items = rows.map((rule) => ({\n id: rule.id,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n description: rule.description ?? null,\n ruleType: rule.ruleType,\n ruleCategory: rule.ruleCategory ?? null,\n entityType: rule.entityType,\n eventType: rule.eventType ?? null,\n enabled: rule.enabled,\n priority: rule.priority,\n version: rule.version,\n effectiveFrom: rule.effectiveFrom ? rule.effectiveFrom.toISOString() : null,\n effectiveTo: rule.effectiveTo ? rule.effectiveTo.toISOString() : null,\n tenantId: rule.tenantId,\n organizationId: rule.organizationId,\n createdAt: rule.createdAt.toISOString(),\n updatedAt: rule.updatedAt.toISOString(),\n }))\n\n const totalPages = Math.max(1, Math.ceil(count / pageSize))\n\n return NextResponse.json({ items, total: count, totalPages })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n let body: any\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })\n }\n\n const payload = {\n ...body,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n createdBy: auth.sub ?? auth.email ?? null,\n }\n\n const { t } = await resolveTranslations()\n const schema = createLocalizedBusinessRuleSchema(t)\n const parsed = schema.safeParse(payload)\n if (!parsed.success) {\n const errors = parsed.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return NextResponse.json({ error: `Validation failed: ${errors.join(', ')}` }, { status: 400 })\n }\n\n const data = {\n ...parsed.data,\n conditionExpression: parsed.data.conditionExpression ?? null,\n }\n\n const rule = em.create(BusinessRule, data)\n\n try {\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n } catch (error) {\n logger.error('Failed to persist new rule', { err: error })\n return NextResponse.json(\n { error: t('business_rules.errors.createFailed') },\n { status: 500 },\n )\n }\n\n return NextResponse.json({ id: rule.id }, { status: 201 })\n}\n\nexport async function PUT(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n let body: any\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })\n }\n\n if (!body.id) {\n return NextResponse.json({ error: 'Rule id is required' }, { status: 400 })\n }\n\n const payload = {\n ...body,\n updatedBy: auth.sub ?? auth.email ?? null,\n }\n delete (payload as Record<string, unknown>).tenantId\n delete (payload as Record<string, unknown>).organizationId\n delete (payload as Record<string, unknown>).createdBy\n\n const { t } = await resolveTranslations()\n const schema = createLocalizedUpdateBusinessRuleSchema(t)\n const parsed = schema.safeParse(payload)\n if (!parsed.success) {\n const errors = parsed.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return NextResponse.json({ error: `Validation failed: ${errors.join(', ')}` }, { status: 400 })\n }\n\n const rule = await em.findOne(BusinessRule, {\n id: parsed.data.id,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n })\n\n if (!rule) {\n return NextResponse.json({ error: 'Rule not found' }, { status: 404 })\n }\n\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'business_rules.rule',\n resourceId: rule.id,\n current: rule.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n throw err\n }\n\n em.assign(rule, parsed.data)\n\n try {\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n } catch (error) {\n logger.error('Failed to persist rule update', { err: error })\n return NextResponse.json(\n { error: t('business_rules.errors.updateFailed') },\n { status: 500 },\n )\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport async function DELETE(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const id = url.searchParams.get('id')\n\n if (!id) {\n return NextResponse.json({ error: 'Rule id is required' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n const rule = await em.findOne(BusinessRule, {\n id,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n })\n\n if (!rule) {\n return NextResponse.json({ error: 'Rule not found' }, { status: 404 })\n }\n\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'business_rules.rule',\n resourceId: rule.id,\n current: rule.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n throw err\n }\n\n rule.deletedAt = new Date()\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Business Rules',\n summary: 'Business rule management',\n methods: {\n GET: {\n summary: 'List business rules',\n description: 'Returns business rules for the current tenant and organization with filtering and pagination.',\n query: querySchema,\n responses: [\n { status: 200, description: 'Business rules collection', schema: ruleListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query parameters', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Create business rule',\n description: 'Creates a new business rule for the current tenant and organization.',\n requestBody: {\n contentType: 'application/json',\n schema: createBusinessRuleSchema,\n },\n responses: [\n {\n status: 201,\n description: 'Business rule created',\n schema: ruleCreateResponseSchema,\n },\n ],\n errors: [\n { status: 400, description: 'Invalid payload', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n PUT: {\n summary: 'Update business rule',\n description: 'Updates an existing business rule.',\n requestBody: {\n contentType: 'application/json',\n schema: updateBusinessRuleSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Business rule updated',\n schema: okResponseSchema,\n },\n ],\n errors: [\n { status: 400, description: 'Invalid payload', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 404, description: 'Business rule not found', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Delete business rule',\n description: 'Soft deletes a business rule by identifier.',\n query: z.object({ id: z.string().uuid().describe('Business rule identifier') }),\n responses: [\n { status: 200, description: 'Business rule deleted', schema: okResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 404, description: 'Business rule not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["import { NextResponse } from 'next/server'\nimport { z } from 'zod'\nimport type { OpenApiRouteDoc } from '@open-mercato/shared/lib/openapi'\nimport { getAuthFromRequest } from '@open-mercato/shared/lib/auth/server'\nimport { createRequestContainer } from '@open-mercato/shared/lib/di/container'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\nimport { isCrudHttpError } from '@open-mercato/shared/lib/crud/errors'\nimport { enforceCommandOptimisticLockWithGuards } from '@open-mercato/shared/lib/crud/optimistic-lock-command'\nimport { BusinessRule } from '../../data/entities'\nimport type { EntityManager } from '@mikro-orm/postgresql'\nimport { escapeLikePattern } from '@open-mercato/shared/lib/db/escapeLikePattern'\nimport {\n createBusinessRuleSchema,\n updateBusinessRuleSchema,\n createLocalizedBusinessRuleSchema,\n createLocalizedUpdateBusinessRuleSchema,\n businessRuleFilterSchema,\n ruleTypeSchema,\n} from '../../data/validators'\nimport {\n invalidateBusinessRuleDiscoveryCache,\n resolveBusinessRuleDiscoveryCache,\n} from '../../lib/rule-engine'\nimport { validateOpenMercatoCallActions } from '../../lib/openmercato-call-options'\nimport { createLogger } from '@open-mercato/shared/lib/logger'\n\nconst logger = createLogger('business_rules').child({ component: 'rules-api' })\n\nconst querySchema = z.looseObject({\n id: z.uuid().optional(),\n page: z.coerce.number().min(1).default(1),\n pageSize: z.coerce.number().min(1).max(100).default(50),\n search: z.string().optional(),\n ruleId: z.string().optional(),\n ruleType: ruleTypeSchema.optional(),\n entityType: z.string().optional(),\n eventType: z.string().optional(),\n enabled: z.coerce.boolean().optional(),\n ruleCategory: z.string().optional(),\n sortField: z.string().optional(),\n sortDir: z.enum(['asc', 'desc']).optional().default('desc'),\n})\n\nconst ruleListItemSchema = z.object({\n id: z.string().uuid(),\n ruleId: z.string(),\n ruleName: z.string(),\n description: z.string().nullable(),\n ruleType: ruleTypeSchema,\n ruleCategory: z.string().nullable(),\n entityType: z.string(),\n eventType: z.string().nullable(),\n enabled: z.boolean(),\n priority: z.number(),\n version: z.number(),\n effectiveFrom: z.string().nullable(),\n effectiveTo: z.string().nullable(),\n tenantId: z.string().uuid(),\n organizationId: z.string().uuid(),\n createdAt: z.string(),\n updatedAt: z.string(),\n})\n\nconst ruleListResponseSchema = z.object({\n items: z.array(ruleListItemSchema),\n total: z.number().int().nonnegative(),\n totalPages: z.number().int().positive(),\n})\n\nconst ruleCreateResponseSchema = z.object({\n id: z.string().uuid(),\n})\n\nconst okResponseSchema = z.object({\n ok: z.literal(true),\n})\n\nconst errorResponseSchema = z.object({\n error: z.string(),\n})\n\nconst routeMetadata = {\n GET: { requireAuth: true, requireFeatures: ['business_rules.view'] },\n POST: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n PUT: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n DELETE: { requireAuth: true, requireFeatures: ['business_rules.manage'] },\n}\n\nexport const metadata = routeMetadata\n\nfunction hasOpenMercatoCallAction(actions: unknown): boolean {\n return Array.isArray(actions)\n && actions.some((action) => action && typeof action === 'object' && (action as { type?: unknown }).type === 'CALL_OPEN_MERCATO')\n}\n\nasync function requireOpenMercatoCallConfiguratorAccess(\n container: ReturnType<typeof createRequestContainer> extends Promise<infer T> ? T : never,\n auth: NonNullable<Awaited<ReturnType<typeof getAuthFromRequest>>>,\n): Promise<Response | null> {\n if (!auth.sub) {\n return NextResponse.json(\n { error: 'Forbidden', requiredFeatures: ['api_keys.create'] },\n { status: 403 },\n )\n }\n\n const rbac = container.resolve('rbacService') as {\n userHasAllFeatures?: (\n userId: string,\n required: string[],\n scope: { tenantId: string | null; organizationId: string | null },\n ) => Promise<boolean>\n } | undefined\n const allowed = await rbac?.userHasAllFeatures?.(auth.sub, ['api_keys.create'], {\n tenantId: auth.tenantId ?? null,\n organizationId: auth.orgId ?? null,\n })\n if (allowed) return null\n\n return NextResponse.json(\n { error: 'Forbidden', requiredFeatures: ['api_keys.create'] },\n { status: 403 },\n )\n}\n\nexport async function GET(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const parsed = querySchema.safeParse({\n id: url.searchParams.get('id') || undefined,\n page: url.searchParams.get('page') || undefined,\n pageSize: url.searchParams.get('pageSize') || undefined,\n search: url.searchParams.get('search') || undefined,\n ruleId: url.searchParams.get('ruleId') || undefined,\n ruleType: url.searchParams.get('ruleType') || undefined,\n entityType: url.searchParams.get('entityType') || undefined,\n eventType: url.searchParams.get('eventType') || undefined,\n enabled: url.searchParams.get('enabled') || undefined,\n ruleCategory: url.searchParams.get('ruleCategory') || undefined,\n sortField: url.searchParams.get('sortField') || undefined,\n sortDir: url.searchParams.get('sortDir') || undefined,\n })\n\n if (!parsed.success) {\n return NextResponse.json({ error: 'Invalid query parameters' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n\n const { id, page, pageSize, search, ruleId, ruleType, entityType, eventType, enabled, ruleCategory, sortField, sortDir } = parsed.data\n\n const filters: Record<string, any> = {\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n }\n\n if (id) filters.id = id\n if (ruleId) filters.ruleId = { $ilike: `%${escapeLikePattern(ruleId)}%` }\n if (search) filters.ruleName = { $ilike: `%${escapeLikePattern(search)}%` }\n if (ruleType) filters.ruleType = ruleType\n if (entityType) filters.entityType = entityType\n if (eventType) filters.eventType = eventType\n if (enabled !== undefined) filters.enabled = enabled\n if (ruleCategory) filters.ruleCategory = ruleCategory\n\n const sortFieldMap: Record<string, string> = {\n ruleId: 'ruleId',\n ruleName: 'ruleName',\n ruleType: 'ruleType',\n entityType: 'entityType',\n priority: 'priority',\n createdAt: 'createdAt',\n updatedAt: 'updatedAt',\n }\n\n const orderByField = sortField && sortFieldMap[sortField] ? sortFieldMap[sortField] : 'priority'\n const orderBy = { [orderByField]: sortDir, ruleId: 'asc' as const }\n\n const [rows, count] = await em.findAndCount(\n BusinessRule,\n filters,\n {\n limit: pageSize,\n offset: (page - 1) * pageSize,\n orderBy,\n }\n )\n\n const items = rows.map((rule) => ({\n id: rule.id,\n ruleId: rule.ruleId,\n ruleName: rule.ruleName,\n description: rule.description ?? null,\n ruleType: rule.ruleType,\n ruleCategory: rule.ruleCategory ?? null,\n entityType: rule.entityType,\n eventType: rule.eventType ?? null,\n enabled: rule.enabled,\n priority: rule.priority,\n version: rule.version,\n effectiveFrom: rule.effectiveFrom ? rule.effectiveFrom.toISOString() : null,\n effectiveTo: rule.effectiveTo ? rule.effectiveTo.toISOString() : null,\n tenantId: rule.tenantId,\n organizationId: rule.organizationId,\n createdAt: rule.createdAt.toISOString(),\n updatedAt: rule.updatedAt.toISOString(),\n }))\n\n const totalPages = Math.max(1, Math.ceil(count / pageSize))\n\n return NextResponse.json({ items, total: count, totalPages })\n}\n\nexport async function POST(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n if (!auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Tenant and organization context required' }, { status: 400 })\n }\n const tenantId = auth.tenantId\n const organizationId = auth.orgId\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n let body: any\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })\n }\n\n const payload = {\n ...body,\n tenantId,\n organizationId,\n createdBy: auth.sub ?? auth.email ?? null,\n }\n\n const { t } = await resolveTranslations()\n const schema = createLocalizedBusinessRuleSchema(t)\n const parsed = schema.safeParse(payload)\n if (!parsed.success) {\n const errors = parsed.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return NextResponse.json({ error: `Validation failed: ${errors.join(', ')}` }, { status: 400 })\n }\n\n if (hasOpenMercatoCallAction(parsed.data.successActions) || hasOpenMercatoCallAction(parsed.data.failureActions)) {\n const accessError = await requireOpenMercatoCallConfiguratorAccess(container, auth)\n if (accessError) return accessError\n }\n\n const actionErrors = [\n ...await validateOpenMercatoCallActions(em as EntityManager, parsed.data.successActions, {\n tenantId,\n organizationId,\n }),\n ...await validateOpenMercatoCallActions(em as EntityManager, parsed.data.failureActions, {\n tenantId,\n organizationId,\n }),\n ]\n if (actionErrors.length > 0) {\n return NextResponse.json({ error: `Validation failed: ${actionErrors.join(', ')}` }, { status: 400 })\n }\n\n const data = {\n ...parsed.data,\n conditionExpression: parsed.data.conditionExpression ?? null,\n }\n\n const rule = em.create(BusinessRule, data)\n\n try {\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n } catch (error) {\n logger.error('Failed to persist new rule', { err: error })\n return NextResponse.json(\n { error: t('business_rules.errors.createFailed') },\n { status: 500 },\n )\n }\n\n return NextResponse.json({ id: rule.id }, { status: 201 })\n}\n\nexport async function PUT(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n if (!auth.tenantId || !auth.orgId) {\n return NextResponse.json({ error: 'Tenant and organization context required' }, { status: 400 })\n }\n const tenantId = auth.tenantId\n const organizationId = auth.orgId\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n let body: any\n try {\n body = await req.json()\n } catch {\n return NextResponse.json({ error: 'Invalid JSON body' }, { status: 400 })\n }\n\n if (!body.id) {\n return NextResponse.json({ error: 'Rule id is required' }, { status: 400 })\n }\n\n const payload = {\n ...body,\n updatedBy: auth.sub ?? auth.email ?? null,\n }\n delete (payload as Record<string, unknown>).tenantId\n delete (payload as Record<string, unknown>).organizationId\n delete (payload as Record<string, unknown>).createdBy\n\n const { t } = await resolveTranslations()\n const schema = createLocalizedUpdateBusinessRuleSchema(t)\n const parsed = schema.safeParse(payload)\n if (!parsed.success) {\n const errors = parsed.error.issues.map(e => `${e.path.join('.')}: ${e.message}`)\n return NextResponse.json({ error: `Validation failed: ${errors.join(', ')}` }, { status: 400 })\n }\n\n const rule = await em.findOne(BusinessRule, {\n id: parsed.data.id,\n tenantId,\n organizationId,\n deletedAt: null,\n })\n\n if (!rule) {\n return NextResponse.json({ error: 'Rule not found' }, { status: 404 })\n }\n\n const touchesOpenMercatoCall = hasOpenMercatoCallAction(parsed.data.successActions)\n || hasOpenMercatoCallAction(parsed.data.failureActions)\n || hasOpenMercatoCallAction(rule.successActions)\n || hasOpenMercatoCallAction(rule.failureActions)\n if (touchesOpenMercatoCall) {\n const accessError = await requireOpenMercatoCallConfiguratorAccess(container, auth)\n if (accessError) return accessError\n }\n\n const actionErrors = [\n ...await validateOpenMercatoCallActions(em as EntityManager, parsed.data.successActions, {\n tenantId,\n organizationId,\n }),\n ...await validateOpenMercatoCallActions(em as EntityManager, parsed.data.failureActions, {\n tenantId,\n organizationId,\n }),\n ]\n if (actionErrors.length > 0) {\n return NextResponse.json({ error: `Validation failed: ${actionErrors.join(', ')}` }, { status: 400 })\n }\n\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'business_rules.rule',\n resourceId: rule.id,\n current: rule.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n throw err\n }\n\n em.assign(rule, parsed.data)\n\n try {\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n } catch (error) {\n logger.error('Failed to persist rule update', { err: error })\n return NextResponse.json(\n { error: t('business_rules.errors.updateFailed') },\n { status: 500 },\n )\n }\n\n return NextResponse.json({ ok: true })\n}\n\nexport async function DELETE(req: Request) {\n const auth = await getAuthFromRequest(req)\n if (!auth) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n const url = new URL(req.url)\n const id = url.searchParams.get('id')\n\n if (!id) {\n return NextResponse.json({ error: 'Rule id is required' }, { status: 400 })\n }\n\n const container = await createRequestContainer()\n const em = container.resolve('em') as EntityManager\n const cache = resolveBusinessRuleDiscoveryCache(container.resolve.bind(container))\n\n const rule = await em.findOne(BusinessRule, {\n id,\n tenantId: auth.tenantId,\n organizationId: auth.orgId,\n deletedAt: null,\n })\n\n if (!rule) {\n return NextResponse.json({ error: 'Rule not found' }, { status: 404 })\n }\n\n try {\n await enforceCommandOptimisticLockWithGuards(container, {\n resourceKind: 'business_rules.rule',\n resourceId: rule.id,\n current: rule.updatedAt ?? null,\n request: req,\n })\n } catch (err) {\n if (isCrudHttpError(err)) {\n return NextResponse.json(err.body, { status: err.status })\n }\n throw err\n }\n\n rule.deletedAt = new Date()\n await em.persist(rule).flush()\n await invalidateBusinessRuleDiscoveryCache(cache, rule.tenantId, rule.organizationId)\n\n return NextResponse.json({ ok: true })\n}\n\nexport const openApi: OpenApiRouteDoc = {\n tag: 'Business Rules',\n summary: 'Business rule management',\n methods: {\n GET: {\n summary: 'List business rules',\n description: 'Returns business rules for the current tenant and organization with filtering and pagination.',\n query: querySchema,\n responses: [\n { status: 200, description: 'Business rules collection', schema: ruleListResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid query parameters', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n POST: {\n summary: 'Create business rule',\n description: 'Creates a new business rule for the current tenant and organization.',\n requestBody: {\n contentType: 'application/json',\n schema: createBusinessRuleSchema,\n },\n responses: [\n {\n status: 201,\n description: 'Business rule created',\n schema: ruleCreateResponseSchema,\n },\n ],\n errors: [\n { status: 400, description: 'Invalid payload', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n ],\n },\n PUT: {\n summary: 'Update business rule',\n description: 'Updates an existing business rule.',\n requestBody: {\n contentType: 'application/json',\n schema: updateBusinessRuleSchema,\n },\n responses: [\n {\n status: 200,\n description: 'Business rule updated',\n schema: okResponseSchema,\n },\n ],\n errors: [\n { status: 400, description: 'Invalid payload', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 404, description: 'Business rule not found', schema: errorResponseSchema },\n ],\n },\n DELETE: {\n summary: 'Delete business rule',\n description: 'Soft deletes a business rule by identifier.',\n query: z.object({ id: z.string().uuid().describe('Business rule identifier') }),\n responses: [\n { status: 200, description: 'Business rule deleted', schema: okResponseSchema },\n ],\n errors: [\n { status: 400, description: 'Invalid identifier', schema: errorResponseSchema },\n { status: 401, description: 'Unauthorized', schema: errorResponseSchema },\n { status: 404, description: 'Business rule not found', schema: errorResponseSchema },\n ],\n },\n },\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -3,6 +3,7 @@ import { Fragment, jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Button } from "@open-mercato/ui/primitives/button";
|
|
5
5
|
import { Plus, Code } from "lucide-react";
|
|
6
|
+
import { apiCall } from "@open-mercato/ui/backend/utils/apiCall";
|
|
6
7
|
import { ActionRow } from "./ActionRow.js";
|
|
7
8
|
import { validateActions } from "./utils/actionValidation.js";
|
|
8
9
|
import { useT } from "@open-mercato/shared/lib/i18n/context";
|
|
@@ -18,7 +19,47 @@ function ActionBuilder({
|
|
|
18
19
|
const t = useT();
|
|
19
20
|
const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog();
|
|
20
21
|
const [showDebug, setShowDebug] = React.useState(false);
|
|
21
|
-
const
|
|
22
|
+
const [openMercatoOptions, setOpenMercatoOptions] = React.useState({
|
|
23
|
+
endpoints: [],
|
|
24
|
+
apiKeys: [],
|
|
25
|
+
loading: true,
|
|
26
|
+
error: null
|
|
27
|
+
});
|
|
28
|
+
const actions = React.useMemo(() => value || [], [value]);
|
|
29
|
+
React.useEffect(() => {
|
|
30
|
+
let cancelled = false;
|
|
31
|
+
async function loadOpenMercatoOptions() {
|
|
32
|
+
setOpenMercatoOptions((current) => ({ ...current, loading: true, error: null }));
|
|
33
|
+
try {
|
|
34
|
+
const response = await apiCall("/api/business_rules/openmercato-call-options");
|
|
35
|
+
if (!response.ok || !response.result) {
|
|
36
|
+
const error2 = response.result && "error" in response.result ? String(response.result.error) : t("business_rules.components.actionRow.openMercato.options.fetchFailed", { status: response.status });
|
|
37
|
+
throw new Error(error2);
|
|
38
|
+
}
|
|
39
|
+
if (!cancelled) {
|
|
40
|
+
setOpenMercatoOptions({
|
|
41
|
+
endpoints: Array.isArray(response.result.endpoints) ? response.result.endpoints : [],
|
|
42
|
+
apiKeys: Array.isArray(response.result.apiKeys) ? response.result.apiKeys : [],
|
|
43
|
+
loading: false,
|
|
44
|
+
error: null
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
} catch (error2) {
|
|
48
|
+
if (!cancelled) {
|
|
49
|
+
setOpenMercatoOptions({
|
|
50
|
+
endpoints: [],
|
|
51
|
+
apiKeys: [],
|
|
52
|
+
loading: false,
|
|
53
|
+
error: error2 instanceof Error ? error2.message : String(error2)
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
void loadOpenMercatoOptions();
|
|
59
|
+
return () => {
|
|
60
|
+
cancelled = true;
|
|
61
|
+
};
|
|
62
|
+
}, [t]);
|
|
22
63
|
const handleAddAction = () => {
|
|
23
64
|
const newAction = {
|
|
24
65
|
type: "",
|
|
@@ -74,11 +115,12 @@ function ActionBuilder({
|
|
|
74
115
|
] })
|
|
75
116
|
] }),
|
|
76
117
|
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: showJsonPreview && actions.length > 0 && /* @__PURE__ */ jsxs(
|
|
77
|
-
|
|
118
|
+
Button,
|
|
78
119
|
{
|
|
79
120
|
type: "button",
|
|
80
121
|
onClick: () => setShowDebug(!showDebug),
|
|
81
|
-
|
|
122
|
+
variant: "muted",
|
|
123
|
+
size: "2xs",
|
|
82
124
|
title: t("business_rules.components.actionBuilder.jsonPreview.toggle"),
|
|
83
125
|
children: [
|
|
84
126
|
/* @__PURE__ */ jsx(Code, { className: "w-3 h-3" }),
|
|
@@ -104,7 +146,8 @@ function ActionBuilder({
|
|
|
104
146
|
onMoveUp: index > 0 ? handleMoveUp : void 0,
|
|
105
147
|
onMoveDown: index < actions.length - 1 ? handleMoveDown : void 0,
|
|
106
148
|
canMoveUp: index > 0,
|
|
107
|
-
canMoveDown: index < actions.length - 1
|
|
149
|
+
canMoveDown: index < actions.length - 1,
|
|
150
|
+
openMercatoOptions
|
|
108
151
|
},
|
|
109
152
|
index
|
|
110
153
|
)) }),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../../src/modules/business_rules/components/ActionBuilder.tsx"],
|
|
4
|
-
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Plus, Code } from 'lucide-react'\nimport { ActionRow } from './ActionRow'\nimport type { Action } from './utils/actionValidation'\nimport { validateActions } from './utils/actionValidation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\nexport type ActionBuilderProps = {\n value: Action[] | null | undefined\n onChange: (value: Action[]) => void\n error?: string\n showJsonPreview?: boolean\n label?: string\n emptyMessage?: string\n}\n\nexport function ActionBuilder({\n value,\n onChange,\n error,\n showJsonPreview = false,\n label,\n emptyMessage,\n}: ActionBuilderProps) {\n const t = useT()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [showDebug, setShowDebug] = React.useState(false)\n const actions = value || []\n\n const handleAddAction = () => {\n const newAction: Action = {\n type: '',\n config: {},\n }\n onChange([...actions, newAction])\n }\n\n const handleChangeAction = (index: number, updatedAction: Action) => {\n const newActions = [...actions]\n newActions[index] = updatedAction\n onChange(newActions)\n }\n\n const handleDeleteAction = (index: number) => {\n const newActions = actions.filter((_, i) => i !== index)\n onChange(newActions)\n }\n\n const handleMoveUp = (index: number) => {\n if (index === 0) return\n const newActions = [...actions]\n const temp = newActions[index - 1]\n newActions[index - 1] = newActions[index]\n newActions[index] = temp\n onChange(newActions)\n }\n\n const handleMoveDown = (index: number) => {\n if (index === actions.length - 1) return\n const newActions = [...actions]\n const temp = newActions[index + 1]\n newActions[index + 1] = newActions[index]\n newActions[index] = temp\n onChange(newActions)\n }\n\n const handleClearAll = async () => {\n const confirmed = await confirmDialog({\n title: t('business_rules.components.actionBuilder.confirm.clearAll'),\n variant: 'destructive',\n })\n if (confirmed) {\n onChange([])\n }\n }\n\n // Validate actions (memoized to avoid expensive re-computation)\n const validation = React.useMemo(() => {\n return validateActions(actions, t)\n }, [actions, t])\n\n return (\n <div className=\"space-y-3\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium text-foreground\">\n {label || t('business_rules.components.actionBuilder.label')}\n </h3>\n {actions.length > 0 && (\n <span className=\"text-xs text-muted-foreground\">\n ({t('business_rules.components.actionBuilder.actionCount', { count: actions.length })})\n </span>\n )}\n </div>\n\n {/* Controls */}\n <div className=\"flex items-center gap-2\">\n {showJsonPreview && actions.length > 0 && (\n <
|
|
5
|
-
"mappings": ";
|
|
6
|
-
"names": []
|
|
4
|
+
"sourcesContent": ["\"use client\"\n\nimport * as React from 'react'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { Plus, Code } from 'lucide-react'\nimport { apiCall } from '@open-mercato/ui/backend/utils/apiCall'\nimport { ActionRow, type OpenMercatoCallOptionsState } from './ActionRow'\nimport type { Action } from './utils/actionValidation'\nimport { validateActions } from './utils/actionValidation'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\nimport type { OpenMercatoCallOptionsResponse } from '../lib/openmercato-call-options-types'\n\nexport type ActionBuilderProps = {\n value: Action[] | null | undefined\n onChange: (value: Action[]) => void\n error?: string\n showJsonPreview?: boolean\n label?: string\n emptyMessage?: string\n}\n\nexport function ActionBuilder({\n value,\n onChange,\n error,\n showJsonPreview = false,\n label,\n emptyMessage,\n}: ActionBuilderProps) {\n const t = useT()\n const { confirm: confirmDialog, ConfirmDialogElement } = useConfirmDialog()\n const [showDebug, setShowDebug] = React.useState(false)\n const [openMercatoOptions, setOpenMercatoOptions] = React.useState<OpenMercatoCallOptionsState>({\n endpoints: [],\n apiKeys: [],\n loading: true,\n error: null,\n })\n const actions = React.useMemo(() => value || [], [value])\n\n React.useEffect(() => {\n let cancelled = false\n\n async function loadOpenMercatoOptions() {\n setOpenMercatoOptions((current) => ({ ...current, loading: true, error: null }))\n try {\n const response = await apiCall<OpenMercatoCallOptionsResponse>('/api/business_rules/openmercato-call-options')\n if (!response.ok || !response.result) {\n const error = response.result && 'error' in response.result\n ? String((response.result as any).error)\n : t('business_rules.components.actionRow.openMercato.options.fetchFailed', { status: response.status })\n throw new Error(error)\n }\n if (!cancelled) {\n setOpenMercatoOptions({\n endpoints: Array.isArray(response.result.endpoints) ? response.result.endpoints : [],\n apiKeys: Array.isArray(response.result.apiKeys) ? response.result.apiKeys : [],\n loading: false,\n error: null,\n })\n }\n } catch (error) {\n if (!cancelled) {\n setOpenMercatoOptions({\n endpoints: [],\n apiKeys: [],\n loading: false,\n error: error instanceof Error ? error.message : String(error),\n })\n }\n }\n }\n\n void loadOpenMercatoOptions()\n return () => {\n cancelled = true\n }\n }, [t])\n\n const handleAddAction = () => {\n const newAction: Action = {\n type: '',\n config: {},\n }\n onChange([...actions, newAction])\n }\n\n const handleChangeAction = (index: number, updatedAction: Action) => {\n const newActions = [...actions]\n newActions[index] = updatedAction\n onChange(newActions)\n }\n\n const handleDeleteAction = (index: number) => {\n const newActions = actions.filter((_, i) => i !== index)\n onChange(newActions)\n }\n\n const handleMoveUp = (index: number) => {\n if (index === 0) return\n const newActions = [...actions]\n const temp = newActions[index - 1]\n newActions[index - 1] = newActions[index]\n newActions[index] = temp\n onChange(newActions)\n }\n\n const handleMoveDown = (index: number) => {\n if (index === actions.length - 1) return\n const newActions = [...actions]\n const temp = newActions[index + 1]\n newActions[index + 1] = newActions[index]\n newActions[index] = temp\n onChange(newActions)\n }\n\n const handleClearAll = async () => {\n const confirmed = await confirmDialog({\n title: t('business_rules.components.actionBuilder.confirm.clearAll'),\n variant: 'destructive',\n })\n if (confirmed) {\n onChange([])\n }\n }\n\n // Validate actions (memoized to avoid expensive re-computation)\n const validation = React.useMemo(() => {\n return validateActions(actions, t)\n }, [actions, t])\n\n return (\n <div className=\"space-y-3\">\n {/* Header */}\n <div className=\"flex items-center justify-between\">\n <div className=\"flex items-center gap-2\">\n <h3 className=\"text-sm font-medium text-foreground\">\n {label || t('business_rules.components.actionBuilder.label')}\n </h3>\n {actions.length > 0 && (\n <span className=\"text-xs text-muted-foreground\">\n ({t('business_rules.components.actionBuilder.actionCount', { count: actions.length })})\n </span>\n )}\n </div>\n\n {/* Controls */}\n <div className=\"flex items-center gap-2\">\n {showJsonPreview && actions.length > 0 && (\n <Button\n type=\"button\"\n onClick={() => setShowDebug(!showDebug)}\n variant=\"muted\"\n size=\"2xs\"\n title={t('business_rules.components.actionBuilder.jsonPreview.toggle')}\n >\n <Code className=\"w-3 h-3\" />\n {showDebug\n ? t('business_rules.components.actionBuilder.jsonPreview.hide')\n : t('business_rules.components.actionBuilder.jsonPreview.show')\n }\n </Button>\n )}\n </div>\n </div>\n\n {/* Empty State */}\n {actions.length === 0 ? (\n <div className=\"flex flex-col items-center justify-center p-8 border-2 border-dashed border-border rounded-lg bg-muted\">\n <p className=\"text-sm text-muted-foreground mb-4\">\n {emptyMessage || t('business_rules.components.actionBuilder.emptyMessage')}\n </p>\n <Button type=\"button\" onClick={handleAddAction} variant=\"outline\" size=\"sm\">\n <Plus className=\"w-4 h-4 mr-2\" />\n {t('business_rules.components.actionBuilder.addAction')}\n </Button>\n </div>\n ) : (\n <>\n {/* Action List */}\n <div className=\"space-y-2\">\n {actions.map((action, index) => (\n <ActionRow\n key={index}\n action={action}\n index={index}\n onChange={handleChangeAction}\n onDelete={handleDeleteAction}\n onMoveUp={index > 0 ? handleMoveUp : undefined}\n onMoveDown={index < actions.length - 1 ? handleMoveDown : undefined}\n canMoveUp={index > 0}\n canMoveDown={index < actions.length - 1}\n openMercatoOptions={openMercatoOptions}\n />\n ))}\n </div>\n\n {/* Add More / Clear All */}\n <div className=\"flex items-center justify-between\">\n <Button type=\"button\" onClick={handleAddAction} variant=\"outline\" size=\"sm\">\n <Plus className=\"w-4 h-4 mr-2\" />\n {t('business_rules.components.actionBuilder.addAction')}\n </Button>\n {actions.length > 1 && (\n <Button type=\"button\" onClick={handleClearAll} variant=\"outline\" size=\"sm\" className=\"text-status-error-text\">\n {t('business_rules.components.actionBuilder.clearAll')}\n </Button>\n )}\n </div>\n </>\n )}\n\n {/* Validation Errors */}\n {!validation.valid && (\n <div className=\"p-3 bg-status-error-bg border border-status-error-border rounded\">\n <p className=\"text-sm font-medium text-status-error-text mb-1\">\n {t('business_rules.components.actionBuilder.validationErrors')}\n </p>\n <ul className=\"list-disc list-inside space-y-0.5\">\n {validation.errors.map((err, index) => (\n <li key={index} className=\"text-xs text-status-error-text\">\n {err}\n </li>\n ))}\n </ul>\n </div>\n )}\n\n {/* External Error */}\n {error && (\n <div className=\"p-3 bg-status-error-bg border border-status-error-border rounded\">\n <p className=\"text-sm text-status-error-text\">{error}</p>\n </div>\n )}\n\n {/* JSON Preview */}\n {showDebug && actions.length > 0 && (\n <div className=\"p-3 bg-zinc-900 dark:bg-zinc-950 rounded text-xs font-mono overflow-x-auto border border-border\">\n <pre className=\"text-zinc-100\">{JSON.stringify(actions, null, 2)}</pre>\n </div>\n )}\n\n {/* Help Text */}\n {actions.length > 0 && (\n <div className=\"text-xs text-muted-foreground space-y-1\">\n <p>\n <strong>{t('business_rules.components.actionBuilder.help.actionOrder')}</strong>{' '}\n {t('business_rules.components.actionBuilder.help.actionOrderDescription')}\n </p>\n <p>\n <strong>{t('business_rules.components.actionBuilder.help.messageInterpolation')}</strong>{' '}\n {t('business_rules.components.actionBuilder.help.messageInterpolationDescription')}\n </p>\n </div>\n )}\n {ConfirmDialogElement}\n </div>\n )\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["error"]
|
|
7
7
|
}
|