@infuro/cms-core 1.0.33 → 1.0.35
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/README.md +22 -6
- package/dist/OrderTrackPage-W3J6WIG2.js +426 -0
- package/dist/OrderTrackPage-Z6FCJQYY.cjs +428 -0
- package/dist/admin.cjs +34072 -20487
- package/dist/admin.d.cts +191 -9
- package/dist/admin.d.ts +191 -9
- package/dist/admin.js +33913 -20423
- package/dist/api.cjs +123 -16508
- package/dist/api.d.cts +633 -3
- package/dist/api.d.ts +633 -3
- package/dist/api.js +14 -16519
- package/dist/auth.cjs +196 -955
- package/dist/auth.d.cts +201 -42
- package/dist/auth.d.ts +201 -42
- package/dist/auth.js +4 -888
- package/dist/chunk-2XE4X74C.js +29602 -0
- package/dist/chunk-3DZRIZOD.cjs +52 -0
- package/dist/chunk-3KPNTQBV.cjs +620 -0
- package/dist/chunk-46GKADYE.cjs +84 -0
- package/dist/chunk-4TRPKBKO.js +589 -0
- package/dist/chunk-5ELSW2UP.js +150 -0
- package/dist/chunk-6KPQWRFW.js +171 -0
- package/dist/chunk-7NMT3GBR.cjs +29 -0
- package/dist/chunk-7YIBMQDR.cjs +86 -0
- package/dist/chunk-BGJAV67S.cjs +29710 -0
- package/dist/chunk-CNTSLED2.cjs +559 -0
- package/dist/chunk-CRFV5WJK.js +16 -0
- package/dist/chunk-D5FBNKQM.cjs +104 -0
- package/dist/chunk-EF2JBPDM.js +114 -0
- package/dist/chunk-EQPITOP6.js +543 -0
- package/dist/chunk-GO7PPYNU.js +76 -0
- package/dist/chunk-HF3L2GIT.cjs +194 -0
- package/dist/chunk-J7XHLOLO.js +830 -0
- package/dist/chunk-JBRR5UYL.js +87 -0
- package/dist/chunk-JC6DLWTE.js +21 -0
- package/dist/chunk-JHF4YYRC.cjs +188 -0
- package/dist/chunk-JXF23MPG.js +25 -0
- package/dist/chunk-MQBT33IV.js +48 -0
- package/dist/chunk-N44BJZ4C.cjs +123 -0
- package/dist/chunk-OOTLNH63.cjs +18 -0
- package/dist/chunk-PAMVINEX.cjs +577 -0
- package/dist/chunk-PNOKNSG2.cjs +222 -0
- package/dist/chunk-QM733NUK.js +186 -0
- package/dist/chunk-R73BKDRO.cjs +90 -0
- package/dist/chunk-SHUYVCID.js +4 -0
- package/dist/chunk-SYBOCAWB.js +97 -0
- package/dist/chunk-TDV6EJHV.js +192 -0
- package/dist/chunk-TFUOHI37.cjs +839 -0
- package/dist/chunk-TIAEXJLI.cjs +182 -0
- package/dist/chunk-UPLVMVRX.cjs +23 -0
- package/dist/chunk-USNT2KNT.cjs +6 -0
- package/dist/chunk-WEMDMVHQ.js +216 -0
- package/dist/chunk-XDSNZUW7.js +564 -0
- package/dist/chunk-XQ3QUHWR.cjs +83 -0
- package/dist/chunk-XW5ATPRW.cjs +155 -0
- package/dist/chunk-ZQ4X6OAU.js +82 -0
- package/dist/chunk-ZSVCP6N3.js +83 -0
- package/dist/cli.cjs +142 -84
- package/dist/cli.js +101 -27
- package/dist/email-FKR4FXFI.js +5 -0
- package/dist/email-KVKVPNCL.cjs +58 -0
- package/dist/email-queue-CGZBVVAS.js +2 -0
- package/dist/email-queue-TPZWLTIV.cjs +23 -0
- package/dist/erp-config-enabled-CUMQ6N2V.cjs +11 -0
- package/dist/erp-config-enabled-T37X7T34.js +2 -0
- package/dist/erp-order-invoice-3YISSOWW.js +3 -0
- package/dist/erp-order-invoice-ZR5F2KTA.cjs +12 -0
- package/dist/event-order-defaults-6E543227.js +2 -0
- package/dist/event-order-defaults-DUGDVGJI.cjs +39 -0
- package/dist/event-order-notifications-5GSAOYVS.cjs +27 -0
- package/dist/event-order-notifications-IIIF23D5.js +10 -0
- package/dist/hooks.cjs +259 -132
- package/dist/hooks.d.cts +42 -1
- package/dist/hooks.d.ts +42 -1
- package/dist/hooks.js +234 -91
- package/dist/index.cjs +3884 -21070
- package/dist/index.d.cts +2255 -749
- package/dist/index.d.ts +2255 -749
- package/dist/index.js +1925 -19891
- package/dist/interpolate-WAKPN56R.cjs +11 -0
- package/dist/interpolate-WDUWDF3I.js +2 -0
- package/dist/layout-36UFTHC5.cjs +11 -0
- package/dist/layout-AOBN26XG.js +2 -0
- package/dist/migrations/1778660000004-CreateCustomerAndCustomerContacts.ts +99 -0
- package/dist/migrations/1778660000005-AddCustomerIdToVendorCustomers.ts +39 -0
- package/dist/migrations/1778660000006-UpdateVendorCustomersContactNullable.ts +36 -0
- package/dist/migrations/1778660000007-VendorOwnerCustomerContactsPermission.ts +39 -0
- package/dist/migrations/1779300000000-VendorOwnerContactsPermission.ts +39 -0
- package/dist/migrations/1779400000000-AddCustomerContactIdToOrders.ts +33 -0
- package/dist/migrations/1779400000000-ConvertStatusToEnum.ts +142 -0
- package/dist/migrations/1779400000000-SeedDefaultCurrencies.ts +33 -0
- package/dist/migrations/1779500000000-VendorRolesAndPermissions.ts +102 -0
- package/dist/migrations/1779600000000-VendorRegistrationProfile.ts +52 -0
- package/dist/migrations/1779700000000-CollectionIsCatalog.ts +22 -0
- package/dist/migrations/1779710000000-CollectionPlatformCatalog.ts +60 -0
- package/dist/migrations/1779720000000-ProductCategoryPlatformCatalog.ts +157 -0
- package/dist/migrations/1779800000000-EventsAndEventProducts.ts +173 -0
- package/dist/migrations/1779810000000-BackfillVendorRoleEventsPermissions.ts +38 -0
- package/dist/migrations/1779820000000-FixProductsCategoryForeignKey.ts +70 -0
- package/dist/migrations/1779830000000-ProductTitleColumn.ts +32 -0
- package/dist/migrations/1779840000000-EventAboutAndVisibilityFields.ts +34 -0
- package/dist/migrations/1779850000000-EventCityCountrySplit.ts +43 -0
- package/dist/migrations/1779860000000-CreateCombos.ts +140 -0
- package/dist/migrations/1780100000000-OrderAttendeesEventId.ts +55 -0
- package/dist/migrations/1780110000000-EventContactFormId.ts +49 -0
- package/dist/migrations/1780130000000-ProductVariants.ts +54 -0
- package/dist/migrations/1780140000000-EventManagementEnhancements.ts +44 -0
- package/dist/migrations/1780160000000-EventRegistrationGstProductContactForm.ts +79 -0
- package/dist/migrations/1780170000000-ComboCurrencyPrices.ts +20 -0
- package/dist/migrations/1781110000000-VendorOwnerCombosPermission.ts +38 -0
- package/dist/migrations/1781120000000-RefundPoliciesAndRequests.ts +225 -0
- package/dist/migrations/1781130000000-CreateAttendees.ts +44 -0
- package/dist/migrations/1781140000000-EventOrderNotifications.ts +29 -0
- package/dist/migrations/1781150000000-EventNamedLists.ts +28 -0
- package/dist/migrations/1781160000000-RefundPolicyEventTiers.ts +27 -0
- package/dist/migrations/1781170000000-EventRefundPolicy.ts +42 -0
- package/dist/migrations/1781180000000-RemoveCartItemsUniqueConstraint.ts +15 -0
- package/dist/migrations/1781190000000-RenameProductTaxesToProductConfig.ts +84 -0
- package/dist/migrations/1781200000000-VendorOwnerProductConfigPermissions.ts +51 -0
- package/dist/migrations/1781210000000-VendorRoleProductConfigPermissions.ts +46 -0
- package/dist/migrations/helpers/vendor-role-seed.ts +243 -0
- package/dist/paid-order-erp-3USEG6WL.js +3 -0
- package/dist/paid-order-erp-FSQ3GSXE.cjs +12 -0
- package/dist/pg-boss-service-4XF2TQ2E.js +2 -0
- package/dist/pg-boss-service-L6MTF4EQ.cjs +15 -0
- package/dist/razorpay-KLO2KNCB.js +49 -0
- package/dist/razorpay-U23LGY72.cjs +56 -0
- package/dist/rbac-debug-db-D7ME7QUY.cjs +35 -0
- package/dist/rbac-debug-db-MTCTVNNM.js +33 -0
- package/dist/sms-defaults-2NL24H57.js +2 -0
- package/dist/sms-defaults-KCOPKQBA.cjs +19 -0
- package/dist/stripe-4FD27QVJ.js +51 -0
- package/dist/stripe-VU6OEG2D.cjs +57 -0
- package/dist/theme.cjs +31 -59
- package/dist/theme.d.cts +78 -3
- package/dist/theme.d.ts +78 -3
- package/dist/theme.js +23 -20
- package/dist/vendor-invite-status-77O7ZQ3U.cjs +19 -0
- package/dist/vendor-invite-status-PWJ3DE76.js +2 -0
- package/dist/whatsapp-queue-3DXA4MXU.js +2 -0
- package/dist/whatsapp-queue-KG65MXD5.cjs +15 -0
- package/package.json +147 -141
- package/dist/admin.cjs.map +0 -1
- package/dist/admin.js.map +0 -1
- package/dist/api.cjs.map +0 -1
- package/dist/api.js.map +0 -1
- package/dist/auth.cjs.map +0 -1
- package/dist/auth.js.map +0 -1
- package/dist/cli.cjs.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/config-DJ5CmQvS.d.cts +0 -8
- package/dist/config-DJ5CmQvS.d.ts +0 -8
- package/dist/hooks.cjs.map +0 -1
- package/dist/hooks.js.map +0 -1
- package/dist/index-DWd5Gjc4.d.ts +0 -582
- package/dist/index-rZTnpK7y.d.cts +0 -582
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/theme.cjs.map +0 -1
- package/dist/theme.js.map +0 -1
- package/dist/types-DCVaXlPV.d.cts +0 -78
- package/dist/types-DCVaXlPV.d.ts +0 -78
- package/dist/vendor-scope-DTYhJk_I.d.cts +0 -129
- package/dist/vendor-scope-DTYhJk_I.d.ts +0 -129
package/dist/index.d.cts
CHANGED
|
@@ -1,18 +1,10 @@
|
|
|
1
|
-
import { e as CompanyDetails, T as TemplateContext, h as EmailTemplateResult, g as EmailTemplateName, O as OrderPlacedLineItem, o as StorageService, i as EntityMap$2 } from './index-rZTnpK7y.cjs';
|
|
2
|
-
export { A as AnalyticsHandlerConfig, a as AuthHandlersConfig, B as BlogBySlugConfig, C as ChangePasswordConfig, b as ChatPublicConfig, c as CmsApiHandlerConfig, d as CmsGetter, f as CrudHandlerOptions, D as DashboardStatsConfig, E as EcommerceAnalyticsConfig, F as ForgotPasswordConfig, j as FormBySlugConfig, G as GetPublicSettingsGroupConfig, k as GetPublicSettingsGroupDataSource, I as InviteAcceptConfig, J as JobScheduleApiConfig, L as LlmAgentKnowledgeApiConfig, l as LlmAgentValidationRulesJson, P as ParsedLlmAgentValidation, S as SetPasswordConfig, m as SettingsApiConfig, n as SocialLinkItem, p as StorefrontApiConfig, q as StorefrontOtpFlags, U as UploadHandlerConfig, r as UserAuthApiConfig, s as UserAvatarConfig, t as UserProfileConfig, u as UsersApiConfig, V as VendorOnboardHandlersConfig, v as VendorOwnerActivation, w as createAnalyticsHandlers, x as createBlogBySlugHandler, y as createChangePasswordHandler, z as createCmsApiHandler, H as createCrudByIdHandler, K as createCrudHandler, M as createDashboardStatsHandler, N as createEcommerceAnalyticsHandler, Q as createForgotPasswordHandler, R as createFormBySlugHandler, W as createInviteAcceptHandler, X as createJobScheduleHandlers, Y as createLlmAgentKnowledgeHandlers, Z as createMediaZipExtractHandler, _ as createSetPasswordHandler, $ as createSettingsApiHandlers, a0 as createStorefrontApiHandler, a1 as createUploadHandler, a2 as createUserAuthApiRouter, a3 as createUserAvatarHandler, a4 as createUserProfileHandler, a5 as createUsersApiHandlers, a6 as createVendorOnboardHandlers, a7 as getCompanyDetailsFromSettings, a8 as getPublicSettingsGroup, a9 as mergeEmailLayoutCompanyDetails, aa as mergeGuardrailsIntoSystemPrompt, ab as parseLlmAgentValidationRules, ac as simpleDecrypt, ad as simpleEncrypt, ae as validateUserMessageAgainstAgentRules, af as validateUserMessageAgainstStructuredRules } from './index-rZTnpK7y.cjs';
|
|
3
1
|
import PgBoss from 'pg-boss';
|
|
4
2
|
import * as typeorm from 'typeorm';
|
|
5
|
-
import { DataSource, EntityTarget, ObjectLiteral, SelectQueryBuilder } from 'typeorm';
|
|
3
|
+
import { DataSource, EntityTarget, ObjectLiteral, EntityManager, SelectQueryBuilder } from 'typeorm';
|
|
6
4
|
import { ClassValue } from 'clsx';
|
|
7
5
|
import { Metadata } from 'next';
|
|
8
|
-
import {
|
|
9
|
-
|
|
10
|
-
import { E as EntityCrudAction, S as SessionUser, e as VendorScope } from './vendor-scope-DTYhJk_I.cjs';
|
|
11
|
-
export { A as ADMIN_GROUP_NAME, a as AuthHelpers, b as EntityPermissionFlags, G as GetSession, O as OPEN_ENDPOINTS, P as PERMISSION_REQUIRED_ENDPOINTS, R as RBAC_ADMIN_ONLY_ENTITIES, V as VENDOR_OWNER_GROUP_NAME, c as VENDOR_SCOPED_STORE_ENTITIES, d as VENDOR_STORE_RBAC_ENTITIES, f as canManageRoles, g as canManageVendorRoles, h as canManageVendorTeam, i as canOnboardVendors, j as createAuthHelpers, k as createCmsAuthBundle, l as getPermissionableEntityKeys, m as getRequiredPermission, n as hasEntityPermission, o as isOpenEndpoint, p as isPlatformAdministrator, q as isPublicMethod, r as isSuperAdminGroupName, s as isVendorGroupName, t as isVendorOwner, u as isVendorPortalUser, v as isVendorStaff, w as permissionRowsToRecord, x as resolveVendorScopeFromSessionUser, y as sessionHasEntityAccess, z as vendorPortalFlagsFromUser } from './vendor-scope-DTYhJk_I.cjs';
|
|
12
|
-
import { a as NavbarConfig, F as FooterConfig } from './types-DCVaXlPV.cjs';
|
|
13
|
-
export { A as AdminNavItem, D as DEFAULT_ADMIN_NAV } from './config-DJ5CmQvS.cjs';
|
|
14
|
-
import 'next-auth/jwt';
|
|
15
|
-
import 'next-auth';
|
|
6
|
+
import { NextAuthOptions } from 'next-auth';
|
|
7
|
+
import { getToken } from 'next-auth/jwt';
|
|
16
8
|
|
|
17
9
|
interface PluginContext {
|
|
18
10
|
dataSource: unknown;
|
|
@@ -126,7 +118,7 @@ declare class ERPSubmissionService {
|
|
|
126
118
|
}[]): ContactFormData | null;
|
|
127
119
|
}
|
|
128
120
|
|
|
129
|
-
interface CmsAppLike$
|
|
121
|
+
interface CmsAppLike$4 {
|
|
130
122
|
getPlugin(name: string): unknown;
|
|
131
123
|
}
|
|
132
124
|
type ErpJobPayload = {
|
|
@@ -145,8 +137,8 @@ type ErpJobPayload = {
|
|
|
145
137
|
kind: 'productUpsert';
|
|
146
138
|
product: Record<string, unknown>;
|
|
147
139
|
};
|
|
148
|
-
declare function queueErp(cms: CmsAppLike$
|
|
149
|
-
declare function registerErpQueueProcessor(cms: CmsAppLike$
|
|
140
|
+
declare function queueErp(cms: CmsAppLike$4, payload: ErpJobPayload): Promise<void>;
|
|
141
|
+
declare function registerErpQueueProcessor(cms: CmsAppLike$4): void;
|
|
150
142
|
|
|
151
143
|
/**
|
|
152
144
|
* Duck-typed DataSource so host apps (e.g. Next) can pass their own TypeORM instance
|
|
@@ -167,7 +159,7 @@ type ErpPaidOrderEntityMap = Record<string, unknown>;
|
|
|
167
159
|
* Enqueues ERP `order.created` only when the order has at least one **completed** payment.
|
|
168
160
|
* Include `payments` in the payload.
|
|
169
161
|
*/
|
|
170
|
-
declare function queueErpPaidOrderForOrderId(cms: CmsAppLike$
|
|
162
|
+
declare function queueErpPaidOrderForOrderId(cms: CmsAppLike$4, dataSource: ErpPaidOrderDataSource, entityMap: ErpPaidOrderEntityMap, orderId: number): Promise<void>;
|
|
171
163
|
|
|
172
164
|
interface ErpContactSyncInput {
|
|
173
165
|
name: string;
|
|
@@ -183,7 +175,7 @@ interface ErpContactSyncInput {
|
|
|
183
175
|
* When ERP is enabled and plugin loaded, enqueue `create-contact` (non-fatal on failure).
|
|
184
176
|
* Used for admin CRUD and storefront contact paths — not form submissions (those use lead/opportunity).
|
|
185
177
|
*/
|
|
186
|
-
declare function queueErpCreateContactIfEnabled(cms: CmsAppLike$
|
|
178
|
+
declare function queueErpCreateContactIfEnabled(cms: CmsAppLike$4, dataSource: ErpPaidOrderDataSource, entityMap: ErpPaidOrderEntityMap, input: ErpContactSyncInput): Promise<void>;
|
|
187
179
|
|
|
188
180
|
interface ERPPluginConfig {
|
|
189
181
|
webhookUrl: string;
|
|
@@ -195,6 +187,47 @@ interface ERPPluginInstance {
|
|
|
195
187
|
}
|
|
196
188
|
declare function erpPlugin(config: ERPPluginConfig): CmsPlugin<ERPPluginInstance>;
|
|
197
189
|
|
|
190
|
+
/** Social entry: use `iconUrl` for an image, or `icon` (emoji/text) as fallback when no image. */
|
|
191
|
+
interface SocialLinkItem {
|
|
192
|
+
url: string;
|
|
193
|
+
iconUrl?: string;
|
|
194
|
+
icon?: string;
|
|
195
|
+
}
|
|
196
|
+
interface CompanyDetails {
|
|
197
|
+
logoUrl?: string;
|
|
198
|
+
companyName?: string;
|
|
199
|
+
supportEmail?: string;
|
|
200
|
+
supportPhone?: string;
|
|
201
|
+
socialLinks?: SocialLinkItem[];
|
|
202
|
+
/** Shown below footer rows; from email plugin settings */
|
|
203
|
+
footerDisclaimer?: string;
|
|
204
|
+
/** Heading above social icons (default "Follow Us") */
|
|
205
|
+
followUsTitle?: string;
|
|
206
|
+
}
|
|
207
|
+
/** One row in order-placed transactional emails */
|
|
208
|
+
interface OrderPlacedLineItem {
|
|
209
|
+
productName: string;
|
|
210
|
+
quantity: number;
|
|
211
|
+
unitPrice: number | string;
|
|
212
|
+
lineTotal: number | string;
|
|
213
|
+
sku?: string | null;
|
|
214
|
+
tax?: number | string | null;
|
|
215
|
+
hsn?: string | null;
|
|
216
|
+
}
|
|
217
|
+
/** Merge branding + email plugin settings for layout (email overrides when set). */
|
|
218
|
+
declare function mergeEmailLayoutCompanyDetails(branding: Record<string, string>, emailSettings: Record<string, string>): CompanyDetails;
|
|
219
|
+
interface EmailTemplateResult {
|
|
220
|
+
subject: string;
|
|
221
|
+
bodyHtml: string;
|
|
222
|
+
text?: string;
|
|
223
|
+
}
|
|
224
|
+
type TemplateContext<T = unknown> = T & {
|
|
225
|
+
companyDetails: CompanyDetails;
|
|
226
|
+
};
|
|
227
|
+
declare const EMAIL_TEMPLATE_NAMES: readonly ["signup", "passwordReset", "passwordChange", "orderPlaced", "returnInitiated", "shippingUpdate", "invite", "formSubmission", "otp", "chatLead", "vendorOnboarded"];
|
|
228
|
+
type EmailTemplateName = (typeof EMAIL_TEMPLATE_NAMES)[number];
|
|
229
|
+
declare function getCompanyDetailsFromSettings(settingsGroup: Record<string, string>): CompanyDetails;
|
|
230
|
+
|
|
198
231
|
interface RenderEmailOptions {
|
|
199
232
|
renderLayout?: (opts: {
|
|
200
233
|
bodyHtml: string;
|
|
@@ -220,6 +253,7 @@ interface EmailPluginConfig$1 {
|
|
|
220
253
|
port?: number;
|
|
221
254
|
secure?: boolean;
|
|
222
255
|
region?: string;
|
|
256
|
+
/** IAM keys for SES API (SendEmail). Not the same as SES SMTP credentials in SMTP_USER/SMTP_PASSWORD. */
|
|
223
257
|
accessKeyId?: string;
|
|
224
258
|
secretAccessKey?: string;
|
|
225
259
|
templateOptions?: RenderEmailOptions;
|
|
@@ -244,6 +278,8 @@ declare class EmailService implements EmailServiceInterface {
|
|
|
244
278
|
private templateOptions?;
|
|
245
279
|
private sesClient?;
|
|
246
280
|
private transporter?;
|
|
281
|
+
/** AWS via SMTP (nodemailer) vs SES API SDK. */
|
|
282
|
+
private awsViaSmtp;
|
|
247
283
|
constructor(config: EmailPluginConfig$1);
|
|
248
284
|
send(emailData: EmailData): Promise<boolean>;
|
|
249
285
|
renderTemplate(templateName: EmailTemplateName, ctx: TemplateContext<unknown>): RenderedEmail;
|
|
@@ -285,7 +321,7 @@ declare function renderLayout(options: {
|
|
|
285
321
|
companyDetails: CompanyDetails;
|
|
286
322
|
}): string;
|
|
287
323
|
|
|
288
|
-
interface CmsAppLike$
|
|
324
|
+
interface CmsAppLike$3 {
|
|
289
325
|
getPlugin(name: string): unknown;
|
|
290
326
|
}
|
|
291
327
|
/** Context for template rendering: at least companyDetails; template-specific fields (formName, etc.) are allowed. */
|
|
@@ -299,8 +335,8 @@ interface EmailJobPayload {
|
|
|
299
335
|
html?: string;
|
|
300
336
|
text?: string;
|
|
301
337
|
}
|
|
302
|
-
declare function registerEmailQueueProcessor(cms: CmsAppLike$
|
|
303
|
-
declare function queueEmail(cms: CmsAppLike$
|
|
338
|
+
declare function registerEmailQueueProcessor(cms: CmsAppLike$3): void;
|
|
339
|
+
declare function queueEmail(cms: CmsAppLike$3, payload: EmailJobPayload): Promise<void>;
|
|
304
340
|
interface OrderPlacedEmailPayload {
|
|
305
341
|
orderNumber: string;
|
|
306
342
|
total?: string | number;
|
|
@@ -318,7 +354,22 @@ interface OrderPlacedEmailPayload {
|
|
|
318
354
|
shippingAddress?: Record<string, string>;
|
|
319
355
|
}
|
|
320
356
|
/** Queues one `orderPlaced` email per recipient (customer + each unique sales address; skips sales if same as customer). */
|
|
321
|
-
declare function queueOrderPlacedEmails(cms: CmsAppLike$
|
|
357
|
+
declare function queueOrderPlacedEmails(cms: CmsAppLike$3, payload: OrderPlacedEmailPayload): Promise<void>;
|
|
358
|
+
interface VendorOnboardEmailPayload {
|
|
359
|
+
vendorName: string;
|
|
360
|
+
vendorSlug?: string;
|
|
361
|
+
ownerName: string;
|
|
362
|
+
ownerEmail: string;
|
|
363
|
+
activation: 'invite' | 'password';
|
|
364
|
+
inviteLink?: string;
|
|
365
|
+
signInLink: string;
|
|
366
|
+
kind?: 'vendor_onboard' | 'team_invite';
|
|
367
|
+
notifyEmails: string[];
|
|
368
|
+
companyDetails: CompanyDetails;
|
|
369
|
+
sendToOwner?: boolean;
|
|
370
|
+
}
|
|
371
|
+
/** Queues `vendorOnboarded` email to owner and each unique notify address (sales team settings). */
|
|
372
|
+
declare function queueVendorOnboardEmails(cms: CmsAppLike$3, payload: VendorOnboardEmailPayload): Promise<void>;
|
|
322
373
|
|
|
323
374
|
interface EmailPluginConfig {
|
|
324
375
|
type: 'AWS' | 'SMTP' | 'GMAIL' | 'SENDGRID';
|
|
@@ -386,7 +437,7 @@ interface AnalyticsPluginConfig {
|
|
|
386
437
|
}
|
|
387
438
|
declare function analyticsPlugin(config?: AnalyticsPluginConfig): CmsPlugin<AnalyticsService>;
|
|
388
439
|
|
|
389
|
-
type MessageTemplateRowLoader = (channel: string, templateKey: string) => Promise<{
|
|
440
|
+
type MessageTemplateRowLoader$1 = (channel: string, templateKey: string) => Promise<{
|
|
390
441
|
body: string;
|
|
391
442
|
externalTemplateRef: string | null;
|
|
392
443
|
providerMeta: Record<string, unknown> | null;
|
|
@@ -426,7 +477,7 @@ interface SmsServiceConfig {
|
|
|
426
477
|
webhookSecret?: string;
|
|
427
478
|
}
|
|
428
479
|
|
|
429
|
-
interface CmsAppLike$
|
|
480
|
+
interface CmsAppLike$2 {
|
|
430
481
|
getPlugin(name: string): unknown;
|
|
431
482
|
}
|
|
432
483
|
interface SmsJobPayload {
|
|
@@ -437,14 +488,14 @@ interface SmsJobPayload {
|
|
|
437
488
|
variables?: Record<string, string>;
|
|
438
489
|
otpCode?: string;
|
|
439
490
|
}
|
|
440
|
-
declare function registerSmsQueueProcessor(cms: CmsAppLike$
|
|
441
|
-
declare function queueSms(cms: CmsAppLike$
|
|
491
|
+
declare function registerSmsQueueProcessor(cms: CmsAppLike$2): void;
|
|
492
|
+
declare function queueSms(cms: CmsAppLike$2, payload: SmsJobPayload): Promise<void>;
|
|
442
493
|
|
|
443
494
|
interface SmsPluginConfig extends Partial<SmsServiceConfig> {
|
|
444
495
|
/** Load admin settings group `sms` (enabled, smsProvider). Secrets typically stay in env. */
|
|
445
496
|
getSmsSettings?: () => Promise<Record<string, string>>;
|
|
446
497
|
/** Resolve `message_templates` rows for SMS (required for `templateKey` sends). */
|
|
447
|
-
getMessageTemplateRow?: MessageTemplateRowLoader;
|
|
498
|
+
getMessageTemplateRow?: MessageTemplateRowLoader$1;
|
|
448
499
|
}
|
|
449
500
|
interface SmsServiceInterface {
|
|
450
501
|
send(opts: {
|
|
@@ -457,6 +508,47 @@ interface SmsServiceInterface {
|
|
|
457
508
|
}
|
|
458
509
|
declare function smsPlugin(config?: SmsPluginConfig): CmsPlugin<SmsServiceInterface | null>;
|
|
459
510
|
|
|
511
|
+
type MessageTemplateRowLoader = (channel: string, templateKey: string) => Promise<{
|
|
512
|
+
body: string;
|
|
513
|
+
externalTemplateRef: string | null;
|
|
514
|
+
enabled: boolean;
|
|
515
|
+
} | null>;
|
|
516
|
+
interface WhatsAppServiceConfig {
|
|
517
|
+
accessToken?: string;
|
|
518
|
+
phoneNumberId?: string;
|
|
519
|
+
apiVersion?: string;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
interface CmsAppLike$1 {
|
|
523
|
+
getPlugin(name: string): unknown;
|
|
524
|
+
}
|
|
525
|
+
interface WhatsAppJobPayload {
|
|
526
|
+
to: string;
|
|
527
|
+
body?: string;
|
|
528
|
+
templateKey?: string;
|
|
529
|
+
externalTemplateRef?: string;
|
|
530
|
+
variables?: Record<string, string>;
|
|
531
|
+
templateParamOrder?: readonly string[];
|
|
532
|
+
}
|
|
533
|
+
declare function registerWhatsAppQueueProcessor(cms: CmsAppLike$1): void;
|
|
534
|
+
declare function queueWhatsApp(cms: CmsAppLike$1, payload: WhatsAppJobPayload): Promise<boolean>;
|
|
535
|
+
|
|
536
|
+
interface WhatsAppPluginConfig extends Partial<WhatsAppServiceConfig> {
|
|
537
|
+
getWhatsAppSettings?: () => Promise<Record<string, string>>;
|
|
538
|
+
getMessageTemplateRow?: MessageTemplateRowLoader;
|
|
539
|
+
}
|
|
540
|
+
interface WhatsAppServiceInterface {
|
|
541
|
+
send(opts: {
|
|
542
|
+
to: string;
|
|
543
|
+
body?: string;
|
|
544
|
+
templateKey?: string;
|
|
545
|
+
externalTemplateRef?: string;
|
|
546
|
+
variables?: Record<string, string>;
|
|
547
|
+
templateParamOrder?: readonly string[];
|
|
548
|
+
}): Promise<boolean>;
|
|
549
|
+
}
|
|
550
|
+
declare function whatsappPlugin(config?: WhatsAppPluginConfig): CmsPlugin<WhatsAppServiceInterface | null>;
|
|
551
|
+
|
|
460
552
|
interface PaymentIntent {
|
|
461
553
|
id: string;
|
|
462
554
|
clientSecret: string;
|
|
@@ -483,6 +575,13 @@ interface RazorpayConfig {
|
|
|
483
575
|
type PaymentPluginConfig = StripeConfig | RazorpayConfig;
|
|
484
576
|
declare function paymentPlugin(config: PaymentPluginConfig): CmsPlugin<PaymentServiceInterface | undefined>;
|
|
485
577
|
|
|
578
|
+
/**
|
|
579
|
+
* Storage plugin contract: upload a file and return its public URL.
|
|
580
|
+
*/
|
|
581
|
+
interface StorageService {
|
|
582
|
+
upload(buffer: Buffer, key: string, contentType: string): Promise<string>;
|
|
583
|
+
}
|
|
584
|
+
|
|
486
585
|
interface S3StoragePluginConfig {
|
|
487
586
|
region: string;
|
|
488
587
|
accessKeyId: string;
|
|
@@ -618,6 +717,173 @@ declare class LlmService implements LlmServiceInterface {
|
|
|
618
717
|
streamChat(messages: LlmMessage[], options?: LlmChatOptions): AsyncIterable<string>;
|
|
619
718
|
}
|
|
620
719
|
|
|
720
|
+
/** Canonical name for new installs / migrations */
|
|
721
|
+
declare const ADMIN_GROUP_NAME = "Administrator";
|
|
722
|
+
/** System administrator group (roles UI + users / user_groups / permissions bypass). */
|
|
723
|
+
declare function isSuperAdminGroupName(name: string | null | undefined): boolean;
|
|
724
|
+
type EntityCrudAction = 'create' | 'read' | 'update' | 'delete';
|
|
725
|
+
type EntityPermissionFlags = {
|
|
726
|
+
c: boolean;
|
|
727
|
+
r: boolean;
|
|
728
|
+
u: boolean;
|
|
729
|
+
d: boolean;
|
|
730
|
+
};
|
|
731
|
+
declare function getPermissionableEntityKeys(entityMap: Record<string, unknown>): string[];
|
|
732
|
+
declare function permissionRowsToRecord(rows: Array<{
|
|
733
|
+
entity: string;
|
|
734
|
+
canCreate: boolean;
|
|
735
|
+
canRead: boolean;
|
|
736
|
+
canUpdate: boolean;
|
|
737
|
+
canDelete: boolean;
|
|
738
|
+
}> | undefined): Record<string, EntityPermissionFlags>;
|
|
739
|
+
declare function hasEntityPermission(record: Record<string, EntityPermissionFlags> | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
740
|
+
|
|
741
|
+
/**
|
|
742
|
+
* @deprecated Administrator bypass is now full entity access via `isRBACAdmin` in `sessionHasEntityAccess`.
|
|
743
|
+
* Kept for backwards-compatible imports.
|
|
744
|
+
*/
|
|
745
|
+
declare const RBAC_ADMIN_ONLY_ENTITIES: Set<string>;
|
|
746
|
+
interface SessionUser {
|
|
747
|
+
id?: string;
|
|
748
|
+
email?: string | null;
|
|
749
|
+
name?: string | null;
|
|
750
|
+
groupId?: number;
|
|
751
|
+
/** User group display name (from login). */
|
|
752
|
+
groupName?: string | null;
|
|
753
|
+
/** @deprecated use entityPerms / isRBACAdmin */
|
|
754
|
+
permissions?: string[];
|
|
755
|
+
/** Administrator group: bypasses entity-level RBAC on all resources */
|
|
756
|
+
isRBACAdmin?: boolean;
|
|
757
|
+
entityPerms?: Record<string, EntityPermissionFlags>;
|
|
758
|
+
/** When false and not isRBACAdmin, admin API/UI is denied. */
|
|
759
|
+
adminAccess?: boolean;
|
|
760
|
+
/** Vendor stores this user can access (from vendor_users). */
|
|
761
|
+
vendorIds?: number[];
|
|
762
|
+
/** Active vendor for scoped CRUD (vendor staff). */
|
|
763
|
+
activeVendorId?: number | null;
|
|
764
|
+
/** Role for the active vendor link (`vendor_users.role`). */
|
|
765
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
766
|
+
/** Active vendor-scoped role id (`vendor_users.vendorRoleId`). */
|
|
767
|
+
vendorRoleId?: number | null;
|
|
768
|
+
vendorRoleName?: string | null;
|
|
769
|
+
/** True when active vendor role has `isOwnerRole`. */
|
|
770
|
+
isVendorRoleOwner?: boolean;
|
|
771
|
+
/** Permissions from active vendor role (`vendor_role_permissions`). */
|
|
772
|
+
vendorEntityPerms?: Record<string, EntityPermissionFlags>;
|
|
773
|
+
/** Set at login: vendor store portal (not platform admin). */
|
|
774
|
+
isVendorPortal?: boolean;
|
|
775
|
+
/** Set at login: vendor store owner (team + permissions). */
|
|
776
|
+
isVendorOwner?: boolean;
|
|
777
|
+
}
|
|
778
|
+
declare function sessionHasEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): boolean;
|
|
779
|
+
declare function canManageRoles(user: SessionUser | null | undefined): boolean;
|
|
780
|
+
type GetSession = () => Promise<{
|
|
781
|
+
user?: SessionUser;
|
|
782
|
+
} | null>;
|
|
783
|
+
declare const OPEN_ENDPOINTS: Array<Record<string, string[]>>;
|
|
784
|
+
declare const PERMISSION_REQUIRED_ENDPOINTS: Record<string, string[]>;
|
|
785
|
+
declare function isOpenEndpoint(pathname: string): boolean;
|
|
786
|
+
declare function getRequiredPermission(pathname: string): string[] | null;
|
|
787
|
+
declare function isPublicMethod(pathname: string, method: string): boolean;
|
|
788
|
+
interface AuthHelpers {
|
|
789
|
+
requireAuth(req: Request): Promise<Response | null>;
|
|
790
|
+
requirePermission(req: Request, permission: string): Promise<Response | null>;
|
|
791
|
+
requireEntityPermission(req: Request, entity: string, action: EntityCrudAction): Promise<Response | null>;
|
|
792
|
+
requireAdminAccess(req: Request): Promise<Response | null>;
|
|
793
|
+
getAuthenticatedUser(): Promise<SessionUser | null>;
|
|
794
|
+
}
|
|
795
|
+
declare function createAuthHelpers(getSession: GetSession, NextResponse: {
|
|
796
|
+
json: (body: unknown, init?: {
|
|
797
|
+
status?: number;
|
|
798
|
+
}) => Response;
|
|
799
|
+
}): AuthHelpers;
|
|
800
|
+
/** Pass return value into `createCmsApiHandler` (includes `getSessionUser` for vendor store APIs). */
|
|
801
|
+
declare function createCmsAuthBundle(getSession: GetSession, NextResponse: {
|
|
802
|
+
json: (body: unknown, init?: {
|
|
803
|
+
status?: number;
|
|
804
|
+
}) => Response;
|
|
805
|
+
}): {
|
|
806
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
807
|
+
requireAdminAccess: (req: Request) => Promise<Response | null>;
|
|
808
|
+
requireEntityPermission: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
809
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
810
|
+
getAuthenticatedUser: () => Promise<SessionUser | null>;
|
|
811
|
+
};
|
|
812
|
+
|
|
813
|
+
/** Entities with a `vendorId` column (store data). */
|
|
814
|
+
declare const VENDOR_SCOPED_STORE_ENTITIES: Set<string>;
|
|
815
|
+
/**
|
|
816
|
+
* Store admin RBAC for vendor portal users (read/create/update/delete fallbacks in rbac-debug).
|
|
817
|
+
* Includes entities without `vendorId` that are still part of the store admin UI.
|
|
818
|
+
*/
|
|
819
|
+
declare const VENDOR_STORE_RBAC_ENTITIES: Set<string>;
|
|
820
|
+
type VendorScope = {
|
|
821
|
+
type: 'all';
|
|
822
|
+
} | {
|
|
823
|
+
type: 'vendor';
|
|
824
|
+
vendorId: number;
|
|
825
|
+
vendorIds: number[];
|
|
826
|
+
} | {
|
|
827
|
+
type: 'deny';
|
|
828
|
+
};
|
|
829
|
+
declare const VENDOR_OWNER_GROUP_NAME = "Vendor Owner";
|
|
830
|
+
/** User groups treated as vendor store staff (sidebar + scoped admin). */
|
|
831
|
+
declare function isVendorGroupName(name: string | null | undefined): boolean;
|
|
832
|
+
declare function isPlatformAdministrator(user: SessionUser | null | undefined): boolean;
|
|
833
|
+
/** Vendor portal UI (store + store admin), not platform admin. */
|
|
834
|
+
declare function isVendorPortalUser(user: SessionUser | null | undefined): boolean;
|
|
835
|
+
declare function isVendorStaff(user: SessionUser | null | undefined): boolean;
|
|
836
|
+
/** Vendor store owner (manages team + role permissions for their store). */
|
|
837
|
+
declare function isVendorOwner(user: SessionUser | null | undefined): boolean;
|
|
838
|
+
declare function canManageVendorTeam(user: SessionUser | null | undefined): boolean;
|
|
839
|
+
declare function canManageVendorRoles(user: SessionUser | null | undefined): boolean;
|
|
840
|
+
/** Platform admins (Administrator group) can onboard vendors. */
|
|
841
|
+
declare function canOnboardVendors(user: SessionUser | null | undefined): boolean;
|
|
842
|
+
declare function resolveVendorScopeFromSessionUser(user: SessionUser | null | undefined): VendorScope;
|
|
843
|
+
/** Compute portal flags at login (persist on JWT). */
|
|
844
|
+
declare function vendorPortalFlagsFromUser(input: {
|
|
845
|
+
email: string;
|
|
846
|
+
isRBACAdmin: boolean;
|
|
847
|
+
groupName?: string | null;
|
|
848
|
+
vendorIds?: number[];
|
|
849
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
850
|
+
isVendorRoleOwner?: boolean;
|
|
851
|
+
}): {
|
|
852
|
+
isVendorPortal: boolean;
|
|
853
|
+
isVendorOwner: boolean;
|
|
854
|
+
};
|
|
855
|
+
|
|
856
|
+
type EntityMap$2 = Record<string, typeorm.EntityTarget<typeorm.ObjectLiteral>>;
|
|
857
|
+
interface CrudHandlerOptions {
|
|
858
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
859
|
+
json: (body: unknown, init?: {
|
|
860
|
+
status?: number;
|
|
861
|
+
}) => Response;
|
|
862
|
+
requireEntityPermission?: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
863
|
+
/** When set, contact create/update enqueues ERP `create-contact` (non-fatal). */
|
|
864
|
+
getCms?: () => Promise<{
|
|
865
|
+
getPlugin: (name: string) => unknown;
|
|
866
|
+
}>;
|
|
867
|
+
/** When set, soft-delete sets `deletedBy` from the current admin user. */
|
|
868
|
+
getDeletedByUserId?: (req: Request) => Promise<number | null>;
|
|
869
|
+
/** When set, store rows are filtered by session vendor (platform admin bypasses). */
|
|
870
|
+
getVendorScope?: () => Promise<VendorScope>;
|
|
871
|
+
/** Hydrated session (group + vendor context) for vendorId resolution on create. */
|
|
872
|
+
getHydratedSessionUser?: () => Promise<SessionUser | null>;
|
|
873
|
+
}
|
|
874
|
+
declare function createCrudHandler(dataSource: DataSource, entityMap: EntityMap$2, options: CrudHandlerOptions): {
|
|
875
|
+
GET(req: Request, resource: string): Promise<Response>;
|
|
876
|
+
POST(req: Request, resource: string): Promise<Response>;
|
|
877
|
+
GET_METADATA(req: Request, resource: string): Promise<Response>;
|
|
878
|
+
BULK_POST(req: Request, resource: string): Promise<Response>;
|
|
879
|
+
GET_EXPORT(req: Request, resource: string): Promise<Response>;
|
|
880
|
+
};
|
|
881
|
+
declare function createCrudByIdHandler(dataSource: DataSource, entityMap: EntityMap$2, options: CrudHandlerOptions): {
|
|
882
|
+
GET(req: Request, resource: string, id: string): Promise<Response>;
|
|
883
|
+
PUT(req: Request, resource: string, id: string): Promise<Response>;
|
|
884
|
+
DELETE(req: Request, resource: string, id: string): Promise<Response>;
|
|
885
|
+
};
|
|
886
|
+
|
|
621
887
|
declare class LlmAgent {
|
|
622
888
|
id: number;
|
|
623
889
|
name: string;
|
|
@@ -779,495 +1045,477 @@ declare function pgBossScheduleNameForId(scheduleId: string): string;
|
|
|
779
1045
|
declare function buildCronFromSchedule(schedule: Pick<JobSchedule, 'scheduleMode' | 'intervalMinutes' | 'runAtTime' | 'runOnDays' | 'cronExpression'>): string;
|
|
780
1046
|
declare function validateScheduleInput(schedule: Pick<JobSchedule, 'scheduleMode' | 'intervalMinutes' | 'runAtTime' | 'cronExpression'>): string | null;
|
|
781
1047
|
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
activeProvider: CaptchaProviderId | null;
|
|
786
|
-
siteKey: string | null;
|
|
787
|
-
availableProviders: Array<{
|
|
788
|
-
id: CaptchaProviderId;
|
|
789
|
-
siteKey: string;
|
|
790
|
-
}>;
|
|
791
|
-
multipleProviders: boolean;
|
|
792
|
-
}
|
|
793
|
-
type CaptchaVerifyResult = {
|
|
794
|
-
ok: true;
|
|
795
|
-
} | {
|
|
796
|
-
ok: false;
|
|
797
|
-
status: number;
|
|
798
|
-
message: string;
|
|
799
|
-
};
|
|
800
|
-
declare function buildCaptchaPublicConfig(config: Record<string, string>): CaptchaPublicConfig;
|
|
801
|
-
declare class CaptchaService {
|
|
802
|
-
private readonly env;
|
|
803
|
-
constructor(env: Record<string, string>);
|
|
804
|
-
isEnforced(): boolean;
|
|
805
|
-
getPublicConfig(): CaptchaPublicConfig;
|
|
806
|
-
verify(body: Record<string, unknown>, req: Request): Promise<CaptchaVerifyResult>;
|
|
807
|
-
}
|
|
808
|
-
|
|
809
|
-
declare function captchaPlugin(): CmsPlugin<CaptchaService | void>;
|
|
810
|
-
|
|
811
|
-
type JsonResponse = (body: unknown, init?: {
|
|
812
|
-
status?: number;
|
|
813
|
-
headers?: HeadersInit;
|
|
814
|
-
}) => Response;
|
|
815
|
-
declare function assertCaptchaOk(getCms: (() => Promise<{
|
|
816
|
-
getPlugin: (name: string) => unknown;
|
|
817
|
-
}>) | undefined, body: Record<string, unknown>, req: Request, json: JsonResponse): Promise<Response | null>;
|
|
1048
|
+
/**
|
|
1049
|
+
* Auth API handler factories. Inject dataSource + entityMap, sendEmail, hash/compare; optional hooks to customize.
|
|
1050
|
+
*/
|
|
818
1051
|
|
|
819
|
-
interface
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
date: Date;
|
|
827
|
-
creator?: string;
|
|
828
|
-
categories?: string[];
|
|
1052
|
+
interface AuthHandlersConfig {
|
|
1053
|
+
json: (body: unknown, init?: {
|
|
1054
|
+
status?: number;
|
|
1055
|
+
}) => Response;
|
|
1056
|
+
baseUrl: string;
|
|
1057
|
+
hashPassword: (plain: string) => Promise<string>;
|
|
1058
|
+
comparePassword: (plain: string, hash: string) => Promise<boolean>;
|
|
829
1059
|
}
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
};
|
|
851
|
-
type BlogGeneratorDraftParseMode = 'json' | 'plaintext';
|
|
852
|
-
interface BlogGeneratorSeoDraft {
|
|
853
|
-
title: string | null;
|
|
854
|
-
description: string | null;
|
|
855
|
-
keywords: string | null;
|
|
856
|
-
ogTitle: string | null;
|
|
857
|
-
ogDescription: string | null;
|
|
1060
|
+
interface ForgotPasswordConfig extends AuthHandlersConfig {
|
|
1061
|
+
dataSource: DataSource;
|
|
1062
|
+
entityMap: EntityMap$2;
|
|
1063
|
+
sendEmail?: (opts: {
|
|
1064
|
+
to: string;
|
|
1065
|
+
subject: string;
|
|
1066
|
+
html: string;
|
|
1067
|
+
text?: string;
|
|
1068
|
+
/** Plain reset URL for templated emails (preferred over parsing html). */
|
|
1069
|
+
resetLink?: string;
|
|
1070
|
+
}) => Promise<void>;
|
|
1071
|
+
resetExpiryHours?: number;
|
|
1072
|
+
afterCreateToken?: (email: string, resetLink: string) => Promise<void>;
|
|
1073
|
+
}
|
|
1074
|
+
declare function createForgotPasswordHandler(config: ForgotPasswordConfig): (request: Request) => Promise<Response>;
|
|
1075
|
+
interface SetPasswordConfig extends AuthHandlersConfig {
|
|
1076
|
+
dataSource: DataSource;
|
|
1077
|
+
entityMap: EntityMap$2;
|
|
1078
|
+
minPasswordLength?: number;
|
|
1079
|
+
beforeUpdate?: (email: string, userId: number) => Promise<void>;
|
|
858
1080
|
}
|
|
859
|
-
|
|
860
|
-
|
|
861
|
-
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
1081
|
+
declare function createSetPasswordHandler(config: SetPasswordConfig): (request: Request) => Promise<Response>;
|
|
1082
|
+
interface InviteAcceptConfig extends AuthHandlersConfig {
|
|
1083
|
+
dataSource: DataSource;
|
|
1084
|
+
entityMap: EntityMap$2;
|
|
1085
|
+
beforeActivate?: (email: string, userId: number) => Promise<void>;
|
|
1086
|
+
}
|
|
1087
|
+
/** Decode invite token (base64 email) and set password + unblock user */
|
|
1088
|
+
declare function createInviteAcceptHandler(config: InviteAcceptConfig): (request: Request) => Promise<Response>;
|
|
1089
|
+
interface ChangePasswordConfig extends AuthHandlersConfig {
|
|
1090
|
+
dataSource: DataSource;
|
|
1091
|
+
entityMap: EntityMap$2;
|
|
1092
|
+
getSession: () => Promise<{
|
|
1093
|
+
user?: {
|
|
1094
|
+
email?: string | null;
|
|
1095
|
+
};
|
|
1096
|
+
} | null>;
|
|
1097
|
+
minPasswordLength?: number;
|
|
1098
|
+
beforeUpdate?: (email: string) => Promise<void>;
|
|
1099
|
+
}
|
|
1100
|
+
declare function createChangePasswordHandler(config: ChangePasswordConfig): (request: Request) => Promise<Response>;
|
|
1101
|
+
interface UserAuthApiConfig extends ForgotPasswordConfig, Omit<SetPasswordConfig, 'dataSource' | 'entityMap' | 'json' | 'baseUrl' | 'hashPassword' | 'comparePassword'>, Omit<InviteAcceptConfig, 'dataSource' | 'entityMap' | 'json' | 'baseUrl' | 'hashPassword' | 'comparePassword'>, Omit<ChangePasswordConfig, 'dataSource' | 'entityMap' | 'json' | 'baseUrl' | 'hashPassword' | 'comparePassword' | 'beforeUpdate' | 'getSession'> {
|
|
1102
|
+
getSession?: () => Promise<{
|
|
1103
|
+
user?: {
|
|
1104
|
+
email?: string | null;
|
|
1105
|
+
};
|
|
1106
|
+
} | null>;
|
|
1107
|
+
beforeChangePasswordUpdate?: (email: string) => Promise<void>;
|
|
870
1108
|
}
|
|
871
1109
|
/**
|
|
872
|
-
*
|
|
873
|
-
*
|
|
1110
|
+
* Single router for all user-auth APIs. Mount in the app once.
|
|
1111
|
+
* Use when you have no users/[id] route (else Next.js gives [id] precedence and "forgot-password" would match as id).
|
|
1112
|
+
* Path is the segment after the mount (e.g. "forgot-password"). Returns 404 for unknown paths.
|
|
874
1113
|
*/
|
|
875
|
-
declare function
|
|
876
|
-
|
|
877
|
-
id: number;
|
|
878
|
-
name: string;
|
|
879
|
-
}[]): {
|
|
880
|
-
categoryId: number | null;
|
|
881
|
-
matched: boolean;
|
|
1114
|
+
declare function createUserAuthApiRouter(config: UserAuthApiConfig): {
|
|
1115
|
+
POST(req: Request, pathname: string): Promise<Response>;
|
|
882
1116
|
};
|
|
1117
|
+
|
|
883
1118
|
/**
|
|
884
|
-
*
|
|
1119
|
+
* CMS API handlers: dashboard, analytics, upload, blog/form by slug, users (list/create/get/update/delete/regenerate-invite/avatar/profile).
|
|
1120
|
+
* All accept injectable deps; upload supports S3 or local.
|
|
885
1121
|
*/
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
article: LatestArticleFromFeed;
|
|
889
|
-
}>): string;
|
|
1122
|
+
|
|
1123
|
+
type RequireEntityPermissionFn = (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
890
1124
|
/**
|
|
891
|
-
*
|
|
1125
|
+
* Optional JSON in `LlmAgent.validationRules`. Used for programmatic checks before the LLM call.
|
|
1126
|
+
* For natural-language output rules, use `guardrails` / `outputRules` / `outputInstructions` (merged into system prompt).
|
|
892
1127
|
*/
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
/**
|
|
900
|
-
|
|
901
|
-
|
|
902
|
-
|
|
903
|
-
|
|
904
|
-
|
|
1128
|
+
type LlmAgentValidationRulesJson = {
|
|
1129
|
+
maxUserChars?: number;
|
|
1130
|
+
maxMessageLength?: number;
|
|
1131
|
+
minUserChars?: number;
|
|
1132
|
+
minMessageLength?: number;
|
|
1133
|
+
blockedSubstrings?: string[];
|
|
1134
|
+
/** Shown to the model as output guardrails (first non-empty of guardrails | outputRules | outputInstructions wins). */
|
|
1135
|
+
guardrails?: string;
|
|
1136
|
+
outputRules?: string;
|
|
1137
|
+
outputInstructions?: string;
|
|
1138
|
+
};
|
|
1139
|
+
type ParsedLlmAgentValidation = {
|
|
1140
|
+
/** Subset used for length / substring checks only. */
|
|
1141
|
+
structured: Pick<LlmAgentValidationRulesJson, 'maxUserChars' | 'maxMessageLength' | 'minUserChars' | 'minMessageLength' | 'blockedSubstrings'>;
|
|
1142
|
+
/** Appended to system prompt so the model follows output guardrails. */
|
|
1143
|
+
guardrailsForPrompt: string | null;
|
|
905
1144
|
};
|
|
906
1145
|
/**
|
|
907
|
-
*
|
|
908
|
-
*
|
|
1146
|
+
* - Valid JSON object: structural keys → validation; `guardrails` / `outputRules` / `outputInstructions` → prompt suffix.
|
|
1147
|
+
* - Not JSON: entire string is treated as prose guardrails for the prompt (no programmatic rules unless you use JSON).
|
|
909
1148
|
*/
|
|
910
|
-
declare function
|
|
911
|
-
declare
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
950
|
-
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
959
|
-
|
|
960
|
-
|
|
961
|
-
article: LatestArticleFromFeed;
|
|
962
|
-
}>;
|
|
963
|
-
/** First feed's article (backward compatibility). */
|
|
964
|
-
article: LatestArticleFromFeed;
|
|
965
|
-
/** Raw model reply (HTML body per defaults; legacy markdown or JSON still parsed when present). */
|
|
966
|
-
blogMarkdown: string;
|
|
967
|
-
blogDrafts: BlogGeneratorBlogDraft[];
|
|
968
|
-
/** Same as first draft; backward compatibility. */
|
|
969
|
-
blogDraft: BlogGeneratorBlogDraft;
|
|
970
|
-
}>;
|
|
1149
|
+
declare function parseLlmAgentValidationRules(validationRulesText: string | null | undefined): ParsedLlmAgentValidation;
|
|
1150
|
+
declare function validateUserMessageAgainstStructuredRules(message: string, structured: ParsedLlmAgentValidation['structured']): {
|
|
1151
|
+
ok: true;
|
|
1152
|
+
} | {
|
|
1153
|
+
ok: false;
|
|
1154
|
+
error: string;
|
|
1155
|
+
};
|
|
1156
|
+
/** Parses `validationRules` then runs programmatic checks only. */
|
|
1157
|
+
declare function validateUserMessageAgainstAgentRules(message: string, validationRulesText: string | null | undefined): {
|
|
1158
|
+
ok: true;
|
|
1159
|
+
} | {
|
|
1160
|
+
ok: false;
|
|
1161
|
+
error: string;
|
|
1162
|
+
};
|
|
1163
|
+
/** Merges guardrails prose into the system instruction sent to the model. */
|
|
1164
|
+
declare function mergeGuardrailsIntoSystemPrompt(baseSystem: string | undefined, guardrailsForPrompt: string | null): string;
|
|
1165
|
+
interface CmsHandlersBase {
|
|
1166
|
+
json: (body: unknown, init?: {
|
|
1167
|
+
status?: number;
|
|
1168
|
+
}) => Response;
|
|
1169
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1170
|
+
requireEntityPermission?: RequireEntityPermissionFn;
|
|
1171
|
+
}
|
|
1172
|
+
interface DashboardStatsConfig extends CmsHandlersBase {
|
|
1173
|
+
dataSource: DataSource;
|
|
1174
|
+
entityMap: EntityMap$2;
|
|
1175
|
+
requirePermission?: (req: Request, permission: string) => Promise<Response | null>;
|
|
1176
|
+
}
|
|
1177
|
+
declare function createDashboardStatsHandler(config: DashboardStatsConfig): (req: Request) => Promise<Response>;
|
|
1178
|
+
interface EcommerceAnalyticsConfig extends CmsHandlersBase {
|
|
1179
|
+
dataSource: DataSource;
|
|
1180
|
+
entityMap: EntityMap$2;
|
|
1181
|
+
}
|
|
1182
|
+
declare function createEcommerceAnalyticsHandler(config: EcommerceAnalyticsConfig): (req: Request) => Promise<Response>;
|
|
1183
|
+
interface VendorDashboardConfig extends CmsHandlersBase {
|
|
1184
|
+
dataSource: DataSource;
|
|
1185
|
+
entityMap: EntityMap$2;
|
|
1186
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
1187
|
+
}
|
|
1188
|
+
declare function createVendorDashboardHandler(config: VendorDashboardConfig): (req: Request) => Promise<Response>;
|
|
1189
|
+
interface AnalyticsHandlerConfig extends CmsHandlersBase {
|
|
1190
|
+
getAnalyticsData?: (days: number) => Promise<unknown>;
|
|
1191
|
+
getPropertyId?: () => ({
|
|
1192
|
+
currentViewId?: string;
|
|
1193
|
+
[k: string]: unknown;
|
|
1194
|
+
});
|
|
1195
|
+
getPermissions?: () => ({
|
|
1196
|
+
serviceAccountEmail?: string;
|
|
1197
|
+
currentViewId?: string;
|
|
1198
|
+
[k: string]: unknown;
|
|
1199
|
+
});
|
|
971
1200
|
}
|
|
1201
|
+
declare function createAnalyticsHandlers(config: AnalyticsHandlerConfig): {
|
|
1202
|
+
GET(req: Request): Promise<Response>;
|
|
1203
|
+
propertyId: () => Promise<Response>;
|
|
1204
|
+
permissions: () => Promise<Response>;
|
|
1205
|
+
};
|
|
972
1206
|
|
|
973
|
-
|
|
974
|
-
|
|
1207
|
+
interface UploadHandlerConfig extends CmsHandlersBase {
|
|
1208
|
+
/** Storage plugin instance or getter (e.g. () => getCms().then(c => c.getPlugin('storage'))). If not set, uses local fallback. */
|
|
1209
|
+
storage?: StorageService | (() => StorageService | undefined) | (() => Promise<StorageService | undefined>);
|
|
1210
|
+
/** Fallback when storage not set: dir relative to cwd (e.g. "public/uploads") */
|
|
1211
|
+
localUploadDir?: string;
|
|
1212
|
+
allowedTypes?: string[];
|
|
1213
|
+
maxSizeBytes?: number;
|
|
1214
|
+
/** Resolve folder chain for `parentId` (merged from createCmsApiHandler when omitted). */
|
|
1215
|
+
dataSource?: DataSource;
|
|
1216
|
+
entityMap?: EntityMap$2;
|
|
1217
|
+
}
|
|
1218
|
+
declare function createUploadHandler(config: UploadHandlerConfig): (req: Request) => Promise<Response>;
|
|
1219
|
+
/** POST /api/media/extract/:id — expand a zip media row into folders/files under the zip’s parent folder. */
|
|
1220
|
+
declare function createMediaZipExtractHandler(config: UploadHandlerConfig): (_req: Request, zipMediaId: string) => Promise<Response>;
|
|
1221
|
+
interface BlogBySlugConfig extends CmsHandlersBase {
|
|
1222
|
+
dataSource: DataSource;
|
|
1223
|
+
entityMap: EntityMap$2;
|
|
1224
|
+
}
|
|
1225
|
+
declare function createBlogBySlugHandler(config: BlogBySlugConfig): (_req: Request, slug: string) => Promise<Response>;
|
|
1226
|
+
interface FormBySlugConfig extends CmsHandlersBase {
|
|
1227
|
+
dataSource: DataSource;
|
|
1228
|
+
entityMap: EntityMap$2;
|
|
1229
|
+
}
|
|
1230
|
+
declare function createFormBySlugHandler(config: FormBySlugConfig): (_req: Request, slug: string) => Promise<Response>;
|
|
1231
|
+
interface FormSaveHandlersConfig extends CmsHandlersBase {
|
|
1232
|
+
dataSource: DataSource;
|
|
1233
|
+
entityMap: EntityMap$2;
|
|
1234
|
+
}
|
|
1235
|
+
interface FormSubmissionHandlerConfig {
|
|
1236
|
+
dataSource: DataSource;
|
|
1237
|
+
entityMap: EntityMap$2;
|
|
1238
|
+
json: (body: unknown, init?: {
|
|
1239
|
+
status?: number;
|
|
1240
|
+
}) => Response;
|
|
1241
|
+
/** When set, form submission notification email is queued (CRM recipient). */
|
|
1242
|
+
getCms?: () => Promise<{
|
|
1243
|
+
getPlugin: (name: string) => unknown;
|
|
1244
|
+
}>;
|
|
1245
|
+
getCompanyDetails?: () => Promise<CompanyDetails>;
|
|
1246
|
+
getRecipientForChannel?: (channel: 'crm' | 'sales' | 'fulfilment') => Promise<string | null>;
|
|
1247
|
+
}
|
|
1248
|
+
interface FormSubmissionGetByIdConfig extends CmsHandlersBase {
|
|
1249
|
+
dataSource: DataSource;
|
|
1250
|
+
entityMap: EntityMap$2;
|
|
1251
|
+
json: (body: unknown, init?: {
|
|
1252
|
+
status?: number;
|
|
1253
|
+
}) => Response;
|
|
1254
|
+
}
|
|
1255
|
+
interface UsersApiConfig extends CmsHandlersBase {
|
|
1256
|
+
dataSource: DataSource;
|
|
1257
|
+
entityMap: EntityMap$2;
|
|
1258
|
+
baseUrl: string;
|
|
1259
|
+
/** When set with email queue/plugin, invite emails are sent on user create and regenerate-invite. */
|
|
1260
|
+
getCms?: () => Promise<{
|
|
1261
|
+
getPlugin: (name: string) => unknown;
|
|
1262
|
+
}>;
|
|
1263
|
+
getCompanyDetails?: () => Promise<CompanyDetails>;
|
|
1264
|
+
/** When set, soft-delete sets `deletedBy` on the user row. */
|
|
1265
|
+
getSessionUser?: () => Promise<SessionUser | null>;
|
|
1266
|
+
}
|
|
1267
|
+
declare function createUsersApiHandlers(config: UsersApiConfig): {
|
|
1268
|
+
list(req: Request): Promise<Response>;
|
|
1269
|
+
create(req: Request): Promise<Response>;
|
|
1270
|
+
getById(_req: Request, id: string): Promise<Response>;
|
|
1271
|
+
update(req: Request, id: string): Promise<Response>;
|
|
1272
|
+
delete(_req: Request, id: string): Promise<Response>;
|
|
1273
|
+
regenerateInvite(_req: Request, id: string): Promise<Response>;
|
|
1274
|
+
};
|
|
1275
|
+
interface UserAvatarConfig extends CmsHandlersBase {
|
|
1276
|
+
getSession: () => Promise<{
|
|
1277
|
+
user?: {
|
|
1278
|
+
email?: string | null;
|
|
1279
|
+
};
|
|
1280
|
+
} | null>;
|
|
1281
|
+
/** Save avatar (buffer, fileName) => publicUrl. Default: local public/uploads/avatars */
|
|
1282
|
+
saveAvatar?: (buffer: Buffer, fileName: string) => Promise<string>;
|
|
1283
|
+
}
|
|
1284
|
+
declare function createUserAvatarHandler(config: UserAvatarConfig): (req: Request) => Promise<Response>;
|
|
1285
|
+
interface UserProfileConfig extends CmsHandlersBase {
|
|
1286
|
+
dataSource: DataSource;
|
|
1287
|
+
entityMap: EntityMap$2;
|
|
1288
|
+
getSession: () => Promise<{
|
|
1289
|
+
user?: {
|
|
1290
|
+
id?: string;
|
|
1291
|
+
email?: string | null;
|
|
1292
|
+
name?: string | null;
|
|
1293
|
+
};
|
|
1294
|
+
} | null>;
|
|
1295
|
+
/** Optional hook after a successful profile PUT (e.g. audit logging). */
|
|
1296
|
+
onProfileUpdated?: (req: Request, user: {
|
|
1297
|
+
id: number;
|
|
1298
|
+
name: string;
|
|
1299
|
+
email: string;
|
|
1300
|
+
phone: string | null;
|
|
1301
|
+
}) => Promise<void>;
|
|
1302
|
+
}
|
|
975
1303
|
/**
|
|
976
|
-
*
|
|
977
|
-
*
|
|
1304
|
+
* GET / PUT handlers for `/api/users/profile` (current session user).
|
|
1305
|
+
* GET merges DB fields with the session; PUT updates the user row and callers should refresh the client session (e.g. `useSession().update()`).
|
|
978
1306
|
*/
|
|
979
|
-
declare
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
1307
|
+
declare function createUserProfileHandler(config: UserProfileConfig): {
|
|
1308
|
+
GET(_req: Request): Promise<Response>;
|
|
1309
|
+
PUT(req: Request): Promise<Response>;
|
|
1310
|
+
};
|
|
1311
|
+
interface SettingsApiConfig extends CmsHandlersBase {
|
|
1312
|
+
dataSource: DataSource;
|
|
1313
|
+
entityMap: EntityMap$2;
|
|
1314
|
+
encryptionKey?: string;
|
|
1315
|
+
/** Groups in this list are readable without auth (GET returns all keys for the group). */
|
|
1316
|
+
publicGetGroups?: string[];
|
|
1317
|
+
}
|
|
1318
|
+
declare function simpleEncrypt(text: string, key: string): string;
|
|
1319
|
+
declare function simpleDecrypt(encoded: string, key: string): string;
|
|
983
1320
|
/**
|
|
984
|
-
*
|
|
985
|
-
* Edit in the admin UI if needed; defaults match product intent.
|
|
1321
|
+
* Structural types so apps with their own `typeorm` install (e.g. npm link) typecheck without duplicate-package errors.
|
|
986
1322
|
*/
|
|
987
|
-
|
|
1323
|
+
type GetPublicSettingsGroupDataSource = {
|
|
1324
|
+
getRepository(entity: unknown): {
|
|
1325
|
+
find(options: object): Promise<unknown[]>;
|
|
1326
|
+
};
|
|
1327
|
+
};
|
|
1328
|
+
interface GetPublicSettingsGroupConfig {
|
|
1329
|
+
dataSource: GetPublicSettingsGroupDataSource;
|
|
1330
|
+
entityMap: Record<string, unknown>;
|
|
1331
|
+
encryptionKey?: string;
|
|
1332
|
+
}
|
|
1333
|
+
/** Same rows as unauthenticated GET /api/settings/:group when the group is in publicGetGroups. */
|
|
1334
|
+
declare function getPublicSettingsGroup(config: GetPublicSettingsGroupConfig, group: string): Promise<Record<string, string>>;
|
|
1335
|
+
declare function createSettingsApiHandlers(config: SettingsApiConfig): {
|
|
1336
|
+
GET(req: Request, group: string): Promise<Response>;
|
|
1337
|
+
PUT(req: Request, group: string): Promise<Response>;
|
|
1338
|
+
};
|
|
1339
|
+
interface ChatApiConfig extends CmsHandlersBase {
|
|
1340
|
+
dataSource: DataSource;
|
|
1341
|
+
entityMap: EntityMap$2;
|
|
1342
|
+
getCms: () => Promise<{
|
|
1343
|
+
getPlugin: (name: string) => unknown;
|
|
1344
|
+
}>;
|
|
1345
|
+
}
|
|
1346
|
+
/** Safe subset of `llm` settings for the storefront chat widget (`GET /api/chat/config`). */
|
|
1347
|
+
interface ChatPublicConfig {
|
|
1348
|
+
enabled: boolean;
|
|
1349
|
+
chatMode: 'whatsapp' | 'external' | 'llm';
|
|
1350
|
+
/** When `chatMode === 'llm'`, slug of the chatbot-scoped agent (`llm_agents.scope = chatbot`). */
|
|
1351
|
+
agentSlug: string;
|
|
1352
|
+
botName: string;
|
|
1353
|
+
icon: string;
|
|
1354
|
+
iconImageUrl: string;
|
|
1355
|
+
iconBackgroundColor: string;
|
|
1356
|
+
headerColor: string;
|
|
1357
|
+
whatsappPhone: string;
|
|
1358
|
+
}
|
|
988
1359
|
|
|
989
1360
|
/**
|
|
990
|
-
*
|
|
991
|
-
*
|
|
992
|
-
* Optional `llm_agents` row: slug {@link BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG} — when present and enabled,
|
|
993
|
-
* model / temperature / max_tokens apply to this call only (writer step uses `blog-generator`).
|
|
1361
|
+
* Admin API: attach knowledge base documents to an LLM agent, ingest text into chunks + embeddings.
|
|
1362
|
+
* Routes: GET/POST /api/llm_agents/:slug/knowledge, DELETE /api/llm_agents/:slug/knowledge/:documentId
|
|
994
1363
|
*
|
|
995
|
-
*
|
|
996
|
-
*
|
|
1364
|
+
* Pipeline logs (grep `[llm-agent-knowledge] pipeline`):
|
|
1365
|
+
* - 01_request — incoming POST, content-type preview
|
|
1366
|
+
* - 02_agent_loaded — agent id for slug
|
|
1367
|
+
* - 03_body_parsed — JSON vs multipart, sizes / documentId
|
|
1368
|
+
* - 04_* — file decode or PDF extract (multipart)
|
|
1369
|
+
* - 05_branch — link_existing_document | new_upload_ingest
|
|
1370
|
+
* - 06_* — KB row + junction (link create / exists)
|
|
1371
|
+
* - 06b_chunks_existing_count — link path: existing chunk rows
|
|
1372
|
+
* - 06_knowledge_document_saved — new ingest: document row id
|
|
1373
|
+
* - 07_chunk_split — split stats
|
|
1374
|
+
* - 07b_chunks_persisted — chunk rows saved
|
|
1375
|
+
* - 07_query_chunks_missing_embedding — link path: rows with NULL embedding
|
|
1376
|
+
* - 08_* — resolve LLM plugin, embed availability or skip
|
|
1377
|
+
* - 09_embedding_workers_start / 10_embedding_workers_finished — concurrent embed+DB update
|
|
1378
|
+
* - 11_response — final outcome summary
|
|
1379
|
+
* - 99_pipeline_error — uncaught exception
|
|
997
1380
|
*/
|
|
998
|
-
declare const BLOG_METADATA_ENRICHER_AGENT_NAME = "Blog Generator Metadata";
|
|
999
|
-
/** `llm_agents.slug` for routing model/temperature for the metadata-only chat step. */
|
|
1000
|
-
declare const BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG = "blog-generator-metadata";
|
|
1001
|
-
declare const BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION = "You are a careful CMS metadata assistant for a publishing system.\n\nYou receive ONE complete blog post as HTML (title is usually in <h1 class=\"blog-post-title\"> or the first <h1>). Your job is to propose structured fields so an editor can save the post: category, URL slug, SEO block, and topical tags.\n\nRULES:\n1. Read the whole article and infer the primary topic and audience.\n2. categoryName must be EXACTLY one string from AVAILABLE_BLOG_CATEGORIES in the user message, or \"\" if none fit.\n3. blogSlug: lowercase kebab-case, ASCII letters/digits/hyphens only, no leading/trailing hyphens, max ~80 chars. Derive from the main topic or title.\n4. seo.title: concise meta title (~50\u201360 characters when reasonable).\n5. seo.description: meta description (~150\u2013160 characters when reasonable), plain text.\n6. seo.keywords: comma-separated phrases, no stuffing.\n7. seo.ogTitle / seo.ogDescription: may mirror title/description or be slightly adapted for social.\n8. tags: 4\u201310 short labels (1\u20133 words each). Prefer exact matches from EXISTING_TAG_NAMES when they truly apply; otherwise invent precise new labels (they may be created in the CMS later).\n9. Do not invent statistics, quotes, or URLs not implied by the article.\n10. Output JSON only \u2014 no markdown outside the JSON, no commentary.\n\nOUTPUT FORMAT (STRICT):\nReturn a single JSON object only. Do not wrap it in a markdown code fence.\n\n{\n \"categoryName\": \"string \u2014 exact match from list or empty string\",\n \"blogSlug\": \"string \u2014 url-safe kebab-case\",\n \"seo\": {\n \"title\": \"string or empty\",\n \"description\": \"string or empty\",\n \"keywords\": \"string or empty\",\n \"ogTitle\": \"string or empty\",\n \"ogDescription\": \"string or empty\"\n },\n \"tags\": [\"tag-one\", \"tag-two\"]\n}";
|
|
1002
|
-
declare const BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES: string;
|
|
1003
1381
|
|
|
1004
|
-
interface
|
|
1005
|
-
|
|
1006
|
-
|
|
1382
|
+
interface LlmAgentKnowledgeApiConfig {
|
|
1383
|
+
dataSource: DataSource;
|
|
1384
|
+
entityMap: EntityMap$2;
|
|
1385
|
+
getCms: () => Promise<{
|
|
1386
|
+
getPlugin: (name: string) => unknown;
|
|
1387
|
+
}>;
|
|
1388
|
+
json: (body: unknown, init?: {
|
|
1389
|
+
status?: number;
|
|
1390
|
+
}) => Response;
|
|
1391
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1392
|
+
requireEntityPermission?: RequireEntityPermissionFn;
|
|
1007
1393
|
}
|
|
1008
|
-
declare function
|
|
1394
|
+
declare function createLlmAgentKnowledgeHandlers(config: LlmAgentKnowledgeApiConfig): {
|
|
1395
|
+
list(req: Request, slug: string): Promise<Response>;
|
|
1396
|
+
post(req: Request, slug: string): Promise<Response>;
|
|
1397
|
+
unlink(req: Request, slug: string, documentIdStr: string): Promise<Response>;
|
|
1398
|
+
} | null;
|
|
1009
1399
|
|
|
1010
|
-
|
|
1400
|
+
/**
|
|
1401
|
+
* Single CMS API handler: dashboard, analytics, upload, media zip extract, blog/form by slug, users API, user auth, CRUD. Mount once (e.g. app/api/[[...path]]/route.ts).
|
|
1402
|
+
*/
|
|
1403
|
+
|
|
1404
|
+
/** CMS instance with getPlugin; when provided, analytics and userAuth.sendEmail can be resolved from plugins when not passed. */
|
|
1405
|
+
type CmsGetter = () => Promise<{
|
|
1406
|
+
getPlugin: (name: string) => unknown;
|
|
1407
|
+
}>;
|
|
1408
|
+
interface CmsApiHandlerConfig {
|
|
1011
1409
|
dataSource: DataSource;
|
|
1012
1410
|
entityMap: EntityMap$2;
|
|
1411
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1013
1412
|
json: (body: unknown, init?: {
|
|
1014
1413
|
status?: number;
|
|
1015
1414
|
}) => Response;
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
1415
|
+
pathToModel?: (segment: string) => string;
|
|
1416
|
+
crudResources?: string[];
|
|
1417
|
+
/** When set, analytics and userAuth.sendEmail can be derived from getPlugin('analytics') and getPlugin('email') when not provided. */
|
|
1418
|
+
getCms?: CmsGetter;
|
|
1419
|
+
/** Optional: used when deriving userAuth.sendEmail to pass company details into email templates (e.g. from settings). */
|
|
1420
|
+
getCompanyDetails?: () => Promise<CompanyDetails>;
|
|
1421
|
+
/** Optional: used for form submission and other channel-based email recipients (from settings group "email"). */
|
|
1422
|
+
getRecipientForChannel?: (channel: 'crm' | 'sales' | 'fulfilment') => Promise<string | null>;
|
|
1423
|
+
userAuth?: UserAuthApiConfig;
|
|
1424
|
+
/** GET /api/dashboard/stats */
|
|
1425
|
+
dashboard?: DashboardStatsConfig;
|
|
1426
|
+
/** GET /api/dashboard/ecommerce */
|
|
1427
|
+
ecommerceAnalytics?: EcommerceAnalyticsConfig;
|
|
1428
|
+
/** GET /api/analytics. If omitted and getCms is set, uses getCms().getPlugin('analytics'). */
|
|
1429
|
+
analytics?: AnalyticsHandlerConfig;
|
|
1430
|
+
/** POST /api/upload (S3 or local) */
|
|
1431
|
+
upload?: UploadHandlerConfig;
|
|
1432
|
+
/** GET /api/blogs/slug/:slug (public) */
|
|
1433
|
+
blogBySlug?: BlogBySlugConfig;
|
|
1434
|
+
/** GET /api/forms/slug/:slug (public) */
|
|
1435
|
+
formBySlug?: FormBySlugConfig;
|
|
1436
|
+
/** POST/PUT /api/forms (save form + fields; when set, overrides CRUD for forms) */
|
|
1437
|
+
formSave?: FormSaveHandlersConfig;
|
|
1438
|
+
/** POST /api/form-submissions (public, no auth) */
|
|
1439
|
+
formSubmission?: FormSubmissionHandlerConfig;
|
|
1440
|
+
/** GET /api/form-submissions/:id (auth) with form + contact relations */
|
|
1441
|
+
formSubmissionGetById?: FormSubmissionGetByIdConfig;
|
|
1442
|
+
/** GET/POST /api/users, GET/PUT/DELETE /api/users/:id, POST /api/users/:id/regenerate-invite */
|
|
1443
|
+
usersApi?: UsersApiConfig;
|
|
1444
|
+
/** POST /api/users/avatar */
|
|
1445
|
+
userAvatar?: UserAvatarConfig;
|
|
1446
|
+
/** GET/PUT /api/users/profile (current session user) */
|
|
1447
|
+
userProfile?: UserProfileConfig;
|
|
1448
|
+
/** GET/PUT /api/settings/:group */
|
|
1449
|
+
settings?: SettingsApiConfig;
|
|
1450
|
+
/** GET /api/chat/config (public); POST /api/chat/identify; GET /api/chat/conversations/:id/messages; POST /api/chat/messages */
|
|
1451
|
+
chat?: ChatApiConfig;
|
|
1021
1452
|
/**
|
|
1022
|
-
*
|
|
1023
|
-
*
|
|
1453
|
+
* GET/POST /api/llm_agents/:slug/knowledge; DELETE …/knowledge/:documentId — agent KB ingest + links.
|
|
1454
|
+
* When omitted but `chat` is set, the same dataSource / entityMap / getCms / json / requireAuth are reused automatically.
|
|
1024
1455
|
*/
|
|
1025
|
-
|
|
1026
|
-
}
|
|
1027
|
-
declare function createSocialMediaHandlers(config: SocialMediaApiConfig): {
|
|
1028
|
-
getLinkedInStatus(req: Request): Promise<Response>;
|
|
1029
|
-
fetchLinkedInOrganizations(req: Request): Promise<Response>;
|
|
1030
|
-
syncLinkedInProfile(req: Request): Promise<Response>;
|
|
1031
|
-
publishBlogToLinkedIn(req: Request, blogId: number): Promise<Response>;
|
|
1032
|
-
getFacebookStatus(req: Request): Promise<Response>;
|
|
1033
|
-
publishBlogToFacebook(req: Request, blogId: number): Promise<Response>;
|
|
1456
|
+
llmAgentKnowledge?: LlmAgentKnowledgeApiConfig;
|
|
1034
1457
|
/**
|
|
1035
|
-
*
|
|
1036
|
-
*
|
|
1037
|
-
* Persist credentials via Plugins → Save: `meta_app_id` (public), `meta_app_secret` and `meta_user_access_token` (encrypted).
|
|
1458
|
+
* Entity-level RBAC (session `entityPerms` / Administrator). When omitted, admin routes that need it respond with 403
|
|
1459
|
+
* (`entity_rbac_required`) so CRUD cannot run as auth-only. Pass `createAuthHelpers(...).requireEntityPermission` from the app.
|
|
1038
1460
|
*/
|
|
1039
|
-
|
|
1461
|
+
requireEntityPermission?: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
1462
|
+
/** Required for vendor store RBAC + scoping. Alias: `getAuthenticatedUser`. */
|
|
1463
|
+
getSessionUser?: () => Promise<SessionUser | null>;
|
|
1464
|
+
/** Same as `getSessionUser` (from `createAuthHelpers().getAuthenticatedUser`). */
|
|
1465
|
+
getAuthenticatedUser?: () => Promise<SessionUser | null>;
|
|
1466
|
+
}
|
|
1467
|
+
declare function createCmsApiHandler(config: CmsApiHandlerConfig): {
|
|
1468
|
+
handle(method: string, pathInput: string[], req: Request): Promise<Response>;
|
|
1040
1469
|
};
|
|
1041
1470
|
|
|
1042
|
-
|
|
1043
|
-
|
|
1044
|
-
|
|
1045
|
-
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
type?: string;
|
|
1060
|
-
code?: number;
|
|
1061
|
-
fbtrace_id?: string;
|
|
1062
|
-
};
|
|
1063
|
-
};
|
|
1064
|
-
/**
|
|
1065
|
-
* Lists Facebook Pages the user manages (page access tokens + metadata).
|
|
1066
|
-
* Requires a User access token with `pages_show_list` or equivalent page permissions.
|
|
1067
|
-
*/
|
|
1068
|
-
declare function metaFetchUserManagedPages(userAccessToken: string): Promise<FacebookMeAccountsResponse>;
|
|
1069
|
-
type MetaGraphMutationResponse = {
|
|
1070
|
-
id?: string;
|
|
1071
|
-
post_id?: string;
|
|
1072
|
-
error?: {
|
|
1073
|
-
message?: string;
|
|
1074
|
-
type?: string;
|
|
1075
|
-
code?: number;
|
|
1076
|
-
fbtrace_id?: string;
|
|
1077
|
-
};
|
|
1471
|
+
interface JobScheduleApiConfig {
|
|
1472
|
+
dataSource: DataSource;
|
|
1473
|
+
entityMap: EntityMap$2;
|
|
1474
|
+
json: (body: unknown, init?: ResponseInit) => Response;
|
|
1475
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1476
|
+
requireEntityPermission?: (req: Request, entity: string, action: 'read' | 'create' | 'update' | 'delete') => Promise<Response | null>;
|
|
1477
|
+
getCms?: CmsGetter;
|
|
1478
|
+
config?: Record<string, string>;
|
|
1479
|
+
}
|
|
1480
|
+
declare function createJobScheduleHandlers(apiConfig: JobScheduleApiConfig): {
|
|
1481
|
+
list(req: Request): Promise<Response>;
|
|
1482
|
+
getById(req: Request, id: string): Promise<Response>;
|
|
1483
|
+
create(req: Request): Promise<Response>;
|
|
1484
|
+
update(req: Request, id: string): Promise<Response>;
|
|
1485
|
+
remove(req: Request, id: string): Promise<Response>;
|
|
1486
|
+
runNow(req: Request, id: string): Promise<Response>;
|
|
1487
|
+
listRuns(req: Request, id: string): Promise<Response>;
|
|
1078
1488
|
};
|
|
1079
|
-
/** Resolves the long-lived page access token for a Page ID from `/me/accounts` data. */
|
|
1080
|
-
declare function metaResolvePageAccessToken(accounts: FacebookMeAccountsResponse, pageId: string): string | null;
|
|
1081
|
-
/**
|
|
1082
|
-
* Upload a photo to a Page timeline (multipart).
|
|
1083
|
-
* @see https://developers.facebook.com/docs/graph-api/reference/page/photos#Creating
|
|
1084
|
-
*/
|
|
1085
|
-
declare function metaPostPagePhoto(opts: {
|
|
1086
|
-
pageId: string;
|
|
1087
|
-
pageAccessToken: string;
|
|
1088
|
-
imageBuffer: Buffer;
|
|
1089
|
-
contentType: string;
|
|
1090
|
-
caption: string;
|
|
1091
|
-
}): Promise<MetaGraphMutationResponse>;
|
|
1092
|
-
/**
|
|
1093
|
-
* Publish a text-only post to the Page feed (when no JPEG/PNG image is available).
|
|
1094
|
-
* @see https://developers.facebook.com/docs/graph-api/reference/page/feed#Creating
|
|
1095
|
-
*/
|
|
1096
|
-
declare function metaPostPageFeed(opts: {
|
|
1097
|
-
pageId: string;
|
|
1098
|
-
pageAccessToken: string;
|
|
1099
|
-
message: string;
|
|
1100
|
-
}): Promise<MetaGraphMutationResponse>;
|
|
1101
1489
|
|
|
1102
|
-
interface
|
|
1103
|
-
|
|
1104
|
-
|
|
1490
|
+
interface EventNotificationHandlersConfig {
|
|
1491
|
+
dataSource: DataSource;
|
|
1492
|
+
entityMap: EntityMap$2;
|
|
1493
|
+
json: (body: unknown, init?: {
|
|
1494
|
+
status?: number;
|
|
1495
|
+
}) => Response;
|
|
1496
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1497
|
+
requireEntityPermission?: RequireEntityPermissionFn;
|
|
1498
|
+
getCms?: () => Promise<CmsAppLike$3>;
|
|
1105
1499
|
}
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1111
|
-
name: string;
|
|
1112
|
-
} | undefined>;
|
|
1500
|
+
declare function createEventNotificationHandlers(config: EventNotificationHandlersConfig): {
|
|
1501
|
+
getSettings(req: Request, id: string): Promise<Response>;
|
|
1502
|
+
updateSettings(req: Request, id: string): Promise<Response>;
|
|
1503
|
+
sendTest(req: Request, id: string): Promise<Response>;
|
|
1504
|
+
};
|
|
1113
1505
|
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
ogTitle?: string | null;
|
|
1128
|
-
ogDescription?: string | null;
|
|
1129
|
-
ogImage?: string | null;
|
|
1130
|
-
};
|
|
1131
|
-
type SeoMetadataOverrides = {
|
|
1132
|
-
title?: string;
|
|
1133
|
-
description?: string;
|
|
1134
|
-
keywords?: string;
|
|
1135
|
-
ogTitle?: string;
|
|
1136
|
-
ogDescription?: string;
|
|
1137
|
-
ogImage?: string;
|
|
1138
|
-
};
|
|
1139
|
-
/** Per-field: join row wins over slug row. */
|
|
1140
|
-
declare function mergeSeoBySlug(join: SeoLike | null | undefined, bySlug: SeoLike | null): SeoLike | null;
|
|
1141
|
-
declare function fetchSeoBySlug(dataSource: DataSource, entityMap: EntityMap$2, slug: string): Promise<SeoLike | null>;
|
|
1142
|
-
/**
|
|
1143
|
-
* Build Next.js Metadata from merged SEO + optional layers.
|
|
1144
|
-
* `overrides` win over SEO; `fallbacks` apply when SEO (and overrides) omit a field.
|
|
1145
|
-
* Returns a partial object; omit fields so the root layout defaults apply.
|
|
1146
|
-
*/
|
|
1147
|
-
declare function resolvePublicMetadata(args: {
|
|
1148
|
-
dataSource: DataSource;
|
|
1149
|
-
entityMap: EntityMap$2;
|
|
1150
|
-
slug: string;
|
|
1151
|
-
seoFromJoin?: SeoLike | null;
|
|
1152
|
-
overrides?: SeoMetadataOverrides;
|
|
1153
|
-
fallbacks?: SeoMetadataOverrides;
|
|
1154
|
-
canonicalPath?: string;
|
|
1155
|
-
metadataBase?: URL;
|
|
1156
|
-
}): Promise<Metadata>;
|
|
1157
|
-
|
|
1158
|
-
/** Links an unclaimed contact (same email, no userId) to the new user after signup or invite. */
|
|
1159
|
-
declare function linkUnclaimedContactToUser(dataSource: DataSource, contactsEntity: EntityTarget<ObjectLiteral>, userId: number, email: string): Promise<void>;
|
|
1160
|
-
|
|
1161
|
-
/** Parse stored config value into a list of emails (JSON array, or comma/semicolon-separated string). */
|
|
1162
|
-
declare function parseEmailRecipientsFromConfig(raw: string | undefined | null): string[];
|
|
1163
|
-
/** Serialize email list for config storage (JSON array in DB). */
|
|
1164
|
-
declare function serializeEmailRecipients(emails: string[]): string;
|
|
1165
|
-
/** Join for SMTP `to` header (multiple recipients). */
|
|
1166
|
-
declare function joinRecipientsForSend(emails: string[]): string | null;
|
|
1167
|
-
|
|
1168
|
-
type OtpPurpose = 'login' | 'verify_email' | 'verify_phone';
|
|
1169
|
-
type OtpChannel = 'email' | 'sms';
|
|
1170
|
-
declare function hashOtpCode(code: string, purpose: string, identifier: string, pepper?: string): string;
|
|
1171
|
-
declare function verifyOtpCodeHash(code: string, storedHash: string, purpose: string, identifier: string, pepper?: string): boolean;
|
|
1172
|
-
declare function generateNumericOtp(length?: number): string;
|
|
1173
|
-
/** Normalize to E.164-like +digits */
|
|
1174
|
-
declare function normalizePhoneE164(raw: string, defaultCountryCode?: string): string | null;
|
|
1175
|
-
type EntityMap$1 = Record<string, EntityTarget<ObjectLiteral>>;
|
|
1176
|
-
declare function countRecentOtpSends(dataSource: DataSource, entityMap: EntityMap$1, purpose: OtpPurpose, identifier: string, since: Date): Promise<number>;
|
|
1177
|
-
declare function createOtpChallenge(dataSource: DataSource, entityMap: EntityMap$1, input: {
|
|
1178
|
-
purpose: OtpPurpose;
|
|
1179
|
-
channel: OtpChannel;
|
|
1180
|
-
identifier: string;
|
|
1181
|
-
code: string;
|
|
1182
|
-
pepper?: string;
|
|
1183
|
-
}): Promise<{
|
|
1184
|
-
ok: true;
|
|
1185
|
-
} | {
|
|
1186
|
-
ok: false;
|
|
1187
|
-
error: string;
|
|
1188
|
-
status: number;
|
|
1189
|
-
}>;
|
|
1190
|
-
declare function verifyAndConsumeOtpChallenge(dataSource: DataSource, entityMap: EntityMap$1, input: {
|
|
1191
|
-
purpose: OtpPurpose;
|
|
1192
|
-
identifier: string;
|
|
1193
|
-
code: string;
|
|
1194
|
-
pepper?: string;
|
|
1195
|
-
}): Promise<{
|
|
1196
|
-
ok: true;
|
|
1197
|
-
} | {
|
|
1198
|
-
ok: false;
|
|
1199
|
-
error: string;
|
|
1200
|
-
status: number;
|
|
1201
|
-
}>;
|
|
1202
|
-
|
|
1203
|
-
/** Returns true if request is allowed; false if rate limited. */
|
|
1204
|
-
declare function allowRateLimit(key: string): Promise<boolean>;
|
|
1205
|
-
type ExtraPublicWriteRule = (method: string, segments: string[]) => boolean;
|
|
1206
|
-
/** Segments are path parts after `/api/` (e.g. `['form-submissions']`). */
|
|
1207
|
-
declare function shouldRateLimitPublicWrite(method: string, segments: string[], extraRule?: ExtraPublicWriteRule): boolean;
|
|
1208
|
-
declare function rateLimitKeyForApiRequest(req: Request, segments: string[]): string;
|
|
1209
|
-
declare function rateLimitPublicApiIfNeeded(req: Request, method: string, segments: string[], options?: {
|
|
1210
|
-
extraRule?: ExtraPublicWriteRule;
|
|
1211
|
-
}): Promise<Response | null>;
|
|
1212
|
-
declare function rateLimitCheckoutPost(req: Request): Promise<Response | null>;
|
|
1213
|
-
|
|
1214
|
-
interface EntityMapLike {
|
|
1215
|
-
configs: unknown;
|
|
1216
|
-
orders: unknown;
|
|
1217
|
-
order_items: unknown;
|
|
1218
|
-
}
|
|
1219
|
-
interface SendOrderPlacedEmailDeps {
|
|
1220
|
-
getDataSource: () => Promise<DataSource>;
|
|
1221
|
-
entityMap: EntityMapLike;
|
|
1222
|
-
getCms: () => Promise<CmsApp>;
|
|
1223
|
-
}
|
|
1224
|
-
/** After payment confirmation: email customer + each sales team address from plugin settings. */
|
|
1225
|
-
declare function sendOrderPlacedEmailsAfterConfirmation(orderId: number, deps: SendOrderPlacedEmailDeps): Promise<void>;
|
|
1226
|
-
|
|
1227
|
-
interface DataSourceManager {
|
|
1228
|
-
getDataSource: () => DataSource;
|
|
1229
|
-
getDataSourceInitialized: () => Promise<DataSource>;
|
|
1230
|
-
resetDataSource: () => void;
|
|
1231
|
-
registerOnReset: (cb: () => void) => void;
|
|
1232
|
-
isConnectionError: (e: unknown) => boolean;
|
|
1233
|
-
}
|
|
1234
|
-
declare function createDataSourceManager(entityMap: Record<string, unknown>, options?: {
|
|
1235
|
-
databaseUrl?: string;
|
|
1236
|
-
idleTimeoutMillis?: number;
|
|
1237
|
-
}): DataSourceManager;
|
|
1238
|
-
|
|
1239
|
-
interface SeedEntityMap {
|
|
1240
|
-
users: unknown;
|
|
1241
|
-
user_groups: unknown;
|
|
1242
|
-
}
|
|
1243
|
-
declare function seedDefaultAdmin(ds: DataSource, entityMap: SeedEntityMap, opts?: {
|
|
1244
|
-
email?: string;
|
|
1245
|
-
password?: string;
|
|
1246
|
-
}): Promise<void>;
|
|
1247
|
-
|
|
1248
|
-
type VendorInviteStatus = 'none' | 'pending' | 'expired' | 'accepted';
|
|
1249
|
-
declare class Vendor {
|
|
1250
|
-
id: number;
|
|
1251
|
-
name: string;
|
|
1252
|
-
slug: string;
|
|
1253
|
-
email: string | null;
|
|
1254
|
-
phone: string | null;
|
|
1255
|
-
logo: string | null;
|
|
1256
|
-
description: string | null;
|
|
1257
|
-
metadata: Record<string, unknown> | null;
|
|
1258
|
-
active: boolean;
|
|
1259
|
-
/** Primary owner user for this vendor (set on onboard). */
|
|
1260
|
-
userId: number | null;
|
|
1261
|
-
inviteStatus: VendorInviteStatus;
|
|
1262
|
-
createdAt: Date;
|
|
1263
|
-
updatedAt: Date;
|
|
1264
|
-
deletedAt: Date | null;
|
|
1265
|
-
deleted: boolean;
|
|
1266
|
-
createdBy: number | null;
|
|
1267
|
-
updatedBy: number | null;
|
|
1268
|
-
deletedBy: number | null;
|
|
1269
|
-
vendorUsers: VendorUser[];
|
|
1270
|
-
}
|
|
1506
|
+
interface EventOrderMessageTemplateHandlersConfig {
|
|
1507
|
+
dataSource: DataSource;
|
|
1508
|
+
entityMap: EntityMap$2;
|
|
1509
|
+
json: (body: unknown, init?: {
|
|
1510
|
+
status?: number;
|
|
1511
|
+
}) => Response;
|
|
1512
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
1513
|
+
requireEntityPermission?: RequireEntityPermissionFn;
|
|
1514
|
+
}
|
|
1515
|
+
declare function createEventOrderMessageTemplateHandlers(config: EventOrderMessageTemplateHandlersConfig): {
|
|
1516
|
+
GET(req: Request): Promise<Response>;
|
|
1517
|
+
PUT(req: Request): Promise<Response>;
|
|
1518
|
+
};
|
|
1271
1519
|
|
|
1272
1520
|
declare class Permission {
|
|
1273
1521
|
id: number;
|
|
@@ -1323,117 +1571,138 @@ declare class User {
|
|
|
1323
1571
|
group: UserGroup | null;
|
|
1324
1572
|
}
|
|
1325
1573
|
|
|
1574
|
+
declare class VendorRolePermission {
|
|
1575
|
+
id: number;
|
|
1576
|
+
vendorRoleId: number;
|
|
1577
|
+
entity: string;
|
|
1578
|
+
canCreate: boolean;
|
|
1579
|
+
canRead: boolean;
|
|
1580
|
+
canUpdate: boolean;
|
|
1581
|
+
canDelete: boolean;
|
|
1582
|
+
createdAt: Date;
|
|
1583
|
+
updatedAt: Date;
|
|
1584
|
+
role: VendorRole;
|
|
1585
|
+
}
|
|
1586
|
+
|
|
1587
|
+
declare class VendorRole {
|
|
1588
|
+
id: number;
|
|
1589
|
+
vendorId: number;
|
|
1590
|
+
name: string;
|
|
1591
|
+
description: string | null;
|
|
1592
|
+
isSystem: boolean;
|
|
1593
|
+
isOwnerRole: boolean;
|
|
1594
|
+
createdAt: Date;
|
|
1595
|
+
updatedAt: Date;
|
|
1596
|
+
deletedAt: Date | null;
|
|
1597
|
+
deleted: boolean;
|
|
1598
|
+
vendor: Vendor;
|
|
1599
|
+
permissions: VendorRolePermission[];
|
|
1600
|
+
}
|
|
1601
|
+
|
|
1326
1602
|
/** Links a staff user to a vendor store. */
|
|
1327
1603
|
type VendorUserRole = 'owner' | 'staff';
|
|
1328
1604
|
declare class VendorUser {
|
|
1329
1605
|
id: number;
|
|
1330
1606
|
vendorId: number;
|
|
1331
1607
|
userId: number;
|
|
1608
|
+
/** @deprecated use vendorRoleId — kept for migration compatibility */
|
|
1332
1609
|
role: VendorUserRole;
|
|
1610
|
+
vendorRoleId: number | null;
|
|
1333
1611
|
createdAt: Date;
|
|
1334
1612
|
updatedAt: Date;
|
|
1335
1613
|
vendor: Vendor;
|
|
1336
1614
|
user: User;
|
|
1615
|
+
vendorRole: VendorRole | null;
|
|
1337
1616
|
}
|
|
1338
1617
|
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
|
|
1351
|
-
|
|
1618
|
+
type VendorInviteStatus = 'none' | 'pending' | 'expired' | 'accepted';
|
|
1619
|
+
type VendorRegistrationStatus = 'pending' | 'approved' | 'rejected' | 'suspended';
|
|
1620
|
+
declare class Vendor {
|
|
1621
|
+
id: number;
|
|
1622
|
+
name: string;
|
|
1623
|
+
slug: string;
|
|
1624
|
+
email: string | null;
|
|
1625
|
+
phone: string | null;
|
|
1626
|
+
legalName: string | null;
|
|
1627
|
+
businessType: string | null;
|
|
1628
|
+
website: string | null;
|
|
1629
|
+
addressLine1: string | null;
|
|
1630
|
+
addressLine2: string | null;
|
|
1631
|
+
city: string | null;
|
|
1632
|
+
state: string | null;
|
|
1633
|
+
country: string | null;
|
|
1634
|
+
postalCode: string | null;
|
|
1635
|
+
gstin: string | null;
|
|
1636
|
+
pan: string | null;
|
|
1637
|
+
logo: string | null;
|
|
1638
|
+
description: string | null;
|
|
1639
|
+
metadata: Record<string, unknown> | null;
|
|
1640
|
+
active: boolean;
|
|
1641
|
+
/** Primary owner user for this vendor (set on onboard). */
|
|
1642
|
+
userId: number | null;
|
|
1643
|
+
inviteStatus: VendorInviteStatus;
|
|
1644
|
+
registrationStatus: VendorRegistrationStatus;
|
|
1645
|
+
createdAt: Date;
|
|
1646
|
+
updatedAt: Date;
|
|
1647
|
+
deletedAt: Date | null;
|
|
1648
|
+
deleted: boolean;
|
|
1649
|
+
createdBy: number | null;
|
|
1650
|
+
updatedBy: number | null;
|
|
1651
|
+
deletedBy: number | null;
|
|
1652
|
+
vendorUsers: VendorUser[];
|
|
1653
|
+
}
|
|
1352
1654
|
|
|
1353
|
-
|
|
1354
|
-
|
|
1655
|
+
declare class FormField {
|
|
1656
|
+
id: number;
|
|
1657
|
+
formId: number;
|
|
1658
|
+
label: string;
|
|
1659
|
+
type: string;
|
|
1660
|
+
placeholder: string | null;
|
|
1661
|
+
options: string | null;
|
|
1662
|
+
required: boolean;
|
|
1663
|
+
validation: string | null;
|
|
1664
|
+
order: number;
|
|
1665
|
+
groupId: number;
|
|
1666
|
+
columnWidth: number;
|
|
1667
|
+
createdAt: Date;
|
|
1668
|
+
updatedAt: Date;
|
|
1669
|
+
deletedAt: Date | null;
|
|
1670
|
+
deleted: boolean;
|
|
1671
|
+
createdBy: number | null;
|
|
1672
|
+
updatedBy: number | null;
|
|
1673
|
+
deletedBy: number | null;
|
|
1674
|
+
form: Form;
|
|
1675
|
+
}
|
|
1355
1676
|
|
|
1356
|
-
|
|
1357
|
-
|
|
1358
|
-
|
|
1359
|
-
|
|
1360
|
-
|
|
1361
|
-
|
|
1677
|
+
declare class Address {
|
|
1678
|
+
id: number;
|
|
1679
|
+
contactId: number;
|
|
1680
|
+
tag: string | null;
|
|
1681
|
+
line1: string | null;
|
|
1682
|
+
line2: string | null;
|
|
1683
|
+
city: string | null;
|
|
1684
|
+
state: string | null;
|
|
1685
|
+
postalCode: string | null;
|
|
1686
|
+
country: string | null;
|
|
1687
|
+
createdAt: Date;
|
|
1688
|
+
updatedAt: Date;
|
|
1689
|
+
contact: Contact;
|
|
1362
1690
|
}
|
|
1363
|
-
declare function loadPublicThemeSettings(config: {
|
|
1364
|
-
dataSource: DataSource;
|
|
1365
|
-
entityMap: EntityMap$2;
|
|
1366
|
-
encryptionKey?: string;
|
|
1367
|
-
defaultActiveThemeId?: string;
|
|
1368
|
-
defaultPrimaryColor?: string;
|
|
1369
|
-
defaultSecondaryColor?: string;
|
|
1370
|
-
}): Promise<PublicThemeSettingsPayload>;
|
|
1371
1691
|
|
|
1372
|
-
|
|
1373
|
-
declare function sanitizeMediaFolderPath(input: unknown): string;
|
|
1374
|
-
/** Single path segment for storage (folder name or legacy path segment). */
|
|
1375
|
-
declare function sanitizeStorageSegment(name: string): string;
|
|
1376
|
-
|
|
1377
|
-
type EntityMap = Record<string, EntityTarget<ObjectLiteral>>;
|
|
1378
|
-
/** Build `a/b/c` path under `uploads/` from the chain of folder rows up to root. */
|
|
1379
|
-
declare function relativePathFromMediaParentId(dataSource: DataSource, entityMap: EntityMap, parentId: number | null): Promise<string>;
|
|
1380
|
-
|
|
1381
|
-
declare const ZIP_MIME_TYPES: Set<string>;
|
|
1382
|
-
declare function isZipMedia(mime: string | null | undefined, filename: string): boolean;
|
|
1383
|
-
|
|
1384
|
-
/**
|
|
1385
|
-
* Executes `fn` inside a transaction where the PostgreSQL GUC
|
|
1386
|
-
* `app.vendor_id` is set for the duration of that transaction.
|
|
1387
|
-
*
|
|
1388
|
-
* This activates the `vendor_isolation` RLS policy added by the
|
|
1389
|
-
* `VendorRls1775940000000` migration.
|
|
1390
|
-
*
|
|
1391
|
-
* vendorId = 0 → admin / all-access (policy allows everything)
|
|
1392
|
-
* vendorId > 0 → only rows whose `vendorId` column matches
|
|
1393
|
-
*
|
|
1394
|
-
* Example:
|
|
1395
|
-
* const orders = await withVendorRlsContext(dataSource, 4, (ds) =>
|
|
1396
|
-
* ds.getRepository(Order).find({ where: { deleted: false } })
|
|
1397
|
-
* );
|
|
1398
|
-
*/
|
|
1399
|
-
declare function withVendorRlsContext<T>(dataSource: DataSource, vendorId: number, fn: (dataSource: DataSource) => Promise<T>): Promise<T>;
|
|
1400
|
-
/**
|
|
1401
|
-
* Convenience wrapper: sets admin mode (vendor_id = '0') so all rows are
|
|
1402
|
-
* visible regardless of their vendorId. Use for platform-admin queries.
|
|
1403
|
-
*/
|
|
1404
|
-
declare function withAdminRlsContext<T>(dataSource: DataSource, fn: (dataSource: DataSource) => Promise<T>): Promise<T>;
|
|
1405
|
-
|
|
1406
|
-
declare function isCustomerTypeContact(type: unknown): boolean;
|
|
1407
|
-
/** Restrict contact list to rows linked in `vendor_customers` with type customer. */
|
|
1408
|
-
declare function applyVendorCustomersContactFilter(qb: SelectQueryBuilder<typeorm.ObjectLiteral>, contactAlias: string, scope: VendorScope, vendorIdFilter: number | null): void;
|
|
1409
|
-
declare function contactIsVendorCustomer(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number, contactId: number): Promise<boolean>;
|
|
1410
|
-
/** Returns an error message when the contact is not a vendor-linked customer; otherwise null. */
|
|
1411
|
-
declare function assertContactAllowedForVendorOrder(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number, contactId: number): Promise<string | null>;
|
|
1412
|
-
declare function resolveVendorIdForContactCheck(scope: VendorScope, bodyOrRow: Record<string, unknown>): number | null;
|
|
1413
|
-
|
|
1414
|
-
declare class OtpChallenge {
|
|
1415
|
-
id: number;
|
|
1416
|
-
purpose: string;
|
|
1417
|
-
channel: string;
|
|
1418
|
-
identifier: string;
|
|
1419
|
-
codeHash: string;
|
|
1420
|
-
expiresAt: Date;
|
|
1421
|
-
attempts: number;
|
|
1422
|
-
consumedAt: Date | null;
|
|
1423
|
-
createdAt: Date;
|
|
1424
|
-
}
|
|
1425
|
-
|
|
1426
|
-
declare class PasswordResetToken {
|
|
1427
|
-
id: number;
|
|
1428
|
-
email: string;
|
|
1429
|
-
token: string;
|
|
1430
|
-
expiresAt: Date;
|
|
1431
|
-
createdAt: Date;
|
|
1432
|
-
}
|
|
1433
|
-
|
|
1434
|
-
declare class Category {
|
|
1692
|
+
declare class ProductCategory {
|
|
1435
1693
|
id: number;
|
|
1694
|
+
/** Null for platform catalog categories (`isCatalog`). */
|
|
1695
|
+
vendorId: number | null;
|
|
1696
|
+
/** Platform-wide catalog type — all vendors add collections/products under these categories. */
|
|
1697
|
+
isCatalog: boolean;
|
|
1436
1698
|
name: string;
|
|
1699
|
+
slug: string;
|
|
1700
|
+
parentId: number | null;
|
|
1701
|
+
image: string | null;
|
|
1702
|
+
description: string | null;
|
|
1703
|
+
metadata: Record<string, unknown> | null;
|
|
1704
|
+
active: boolean;
|
|
1705
|
+
sortOrder: number;
|
|
1437
1706
|
createdAt: Date;
|
|
1438
1707
|
updatedAt: Date;
|
|
1439
1708
|
deletedAt: Date | null;
|
|
@@ -1441,18 +1710,16 @@ declare class Category {
|
|
|
1441
1710
|
createdBy: number | null;
|
|
1442
1711
|
updatedBy: number | null;
|
|
1443
1712
|
deletedBy: number | null;
|
|
1444
|
-
|
|
1713
|
+
vendor: Vendor | null;
|
|
1714
|
+
parent: ProductCategory | null;
|
|
1715
|
+
children: ProductCategory[];
|
|
1716
|
+
products: Product[];
|
|
1717
|
+
collections: Collection[];
|
|
1445
1718
|
}
|
|
1446
1719
|
|
|
1447
|
-
declare class
|
|
1720
|
+
declare class Category {
|
|
1448
1721
|
id: number;
|
|
1449
|
-
|
|
1450
|
-
description: string | null;
|
|
1451
|
-
keywords: string | null;
|
|
1452
|
-
ogTitle: string | null;
|
|
1453
|
-
ogDescription: string | null;
|
|
1454
|
-
ogImage: string | null;
|
|
1455
|
-
slug: string;
|
|
1722
|
+
name: string;
|
|
1456
1723
|
createdAt: Date;
|
|
1457
1724
|
updatedAt: Date;
|
|
1458
1725
|
deletedAt: Date | null;
|
|
@@ -1518,85 +1785,15 @@ declare class Blog {
|
|
|
1518
1785
|
tags: Tag[];
|
|
1519
1786
|
}
|
|
1520
1787
|
|
|
1521
|
-
declare class
|
|
1522
|
-
id: number;
|
|
1523
|
-
formId: number;
|
|
1524
|
-
label: string;
|
|
1525
|
-
type: string;
|
|
1526
|
-
placeholder: string | null;
|
|
1527
|
-
options: string | null;
|
|
1528
|
-
required: boolean;
|
|
1529
|
-
validation: string | null;
|
|
1530
|
-
order: number;
|
|
1531
|
-
groupId: number;
|
|
1532
|
-
columnWidth: number;
|
|
1533
|
-
createdAt: Date;
|
|
1534
|
-
updatedAt: Date;
|
|
1535
|
-
deletedAt: Date | null;
|
|
1536
|
-
deleted: boolean;
|
|
1537
|
-
createdBy: number | null;
|
|
1538
|
-
updatedBy: number | null;
|
|
1539
|
-
deletedBy: number | null;
|
|
1540
|
-
form: Form;
|
|
1541
|
-
}
|
|
1542
|
-
|
|
1543
|
-
declare class Form {
|
|
1788
|
+
declare class Seo {
|
|
1544
1789
|
id: number;
|
|
1545
|
-
|
|
1790
|
+
title: string | null;
|
|
1546
1791
|
description: string | null;
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
updatedAt: Date;
|
|
1552
|
-
deletedAt: Date | null;
|
|
1553
|
-
deleted: boolean;
|
|
1554
|
-
createdBy: number | null;
|
|
1555
|
-
updatedBy: number | null;
|
|
1556
|
-
deletedBy: number | null;
|
|
1557
|
-
fields: FormField[];
|
|
1558
|
-
submissions: FormSubmission[];
|
|
1559
|
-
}
|
|
1560
|
-
|
|
1561
|
-
declare class FormSubmission {
|
|
1562
|
-
id: number;
|
|
1563
|
-
formId: number;
|
|
1564
|
-
contactId: number | null;
|
|
1565
|
-
data: Record<string, unknown>;
|
|
1566
|
-
ipAddress: string | null;
|
|
1567
|
-
userAgent: string | null;
|
|
1568
|
-
createdAt: Date;
|
|
1569
|
-
updatedAt: Date;
|
|
1570
|
-
form: Form;
|
|
1571
|
-
contact: Contact | null;
|
|
1572
|
-
}
|
|
1573
|
-
|
|
1574
|
-
declare class Address {
|
|
1575
|
-
id: number;
|
|
1576
|
-
contactId: number;
|
|
1577
|
-
tag: string | null;
|
|
1578
|
-
line1: string | null;
|
|
1579
|
-
line2: string | null;
|
|
1580
|
-
city: string | null;
|
|
1581
|
-
state: string | null;
|
|
1582
|
-
postalCode: string | null;
|
|
1583
|
-
country: string | null;
|
|
1584
|
-
createdAt: Date;
|
|
1585
|
-
updatedAt: Date;
|
|
1586
|
-
contact: Contact;
|
|
1587
|
-
}
|
|
1588
|
-
|
|
1589
|
-
declare class ProductCategory {
|
|
1590
|
-
id: number;
|
|
1591
|
-
vendorId: number;
|
|
1592
|
-
name: string;
|
|
1792
|
+
keywords: string | null;
|
|
1793
|
+
ogTitle: string | null;
|
|
1794
|
+
ogDescription: string | null;
|
|
1795
|
+
ogImage: string | null;
|
|
1593
1796
|
slug: string;
|
|
1594
|
-
parentId: number | null;
|
|
1595
|
-
image: string | null;
|
|
1596
|
-
description: string | null;
|
|
1597
|
-
metadata: Record<string, unknown> | null;
|
|
1598
|
-
active: boolean;
|
|
1599
|
-
sortOrder: number;
|
|
1600
1797
|
createdAt: Date;
|
|
1601
1798
|
updatedAt: Date;
|
|
1602
1799
|
deletedAt: Date | null;
|
|
@@ -1604,11 +1801,7 @@ declare class ProductCategory {
|
|
|
1604
1801
|
createdBy: number | null;
|
|
1605
1802
|
updatedBy: number | null;
|
|
1606
1803
|
deletedBy: number | null;
|
|
1607
|
-
|
|
1608
|
-
parent: ProductCategory | null;
|
|
1609
|
-
children: ProductCategory[];
|
|
1610
|
-
products: Product[];
|
|
1611
|
-
collections: Collection[];
|
|
1804
|
+
blogs: Blog[];
|
|
1612
1805
|
}
|
|
1613
1806
|
|
|
1614
1807
|
declare class Brand {
|
|
@@ -1637,7 +1830,8 @@ declare class Brand {
|
|
|
1637
1830
|
|
|
1638
1831
|
declare class Collection {
|
|
1639
1832
|
id: number;
|
|
1640
|
-
|
|
1833
|
+
/** Null for platform catalog collections (`isCatalog`). */
|
|
1834
|
+
vendorId: number | null;
|
|
1641
1835
|
categoryId: number | null;
|
|
1642
1836
|
brandId: number | null;
|
|
1643
1837
|
name: string;
|
|
@@ -1648,6 +1842,8 @@ declare class Collection {
|
|
|
1648
1842
|
metadata: Record<string, unknown> | null;
|
|
1649
1843
|
variants: Array<Record<string, unknown>> | null;
|
|
1650
1844
|
active: boolean;
|
|
1845
|
+
/** Platform-wide catalog type — all vendors add products under these collections. */
|
|
1846
|
+
isCatalog: boolean;
|
|
1651
1847
|
sortOrder: number;
|
|
1652
1848
|
createdAt: Date;
|
|
1653
1849
|
updatedAt: Date;
|
|
@@ -1657,7 +1853,7 @@ declare class Collection {
|
|
|
1657
1853
|
updatedBy: number | null;
|
|
1658
1854
|
deletedBy: number | null;
|
|
1659
1855
|
seoId: number | null;
|
|
1660
|
-
vendor: Vendor;
|
|
1856
|
+
vendor: Vendor | null;
|
|
1661
1857
|
seo: Seo | null;
|
|
1662
1858
|
category: ProductCategory | null;
|
|
1663
1859
|
brand: Brand | null;
|
|
@@ -1716,15 +1912,64 @@ declare class Tax {
|
|
|
1716
1912
|
vendor: Vendor;
|
|
1717
1913
|
}
|
|
1718
1914
|
|
|
1719
|
-
declare
|
|
1915
|
+
declare enum RefundPolicyStatus {
|
|
1916
|
+
ACTIVE = "active",
|
|
1917
|
+
INACTIVE = "inactive"
|
|
1918
|
+
}
|
|
1919
|
+
declare enum RefundPolicyType$1 {
|
|
1920
|
+
PERCENTAGE = "percentage",
|
|
1921
|
+
EVENT_TIERS = "event_tiers"
|
|
1922
|
+
}
|
|
1923
|
+
type RefundPolicyTierRow = {
|
|
1924
|
+
fromDaysBefore: number;
|
|
1925
|
+
toDaysBefore: number | null;
|
|
1926
|
+
percentage: number;
|
|
1927
|
+
};
|
|
1928
|
+
declare class RefundPolicy {
|
|
1929
|
+
id: number;
|
|
1930
|
+
name: string;
|
|
1931
|
+
desc?: string;
|
|
1932
|
+
vendorId: number;
|
|
1933
|
+
vendor: Vendor;
|
|
1934
|
+
refundWindowDays: number;
|
|
1935
|
+
status: RefundPolicyStatus;
|
|
1936
|
+
type: RefundPolicyType$1;
|
|
1937
|
+
value: number;
|
|
1938
|
+
/** Day bands before event start → refund % (when type is event_tiers). */
|
|
1939
|
+
tiers?: RefundPolicyTierRow[] | null;
|
|
1940
|
+
productConfigs: ProductConfig[];
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
declare class ProductConfig {
|
|
1720
1944
|
id: number;
|
|
1721
1945
|
productId: number;
|
|
1722
1946
|
taxId: number;
|
|
1947
|
+
refundPolicyId: number | null;
|
|
1723
1948
|
rate: number | null;
|
|
1724
1949
|
createdAt: Date;
|
|
1725
1950
|
updatedAt: Date;
|
|
1726
1951
|
product: Product;
|
|
1727
1952
|
tax: Tax;
|
|
1953
|
+
refundPolicy: RefundPolicy | null;
|
|
1954
|
+
}
|
|
1955
|
+
|
|
1956
|
+
type ProductVariantStatus = 'draft' | 'available' | 'reserved' | 'sold';
|
|
1957
|
+
/** Option dimensions (Color, Size, …) plus optional `image_url` for PDP image switching. */
|
|
1958
|
+
type ProductVariantAttributes = Record<string, string>;
|
|
1959
|
+
declare class ProductVariant {
|
|
1960
|
+
id: number;
|
|
1961
|
+
productId: number;
|
|
1962
|
+
sku: string | null;
|
|
1963
|
+
price: number | null;
|
|
1964
|
+
compareAtPrice: number | null;
|
|
1965
|
+
currencyPrices: Record<string, number> | null;
|
|
1966
|
+
inventory: number;
|
|
1967
|
+
status: ProductVariantStatus;
|
|
1968
|
+
attributes: ProductVariantAttributes | null;
|
|
1969
|
+
imageUrls: string[] | null;
|
|
1970
|
+
createdAt: Date;
|
|
1971
|
+
updatedAt: Date;
|
|
1972
|
+
product: Product;
|
|
1728
1973
|
}
|
|
1729
1974
|
|
|
1730
1975
|
declare class Product {
|
|
@@ -1740,8 +1985,11 @@ declare class Product {
|
|
|
1740
1985
|
type: 'product' | 'service';
|
|
1741
1986
|
slug: string | null;
|
|
1742
1987
|
name: string | null;
|
|
1988
|
+
/** Optional display title (kept in sync with `name` by the products API). */
|
|
1989
|
+
title: string | null;
|
|
1743
1990
|
price: number;
|
|
1744
1991
|
compareAtPrice: number | null;
|
|
1992
|
+
currencyPrices: Record<string, number> | null;
|
|
1745
1993
|
quantity: number;
|
|
1746
1994
|
status: 'draft' | 'available' | 'reserved' | 'sold';
|
|
1747
1995
|
featured: boolean;
|
|
@@ -1754,13 +2002,17 @@ declare class Product {
|
|
|
1754
2002
|
updatedBy: number | null;
|
|
1755
2003
|
deletedBy: number | null;
|
|
1756
2004
|
seoId: number | null;
|
|
2005
|
+
/** CMS form used for product checkout / attendee capture. */
|
|
2006
|
+
contactFormId: number | null;
|
|
1757
2007
|
vendor: Vendor;
|
|
1758
2008
|
seo: Seo | null;
|
|
2009
|
+
contactForm: Form | null;
|
|
1759
2010
|
collection: Collection | null;
|
|
1760
2011
|
brand: Brand | null;
|
|
1761
2012
|
category: ProductCategory | null;
|
|
1762
2013
|
attributes: ProductAttribute[];
|
|
1763
|
-
taxes:
|
|
2014
|
+
taxes: ProductConfig[];
|
|
2015
|
+
variants: ProductVariant[];
|
|
1764
2016
|
}
|
|
1765
2017
|
|
|
1766
2018
|
declare class OrderItem {
|
|
@@ -1768,6 +2020,8 @@ declare class OrderItem {
|
|
|
1768
2020
|
orderId: number;
|
|
1769
2021
|
productId: number;
|
|
1770
2022
|
discountIds: number[];
|
|
2023
|
+
vendorId: number | null;
|
|
2024
|
+
vendor: Vendor | null;
|
|
1771
2025
|
quantity: number;
|
|
1772
2026
|
unitPrice: number;
|
|
1773
2027
|
subTotal: number;
|
|
@@ -1789,6 +2043,13 @@ declare class OrderItem {
|
|
|
1789
2043
|
product: Product;
|
|
1790
2044
|
}
|
|
1791
2045
|
|
|
2046
|
+
declare enum PaymentStatus {
|
|
2047
|
+
Unpaid = "unpaid",
|
|
2048
|
+
Paid = "paid",
|
|
2049
|
+
Pending = "pending",
|
|
2050
|
+
Failed = "failed",
|
|
2051
|
+
Refunded = "refunded"
|
|
2052
|
+
}
|
|
1792
2053
|
declare class Payment {
|
|
1793
2054
|
id: number;
|
|
1794
2055
|
vendorId: number;
|
|
@@ -1796,7 +2057,7 @@ declare class Payment {
|
|
|
1796
2057
|
contactId: number | null;
|
|
1797
2058
|
amount: number;
|
|
1798
2059
|
currency: string;
|
|
1799
|
-
status:
|
|
2060
|
+
status: PaymentStatus;
|
|
1800
2061
|
method: string | null;
|
|
1801
2062
|
externalReference: string | null;
|
|
1802
2063
|
metadata: Record<string, unknown> | null;
|
|
@@ -1812,107 +2073,1109 @@ declare class Payment {
|
|
|
1812
2073
|
order: Order;
|
|
1813
2074
|
contact: Contact | null;
|
|
1814
2075
|
}
|
|
1815
|
-
|
|
1816
|
-
declare enum AddressType {
|
|
1817
|
-
SHIPPING_ADDRESS = "shipping_address",
|
|
1818
|
-
BILLING_ADDRESS = "billing_address"
|
|
2076
|
+
|
|
2077
|
+
declare enum AddressType {
|
|
2078
|
+
SHIPPING_ADDRESS = "shipping_address",
|
|
2079
|
+
BILLING_ADDRESS = "billing_address"
|
|
2080
|
+
}
|
|
2081
|
+
declare class OrderAddresses {
|
|
2082
|
+
id: number;
|
|
2083
|
+
contactId: number;
|
|
2084
|
+
addressType: AddressType;
|
|
2085
|
+
line1: string;
|
|
2086
|
+
line2: string | null;
|
|
2087
|
+
city: string;
|
|
2088
|
+
state: string;
|
|
2089
|
+
postalCode: string;
|
|
2090
|
+
country: string;
|
|
2091
|
+
createdAt: Date;
|
|
2092
|
+
updatedAt: Date;
|
|
2093
|
+
contact: Contact;
|
|
2094
|
+
billingOrders: Order[];
|
|
2095
|
+
shippingOrders: Order[];
|
|
2096
|
+
}
|
|
2097
|
+
|
|
2098
|
+
declare class Customer {
|
|
2099
|
+
id: number;
|
|
2100
|
+
userId: number;
|
|
2101
|
+
user: User | null;
|
|
2102
|
+
name: string;
|
|
2103
|
+
email: string;
|
|
2104
|
+
phone: string;
|
|
2105
|
+
createdAt: Date;
|
|
2106
|
+
updatedAt: Date;
|
|
2107
|
+
deletedAt: Date | null;
|
|
2108
|
+
deleted: boolean;
|
|
2109
|
+
createdBy: number | null;
|
|
2110
|
+
updatedBy: number | null;
|
|
2111
|
+
deletedBy: number | null;
|
|
2112
|
+
}
|
|
2113
|
+
|
|
2114
|
+
declare class Customer_Contacts {
|
|
2115
|
+
id: number;
|
|
2116
|
+
customerId: number;
|
|
2117
|
+
customer: Customer;
|
|
2118
|
+
contactId: number;
|
|
2119
|
+
contact: Contact;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
type OrderKind = 'sale' | 'return' | 'replacement';
|
|
2123
|
+
declare enum OrderStatus {
|
|
2124
|
+
Pending = "pending",
|
|
2125
|
+
Confirmed = "confirmed",
|
|
2126
|
+
Processing = "processing",
|
|
2127
|
+
Completed = "completed",
|
|
2128
|
+
Cancelled = "cancelled"
|
|
2129
|
+
}
|
|
2130
|
+
declare class Order {
|
|
2131
|
+
id: number;
|
|
2132
|
+
vendorId: number;
|
|
2133
|
+
orderNumber: string;
|
|
2134
|
+
qrToken: string | null;
|
|
2135
|
+
orderKind: OrderKind;
|
|
2136
|
+
parentOrderId: number | null;
|
|
2137
|
+
contactId: number;
|
|
2138
|
+
/** Junction row linking the account customer to the checkout contact (storefront checkout). */
|
|
2139
|
+
customerContactId: number | null;
|
|
2140
|
+
billingAddressId: number | null;
|
|
2141
|
+
shippingAddressId: number | null;
|
|
2142
|
+
status: OrderStatus;
|
|
2143
|
+
subtotal: number;
|
|
2144
|
+
tax: number;
|
|
2145
|
+
discount: number;
|
|
2146
|
+
total: number;
|
|
2147
|
+
currency: string;
|
|
2148
|
+
metadata: Record<string, unknown> | null;
|
|
2149
|
+
createdAt: Date;
|
|
2150
|
+
updatedAt: Date;
|
|
2151
|
+
deletedAt: Date | null;
|
|
2152
|
+
deleted: boolean;
|
|
2153
|
+
createdBy: number | null;
|
|
2154
|
+
updatedBy: number | null;
|
|
2155
|
+
deletedBy: number | null;
|
|
2156
|
+
vendor: Vendor;
|
|
2157
|
+
parentOrder: Order | null;
|
|
2158
|
+
children: Order[];
|
|
2159
|
+
contact: Contact;
|
|
2160
|
+
customerContact: Customer_Contacts | null;
|
|
2161
|
+
billingAddress: OrderAddresses | null;
|
|
2162
|
+
shippingAddress: OrderAddresses | null;
|
|
2163
|
+
items: OrderItem[];
|
|
2164
|
+
payments: Payment[];
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
declare class ChatMessage {
|
|
2168
|
+
id: number;
|
|
2169
|
+
conversationId: number;
|
|
2170
|
+
role: 'user' | 'assistant' | 'system';
|
|
2171
|
+
content: string;
|
|
2172
|
+
createdAt: Date;
|
|
2173
|
+
conversation: ChatConversation;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
declare class ChatConversation {
|
|
2177
|
+
id: number;
|
|
2178
|
+
contactId: number;
|
|
2179
|
+
createdAt: Date;
|
|
2180
|
+
updatedAt: Date;
|
|
2181
|
+
/** Set when a chat lead email was sent for this conversation (intent tool). */
|
|
2182
|
+
leadEmailSentAt: Date | null;
|
|
2183
|
+
contact: Contact;
|
|
2184
|
+
messages: ChatMessage[];
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
declare class Contact {
|
|
2188
|
+
id: number;
|
|
2189
|
+
name: string;
|
|
2190
|
+
email: string;
|
|
2191
|
+
phone: string | null;
|
|
2192
|
+
type: string | null;
|
|
2193
|
+
company: string | null;
|
|
2194
|
+
taxId: string | null;
|
|
2195
|
+
notes: string | null;
|
|
2196
|
+
createdAt: Date;
|
|
2197
|
+
updatedAt: Date;
|
|
2198
|
+
deletedAt: Date | null;
|
|
2199
|
+
deleted: boolean;
|
|
2200
|
+
createdBy: number | null;
|
|
2201
|
+
updatedBy: number | null;
|
|
2202
|
+
deletedBy: number | null;
|
|
2203
|
+
userId: number | null;
|
|
2204
|
+
user: User | null;
|
|
2205
|
+
form_submissions: FormSubmission[];
|
|
2206
|
+
addresses: Address[];
|
|
2207
|
+
orders: Order[];
|
|
2208
|
+
payments: Payment[];
|
|
2209
|
+
chatConversations: ChatConversation[];
|
|
2210
|
+
orderAddresses: OrderAddresses[];
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
declare class FormSubmission {
|
|
2214
|
+
id: number;
|
|
2215
|
+
formId: number;
|
|
2216
|
+
contactId: number | null;
|
|
2217
|
+
data: Record<string, unknown>;
|
|
2218
|
+
ipAddress: string | null;
|
|
2219
|
+
userAgent: string | null;
|
|
2220
|
+
createdAt: Date;
|
|
2221
|
+
updatedAt: Date;
|
|
2222
|
+
form: Form;
|
|
2223
|
+
contact: Contact | null;
|
|
2224
|
+
}
|
|
2225
|
+
|
|
2226
|
+
declare class Form {
|
|
2227
|
+
id: number;
|
|
2228
|
+
name: string;
|
|
2229
|
+
description: string | null;
|
|
2230
|
+
campaign: string | null;
|
|
2231
|
+
slug: string;
|
|
2232
|
+
published: boolean;
|
|
2233
|
+
createdAt: Date;
|
|
2234
|
+
updatedAt: Date;
|
|
2235
|
+
deletedAt: Date | null;
|
|
2236
|
+
deleted: boolean;
|
|
2237
|
+
createdBy: number | null;
|
|
2238
|
+
updatedBy: number | null;
|
|
2239
|
+
deletedBy: number | null;
|
|
2240
|
+
fields: FormField[];
|
|
2241
|
+
submissions: FormSubmission[];
|
|
2242
|
+
}
|
|
2243
|
+
|
|
2244
|
+
declare class EventProduct {
|
|
2245
|
+
id: number;
|
|
2246
|
+
eventId: number;
|
|
2247
|
+
productId: number;
|
|
2248
|
+
displayOrder: number;
|
|
2249
|
+
isActive: boolean;
|
|
2250
|
+
createdAt: Date;
|
|
2251
|
+
updatedAt: Date;
|
|
2252
|
+
event: Event;
|
|
2253
|
+
product: Product;
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
type EventSocialMediaLinks = {
|
|
2257
|
+
facebook?: string;
|
|
2258
|
+
instagram?: string;
|
|
2259
|
+
linkedin?: string;
|
|
2260
|
+
youtube?: string;
|
|
2261
|
+
twitter?: string;
|
|
2262
|
+
tiktok?: string;
|
|
2263
|
+
whatsapp?: string;
|
|
2264
|
+
};
|
|
2265
|
+
type EventPricingType = 'free' | 'paid';
|
|
2266
|
+
type EventEntityMode = 'inperson' | 'online' | 'hybrid';
|
|
2267
|
+
type EventVisibility = 'public' | 'private';
|
|
2268
|
+
type EventOrderNotificationChannel$1 = 'email' | 'whatsapp';
|
|
2269
|
+
type EventOrderTemplateOverride$1 = {
|
|
2270
|
+
subject?: string;
|
|
2271
|
+
body?: string;
|
|
2272
|
+
externalTemplateRef?: string;
|
|
2273
|
+
};
|
|
2274
|
+
type EventOrderNotificationTemplates = Partial<Record<EventOrderNotificationChannel$1, EventOrderTemplateOverride$1>>;
|
|
2275
|
+
declare class Event {
|
|
2276
|
+
id: number;
|
|
2277
|
+
vendorId: number | null;
|
|
2278
|
+
name: string;
|
|
2279
|
+
slug: string;
|
|
2280
|
+
description: string | null;
|
|
2281
|
+
expectedSpeakers: number | null;
|
|
2282
|
+
expectedParticipants: number | null;
|
|
2283
|
+
isActive: boolean;
|
|
2284
|
+
comingSoon: boolean;
|
|
2285
|
+
bannerImageUrl: string | null;
|
|
2286
|
+
logoUrl: string | null;
|
|
2287
|
+
venue: string | null;
|
|
2288
|
+
additionalVenueDetails: string | null;
|
|
2289
|
+
visibility: EventVisibility;
|
|
2290
|
+
startDate: Date | null;
|
|
2291
|
+
endDate: Date | null;
|
|
2292
|
+
registrationOpensAt: Date | null;
|
|
2293
|
+
registrationClosesAt: Date | null;
|
|
2294
|
+
pricingType: EventPricingType | null;
|
|
2295
|
+
entityTypes: string[] | null;
|
|
2296
|
+
entityMode: EventEntityMode | null;
|
|
2297
|
+
city: string | null;
|
|
2298
|
+
country: string | null;
|
|
2299
|
+
cityCountry: string | null;
|
|
2300
|
+
defaultCurrency: string | null;
|
|
2301
|
+
supportedCurrencies: string[] | null;
|
|
2302
|
+
timezone: string | null;
|
|
2303
|
+
socialMediaLinks: EventSocialMediaLinks | null;
|
|
2304
|
+
officialWebsiteUrl: string | null;
|
|
2305
|
+
supportContact: string | null;
|
|
2306
|
+
allowGroupOrders: boolean;
|
|
2307
|
+
sendIndividualTicketPDFToAttendees: boolean;
|
|
2308
|
+
/** Send email/WhatsApp when an order containing this event's products is created. */
|
|
2309
|
+
orderNotificationsEnabled: boolean;
|
|
2310
|
+
/** Enabled channels, e.g. ["email","whatsapp"]. */
|
|
2311
|
+
orderNotificationChannels: EventOrderNotificationChannel$1[] | null;
|
|
2312
|
+
/** Per-event template overrides keyed by channel. */
|
|
2313
|
+
orderNotificationTemplates: EventOrderNotificationTemplates | null;
|
|
2314
|
+
/** CMS contact/attendee form used for this event's registration checkout. */
|
|
2315
|
+
contactFormId: number | null;
|
|
2316
|
+
/** GST / tax applied to event ticket sales. */
|
|
2317
|
+
taxId: number | null;
|
|
2318
|
+
/** Optional return/refund policy applied when cancelling orders for this event. */
|
|
2319
|
+
refundPolicyId: number | null;
|
|
2320
|
+
taxRate: number | null;
|
|
2321
|
+
maxGroupPurchaseQuantity: number | null;
|
|
2322
|
+
sponsors: Record<string, unknown> | unknown[] | null;
|
|
2323
|
+
agenda: Record<string, unknown> | unknown[] | null;
|
|
2324
|
+
workshops: Record<string, unknown> | unknown[] | null;
|
|
2325
|
+
exhibitors: Record<string, unknown> | unknown[] | null;
|
|
2326
|
+
partners: Record<string, unknown> | unknown[] | null;
|
|
2327
|
+
speakers: Record<string, unknown> | unknown[] | null;
|
|
2328
|
+
sortOrder: number;
|
|
2329
|
+
createdAt: Date;
|
|
2330
|
+
updatedAt: Date;
|
|
2331
|
+
deletedAt: Date | null;
|
|
2332
|
+
deleted: boolean;
|
|
2333
|
+
createdBy: number | null;
|
|
2334
|
+
updatedBy: number | null;
|
|
2335
|
+
deletedBy: number | null;
|
|
2336
|
+
vendor: Vendor | null;
|
|
2337
|
+
contactForm: Form | null;
|
|
2338
|
+
tax: Tax | null;
|
|
2339
|
+
refundPolicy: RefundPolicy | null;
|
|
2340
|
+
eventProducts: EventProduct[];
|
|
2341
|
+
}
|
|
2342
|
+
|
|
2343
|
+
type OrderLineForTemplate = {
|
|
2344
|
+
name: string;
|
|
2345
|
+
quantity: number;
|
|
2346
|
+
total: number | string;
|
|
2347
|
+
currency: string;
|
|
2348
|
+
};
|
|
2349
|
+
declare function buildEventOrderTemplateVariables(input: {
|
|
2350
|
+
event: Event;
|
|
2351
|
+
order: {
|
|
2352
|
+
orderNumber: string;
|
|
2353
|
+
total: number | string;
|
|
2354
|
+
currency: string;
|
|
2355
|
+
qrToken?: string | null;
|
|
2356
|
+
};
|
|
2357
|
+
contact: {
|
|
2358
|
+
name?: string | null;
|
|
2359
|
+
email?: string | null;
|
|
2360
|
+
phone?: string | null;
|
|
2361
|
+
};
|
|
2362
|
+
productNames: string;
|
|
2363
|
+
orderLines?: OrderLineForTemplate[];
|
|
2364
|
+
siteUrl?: string;
|
|
2365
|
+
}): Record<string, string>;
|
|
2366
|
+
|
|
2367
|
+
declare const EVENT_ORDER_TEMPLATE_KEY = "eventOrderPlaced";
|
|
2368
|
+
type EventOrderNotificationChannel = 'email' | 'whatsapp';
|
|
2369
|
+
type EventOrderTemplateOverride = {
|
|
2370
|
+
subject?: string;
|
|
2371
|
+
body?: string;
|
|
2372
|
+
externalTemplateRef?: string;
|
|
2373
|
+
};
|
|
2374
|
+
type EventOrderMessageTemplateDefault = {
|
|
2375
|
+
channel: EventOrderNotificationChannel;
|
|
2376
|
+
templateKey: string;
|
|
2377
|
+
name: string;
|
|
2378
|
+
subject?: string;
|
|
2379
|
+
body: string;
|
|
2380
|
+
externalTemplateRef?: string;
|
|
2381
|
+
};
|
|
2382
|
+
/** Variables available in email HTML and WhatsApp text templates. */
|
|
2383
|
+
declare const EVENT_ORDER_TEMPLATE_VARIABLES: readonly ["eventName", "eventSlug", "venue", "startDate", "orderNumber", "orderTotal", "currency", "customerName", "customerEmail", "customerPhone", "productNames", "trackUrl", "qrImageUrl", "orderDetails", "orderDetailsHtml"];
|
|
2384
|
+
declare const EVENT_ORDER_MESSAGE_TEMPLATE_DEFAULTS: EventOrderMessageTemplateDefault[];
|
|
2385
|
+
type ResolvedEventOrderTemplate = {
|
|
2386
|
+
subject?: string;
|
|
2387
|
+
body: string;
|
|
2388
|
+
externalTemplateRef?: string;
|
|
2389
|
+
enabled: boolean;
|
|
2390
|
+
};
|
|
2391
|
+
declare function resolveEventOrderTemplate(channel: EventOrderNotificationChannel, getRow: (channel: string, key: string) => Promise<{
|
|
2392
|
+
subject: string | null;
|
|
2393
|
+
body: string;
|
|
2394
|
+
externalTemplateRef: string | null;
|
|
2395
|
+
enabled: boolean;
|
|
2396
|
+
} | null>, eventOverride?: EventOrderTemplateOverride | null): Promise<ResolvedEventOrderTemplate | null>;
|
|
2397
|
+
|
|
2398
|
+
interface DispatchEventOrderNotificationsDeps {
|
|
2399
|
+
dataSource: DataSource;
|
|
2400
|
+
entityMap: Record<string, unknown>;
|
|
2401
|
+
getCms: () => Promise<CmsAppLike$3>;
|
|
2402
|
+
}
|
|
2403
|
+
|
|
2404
|
+
declare function dispatchEventOrderNotifications(orderId: number, deps: DispatchEventOrderNotificationsDeps): Promise<void>;
|
|
2405
|
+
|
|
2406
|
+
type CaptchaProviderId = 'turnstile' | 'recaptcha_v3';
|
|
2407
|
+
interface CaptchaPublicConfig {
|
|
2408
|
+
enabled: boolean;
|
|
2409
|
+
activeProvider: CaptchaProviderId | null;
|
|
2410
|
+
siteKey: string | null;
|
|
2411
|
+
availableProviders: Array<{
|
|
2412
|
+
id: CaptchaProviderId;
|
|
2413
|
+
siteKey: string;
|
|
2414
|
+
}>;
|
|
2415
|
+
multipleProviders: boolean;
|
|
2416
|
+
}
|
|
2417
|
+
type CaptchaVerifyResult = {
|
|
2418
|
+
ok: true;
|
|
2419
|
+
} | {
|
|
2420
|
+
ok: false;
|
|
2421
|
+
status: number;
|
|
2422
|
+
message: string;
|
|
2423
|
+
};
|
|
2424
|
+
declare function buildCaptchaPublicConfig(config: Record<string, string>): CaptchaPublicConfig;
|
|
2425
|
+
declare class CaptchaService {
|
|
2426
|
+
private readonly env;
|
|
2427
|
+
constructor(env: Record<string, string>);
|
|
2428
|
+
isEnforced(): boolean;
|
|
2429
|
+
getPublicConfig(): CaptchaPublicConfig;
|
|
2430
|
+
verify(body: Record<string, unknown>, req: Request): Promise<CaptchaVerifyResult>;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
declare function captchaPlugin(): CmsPlugin<CaptchaService | void>;
|
|
2434
|
+
|
|
2435
|
+
type JsonResponse = (body: unknown, init?: {
|
|
2436
|
+
status?: number;
|
|
2437
|
+
headers?: HeadersInit;
|
|
2438
|
+
}) => Response;
|
|
2439
|
+
declare function assertCaptchaOk(getCms: (() => Promise<{
|
|
2440
|
+
getPlugin: (name: string) => unknown;
|
|
2441
|
+
}>) | undefined, body: Record<string, unknown>, req: Request, json: JsonResponse): Promise<Response | null>;
|
|
2442
|
+
|
|
2443
|
+
interface LatestArticleFromFeed {
|
|
2444
|
+
title?: string;
|
|
2445
|
+
link?: string;
|
|
2446
|
+
/** Short excerpt */
|
|
2447
|
+
summary?: string;
|
|
2448
|
+
/** Full content if available */
|
|
2449
|
+
content?: string;
|
|
2450
|
+
date: Date;
|
|
2451
|
+
creator?: string;
|
|
2452
|
+
categories?: string[];
|
|
2453
|
+
}
|
|
2454
|
+
type RssItem = {
|
|
2455
|
+
title?: string;
|
|
2456
|
+
link?: string;
|
|
2457
|
+
pubDate?: string;
|
|
2458
|
+
isoDate?: string;
|
|
2459
|
+
contentSnippet?: string;
|
|
2460
|
+
summary?: string;
|
|
2461
|
+
description?: string;
|
|
2462
|
+
content?: string;
|
|
2463
|
+
creator?: string;
|
|
2464
|
+
'dc:creator'?: string;
|
|
2465
|
+
'content:encoded'?: string;
|
|
2466
|
+
categories?: string[];
|
|
2467
|
+
guid?: string | {
|
|
2468
|
+
_: string;
|
|
2469
|
+
};
|
|
2470
|
+
};
|
|
2471
|
+
declare function getRssArticleSummaryFromItem(item: RssItem): {
|
|
2472
|
+
summary: string;
|
|
2473
|
+
fullContent: string;
|
|
2474
|
+
};
|
|
2475
|
+
type BlogGeneratorDraftParseMode = 'json' | 'plaintext';
|
|
2476
|
+
interface BlogGeneratorSeoDraft {
|
|
2477
|
+
title: string | null;
|
|
2478
|
+
description: string | null;
|
|
2479
|
+
keywords: string | null;
|
|
2480
|
+
ogTitle: string | null;
|
|
2481
|
+
ogDescription: string | null;
|
|
2482
|
+
}
|
|
2483
|
+
interface BlogGeneratorBlogDraft {
|
|
2484
|
+
title: string;
|
|
2485
|
+
slug?: string;
|
|
2486
|
+
markdown: string;
|
|
2487
|
+
/** Short plain-text copy for social (e.g. LinkedIn); optional until social LLM step runs. */
|
|
2488
|
+
socialMediaContent?: string | null;
|
|
2489
|
+
categoryName: string | null;
|
|
2490
|
+
seo: BlogGeneratorSeoDraft;
|
|
2491
|
+
/** Suggested tag labels (may not exist in CMS yet). */
|
|
2492
|
+
tags: string[];
|
|
2493
|
+
parseMode: BlogGeneratorDraftParseMode;
|
|
2494
|
+
}
|
|
2495
|
+
/**
|
|
2496
|
+
* Parses the LLM reply: prefers a single JSON object with blogTitle, blogHtml/blogMarkdown/content, categoryName, seo, …
|
|
2497
|
+
* Falls back to treating the entire string as HTML (or legacy markdown) if JSON parsing fails.
|
|
2498
|
+
*/
|
|
2499
|
+
declare function parseBlogGeneratorAgentContent(raw: string): BlogGeneratorBlogDraft;
|
|
2500
|
+
declare function resolveBlogCategoryIdByName(needle: string | null | undefined, rows: readonly {
|
|
2501
|
+
id: number;
|
|
2502
|
+
name: string;
|
|
2503
|
+
}[]): {
|
|
2504
|
+
categoryId: number | null;
|
|
2505
|
+
matched: boolean;
|
|
2506
|
+
};
|
|
2507
|
+
/**
|
|
2508
|
+
* Minimal user payload: latest item per feed only (system prompt carries writing rules).
|
|
2509
|
+
*/
|
|
2510
|
+
declare function buildRssUserPromptFromFeeds(feeds: ReadonlyArray<{
|
|
2511
|
+
rssUrl: string;
|
|
2512
|
+
article: LatestArticleFromFeed;
|
|
2513
|
+
}>): string;
|
|
2514
|
+
/**
|
|
2515
|
+
* User message for the metadata-only LLM step (one blog at a time).
|
|
2516
|
+
*/
|
|
2517
|
+
declare function buildBlogMetadataUserPrompt(opts: {
|
|
2518
|
+
title: string;
|
|
2519
|
+
markdown: string;
|
|
2520
|
+
categoryNames: readonly string[];
|
|
2521
|
+
tagNames: readonly string[];
|
|
2522
|
+
}): string;
|
|
2523
|
+
/** Parses JSON from the metadata-enrichment LLM (category, slug, seo, tags). */
|
|
2524
|
+
declare function parseBlogMetadataEnrichmentJson(raw: string): {
|
|
2525
|
+
categoryName: string | null;
|
|
2526
|
+
blogSlug: string | null;
|
|
2527
|
+
seo: BlogGeneratorSeoDraft;
|
|
2528
|
+
tags: string[];
|
|
2529
|
+
};
|
|
2530
|
+
/**
|
|
2531
|
+
* Parses LLM output: prefers HTML + {@link BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR} for multiple articles.
|
|
2532
|
+
* If the model still returns legacy JSON with `blogHtml` / `blogMarkdown`, returns a single draft from that object.
|
|
2533
|
+
*/
|
|
2534
|
+
declare function parseBlogGeneratorModelOutput(raw: string): BlogGeneratorBlogDraft[];
|
|
2535
|
+
declare class BlogGeneratorService {
|
|
2536
|
+
readonly version: "1.0.0";
|
|
2537
|
+
getLatestArticleFromFeed(rssUrl: string): Promise<LatestArticleFromFeed | null>;
|
|
2538
|
+
/** Defaults for the Blog Generator Agent (admin can override per request). */
|
|
2539
|
+
getAgentDefaults(): {
|
|
2540
|
+
agentName: string;
|
|
2541
|
+
systemInstruction: string;
|
|
2542
|
+
validationRules: string;
|
|
2543
|
+
};
|
|
2544
|
+
/**
|
|
2545
|
+
* Second LLM call: one draft at a time — category, URL slug, SEO fields, tags (JSON).
|
|
2546
|
+
*/
|
|
2547
|
+
private enrichBlogDraftWithLlmMetadata;
|
|
2548
|
+
/**
|
|
2549
|
+
* Third LLM call: one draft at a time — short social copy (JSON `{ socialMediaContent }`).
|
|
2550
|
+
*/
|
|
2551
|
+
private enrichBlogDraftWithLlmSocial;
|
|
2552
|
+
/**
|
|
2553
|
+
* Fetches the latest item for each RSS URL, then calls {@link LlmServiceInterface.chatAgent}.
|
|
2554
|
+
* `userPrompt` is only per-feed source material; rules live in the system prompt.
|
|
2555
|
+
* Expects HTML article fragment(s), optionally separated by {@link BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR}.
|
|
2556
|
+
*/
|
|
2557
|
+
generateBlogMarkdownFromRss(params: {
|
|
2558
|
+
llm: LlmServiceInterface;
|
|
2559
|
+
/** Single feed (legacy). */
|
|
2560
|
+
rssUrl?: string;
|
|
2561
|
+
/** One or more feeds; latest item per URL is sent together. Prefer this when multiple URLs. */
|
|
2562
|
+
rssUrls?: readonly string[];
|
|
2563
|
+
systemInstruction?: string;
|
|
2564
|
+
validationRules?: string;
|
|
2565
|
+
/** Reserved for future structured output; writer does not inject categories into the user prompt. */
|
|
2566
|
+
categoryNamesHint?: readonly string[];
|
|
2567
|
+
/** Names of non-deleted tags in CMS (hint for reuse). */
|
|
2568
|
+
tagNamesHint?: readonly string[];
|
|
2569
|
+
/** From optional `llm_agents` row (slug `blog-generator`): model / sampling for the writer step. */
|
|
2570
|
+
llmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
2571
|
+
/** Optional overrides for the metadata step; defaults live in `blog-generator-metadata-defaults.ts`. */
|
|
2572
|
+
metadataSystemInstruction?: string;
|
|
2573
|
+
metadataValidationRules?: string;
|
|
2574
|
+
/** From optional `llm_agents` row (slug `blog-generator-metadata`): model / sampling for metadata only. */
|
|
2575
|
+
metadataLlmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
2576
|
+
/** Optional overrides for the social-summary step; defaults in `blog-generator-social-defaults.ts`. */
|
|
2577
|
+
socialSystemInstruction?: string;
|
|
2578
|
+
socialValidationRules?: string;
|
|
2579
|
+
/** From optional `llm_agents` row (slug `blog-generator-social`): model / sampling for social copy only. */
|
|
2580
|
+
socialLlmAgentChatOptions?: Pick<LlmAgentOptions, 'model' | 'temperature' | 'max_tokens'>;
|
|
2581
|
+
}): Promise<{
|
|
2582
|
+
agentName: string;
|
|
2583
|
+
feedArticles: Array<{
|
|
2584
|
+
rssUrl: string;
|
|
2585
|
+
article: LatestArticleFromFeed;
|
|
2586
|
+
}>;
|
|
2587
|
+
/** First feed's article (backward compatibility). */
|
|
2588
|
+
article: LatestArticleFromFeed;
|
|
2589
|
+
/** Raw model reply (HTML body per defaults; legacy markdown or JSON still parsed when present). */
|
|
2590
|
+
blogMarkdown: string;
|
|
2591
|
+
blogDrafts: BlogGeneratorBlogDraft[];
|
|
2592
|
+
/** Same as first draft; backward compatibility. */
|
|
2593
|
+
blogDraft: BlogGeneratorBlogDraft;
|
|
2594
|
+
}>;
|
|
2595
|
+
}
|
|
2596
|
+
|
|
2597
|
+
/** Stable display name; not persisted as DB agent row in v1. */
|
|
2598
|
+
declare const BLOG_GENERATOR_AGENT_NAME = "Blog Generator Agent";
|
|
2599
|
+
/**
|
|
2600
|
+
* Optional `llm_agents` row: when present and enabled, model / temperature / max_tokens
|
|
2601
|
+
* are applied to {@link LlmServiceInterface.chatAgent} (system + user content still come from blog generator defaults / UI).
|
|
2602
|
+
*/
|
|
2603
|
+
declare const BLOG_GENERATOR_LLM_AGENT_SLUG = "blog-generator";
|
|
2604
|
+
/** Line that separates multiple articles in the model reply (HTML or legacy markdown; must match parser and prompts). */
|
|
2605
|
+
declare const BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR = "---BLOG_GENERATOR_NEXT---";
|
|
2606
|
+
declare const BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION = "You are a professional financial and business content writer.\n\nYour task is to generate completely original, high-quality blog article(s) from the latest RSS-derived source material in the user message (one block per feed). The user message is factual input only.\n\nIMPORTANT RULES:\n\n1. NEVER copy the RSS article directly.\n2. Rewrite the information into a fresh, human-like article.\n3. Expand the topic with professional insights and explanations.\n4. Maintain a natural editorial tone.\n5. Make the article SEO-friendly.\n6. Use engaging headings and subheadings.\n7. Avoid robotic AI phrasing.\n8. Do not mention that the content came from RSS or feeds.\n9. Preserve factual accuracy from the source material.\n10. The output should feel like a professionally written industry blog.\n\nMULTIPLE FEEDS:\n- If several feeds are provided, compare them: if they largely cover the same story or overlap heavily, produce ONE cohesive article.\n- If they cover clearly different topics or distinct stories, produce MULTIPLE articles (one per distinct story).\n- You may also produce one synthesis plus a short separate angle when that best serves the reader\u2014use your judgment.\n\nWRITING STYLE:\n- Professional\n- Clear\n- Informative\n- Business-focused\n- Human sounding\n- Modern editorial style\n\nARTICLE STRUCTURE (each article \u2014 express in HTML):\n1. Engaging introduction\n2. Industry context\n3. Main developments\n4. Key implications\n5. Expert/business analysis\n6. Conclusion\n\nHTML STRUCTURE (STRICT \u2014 each article must be valid, semantic HTML only):\n- Output HTML only. Do not use Markdown (no # headings, no **bold**, no `code fences`).\n- Wrap each complete article in a single root: <article class=\"blog-post\"> ... </article>\n- Inside <article>, use this outline:\n - <header><h1 class=\"blog-post-title\">\u2026main title\u2026</h1></header> (exactly one h1 per article)\n - <section class=\"blog-post-body\"> for all following content\n - Use <h2> and <h3> for section and subsection titles (never skip levels: h1 \u2192 h2 \u2192 h3).\n - Use <p> for paragraphs; keep paragraphs focused (avoid huge unbroken text).\n - Use <ul>/<ol> with <li> for lists where appropriate.\n - Use <strong> and <em> for emphasis sparingly; use <blockquote> only when quoting or callouts fit.\n- Do not include <html>, <head>, <body>, or document-level wrappers \u2014 only the fragment(s) described above.\n- Do not use <script>, <style>, <iframe>, or inline event handlers. Avoid inline style=\"\" except when essential for accessibility (prefer none).\n- Escape angle brackets in body text if you must mention markup; keep output safe for embedding in a CMS.\n\nCONTENT REQUIREMENTS:\n- Minimum 800 words per article unless source material is very small.\n- Add context around industry trends where appropriate.\n- Explain why the topic matters.\n- Include practical implications for businesses/professionals.\n\nIF RSS CONTENT IS LIMITED:\n- Expand intelligently using general industry knowledge.\n- Keep the article relevant to the original topic.\n- Do not invent fake facts or statistics.\n\nOUTPUT FORMAT (STRICT \u2014 HTML only):\n- Return ONLY the article HTML fragment(s). No JSON, no preamble or postscript (\"Here is your article\u2026\"), no markdown.\n- If you output more than one article, output multiple <article class=\"blog-post\">\u2026</article> blocks in sequence, and between articles put a single line containing exactly this (and nothing else on that line):\n---BLOG_GENERATOR_NEXT---\n- If you output a single article, use one <article> only and do not use that separator line.";
|
|
2607
|
+
/**
|
|
2608
|
+
* JSON so {@link parseLlmAgentValidationRules} can attach guardrails and allow long source payloads.
|
|
2609
|
+
* Edit in the admin UI if needed; defaults match product intent.
|
|
2610
|
+
*/
|
|
2611
|
+
declare const BLOG_GENERATOR_DEFAULT_VALIDATION_RULES: string;
|
|
2612
|
+
|
|
2613
|
+
/**
|
|
2614
|
+
* Second-step LLM: classifies one finished HTML blog body into CMS fields (category, SEO, tags).
|
|
2615
|
+
*
|
|
2616
|
+
* Optional `llm_agents` row: slug {@link BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG} — when present and enabled,
|
|
2617
|
+
* model / temperature / max_tokens apply to this call only (writer step uses `blog-generator`).
|
|
2618
|
+
*
|
|
2619
|
+
* To change how metadata is produced, edit the constants in this file (system instruction + validation JSON).
|
|
2620
|
+
* No admin UI override is wired yet; add request body fields in `cms-api-handler` if you need runtime overrides later.
|
|
2621
|
+
*/
|
|
2622
|
+
declare const BLOG_METADATA_ENRICHER_AGENT_NAME = "Blog Generator Metadata";
|
|
2623
|
+
/** `llm_agents.slug` for routing model/temperature for the metadata-only chat step. */
|
|
2624
|
+
declare const BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG = "blog-generator-metadata";
|
|
2625
|
+
declare const BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION = "You are a careful CMS metadata assistant for a publishing system.\n\nYou receive ONE complete blog post as HTML (title is usually in <h1 class=\"blog-post-title\"> or the first <h1>). Your job is to propose structured fields so an editor can save the post: category, URL slug, SEO block, and topical tags.\n\nRULES:\n1. Read the whole article and infer the primary topic and audience.\n2. categoryName must be EXACTLY one string from AVAILABLE_BLOG_CATEGORIES in the user message, or \"\" if none fit.\n3. blogSlug: lowercase kebab-case, ASCII letters/digits/hyphens only, no leading/trailing hyphens, max ~80 chars. Derive from the main topic or title.\n4. seo.title: concise meta title (~50\u201360 characters when reasonable).\n5. seo.description: meta description (~150\u2013160 characters when reasonable), plain text.\n6. seo.keywords: comma-separated phrases, no stuffing.\n7. seo.ogTitle / seo.ogDescription: may mirror title/description or be slightly adapted for social.\n8. tags: 4\u201310 short labels (1\u20133 words each). Prefer exact matches from EXISTING_TAG_NAMES when they truly apply; otherwise invent precise new labels (they may be created in the CMS later).\n9. Do not invent statistics, quotes, or URLs not implied by the article.\n10. Output JSON only \u2014 no markdown outside the JSON, no commentary.\n\nOUTPUT FORMAT (STRICT):\nReturn a single JSON object only. Do not wrap it in a markdown code fence.\n\n{\n \"categoryName\": \"string \u2014 exact match from list or empty string\",\n \"blogSlug\": \"string \u2014 url-safe kebab-case\",\n \"seo\": {\n \"title\": \"string or empty\",\n \"description\": \"string or empty\",\n \"keywords\": \"string or empty\",\n \"ogTitle\": \"string or empty\",\n \"ogDescription\": \"string or empty\"\n },\n \"tags\": [\"tag-one\", \"tag-two\"]\n}";
|
|
2626
|
+
declare const BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES: string;
|
|
2627
|
+
|
|
2628
|
+
interface BlogGeneratorPluginConfig {
|
|
2629
|
+
/** Set to false to skip registering the plugin. */
|
|
2630
|
+
enabled?: boolean;
|
|
2631
|
+
}
|
|
2632
|
+
declare function blogGeneratorPlugin(config?: BlogGeneratorPluginConfig): CmsPlugin<BlogGeneratorService | undefined>;
|
|
2633
|
+
|
|
2634
|
+
interface SocialMediaApiConfig {
|
|
2635
|
+
dataSource: DataSource;
|
|
2636
|
+
entityMap: EntityMap$2;
|
|
2637
|
+
json: (body: unknown, init?: {
|
|
2638
|
+
status?: number;
|
|
2639
|
+
}) => Response;
|
|
2640
|
+
requireAuth: (req: Request) => Promise<Response | null>;
|
|
2641
|
+
requireEntityPermission: (req: Request, entity: string, action: EntityCrudAction) => Promise<Response | null>;
|
|
2642
|
+
encryptionKey?: string;
|
|
2643
|
+
/** Used to resolve relative cover image URLs (e.g. https://mysite.com). */
|
|
2644
|
+
publicSiteUrl?: string;
|
|
2645
|
+
/**
|
|
2646
|
+
* When true (default), `console.info` / `console.warn` lines are emitted for LinkedIn blog publish
|
|
2647
|
+
* (text vs image path, sizes, errors). Set false or `CMS_LINKEDIN_PUBLISH_LOG=0` to silence.
|
|
2648
|
+
*/
|
|
2649
|
+
linkedInPublishLogging?: boolean;
|
|
2650
|
+
}
|
|
2651
|
+
declare function createSocialMediaHandlers(config: SocialMediaApiConfig): {
|
|
2652
|
+
getLinkedInStatus(req: Request): Promise<Response>;
|
|
2653
|
+
fetchLinkedInOrganizations(req: Request): Promise<Response>;
|
|
2654
|
+
syncLinkedInProfile(req: Request): Promise<Response>;
|
|
2655
|
+
publishBlogToLinkedIn(req: Request, blogId: number): Promise<Response>;
|
|
2656
|
+
getFacebookStatus(req: Request): Promise<Response>;
|
|
2657
|
+
publishBlogToFacebook(req: Request, blogId: number): Promise<Response>;
|
|
2658
|
+
/**
|
|
2659
|
+
* POST JSON `{ appId, appSecret, userAccessToken }`. Calls Graph `GET /me/accounts` with the user token.
|
|
2660
|
+
* App ID and secret are validated but not used yet (reserved for future token flows).
|
|
2661
|
+
* Persist credentials via Plugins → Save: `meta_app_id` (public), `meta_app_secret` and `meta_user_access_token` (encrypted).
|
|
2662
|
+
*/
|
|
2663
|
+
fetchFacebookManagedPages(req: Request): Promise<Response>;
|
|
2664
|
+
};
|
|
2665
|
+
|
|
2666
|
+
/**
|
|
2667
|
+
* Meta (Facebook) Graph API helpers (server-side). Uses fetch — no SDK.
|
|
2668
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/user/accounts
|
|
2669
|
+
*/
|
|
2670
|
+
type FacebookPageAccount = {
|
|
2671
|
+
access_token?: string;
|
|
2672
|
+
category?: string;
|
|
2673
|
+
name?: string;
|
|
2674
|
+
id?: string;
|
|
2675
|
+
/** Graph may return additional fields */
|
|
2676
|
+
[key: string]: unknown;
|
|
2677
|
+
};
|
|
2678
|
+
type FacebookMeAccountsResponse = {
|
|
2679
|
+
data?: FacebookPageAccount[];
|
|
2680
|
+
paging?: Record<string, unknown>;
|
|
2681
|
+
error?: {
|
|
2682
|
+
message?: string;
|
|
2683
|
+
type?: string;
|
|
2684
|
+
code?: number;
|
|
2685
|
+
fbtrace_id?: string;
|
|
2686
|
+
};
|
|
2687
|
+
};
|
|
2688
|
+
/**
|
|
2689
|
+
* Lists Facebook Pages the user manages (page access tokens + metadata).
|
|
2690
|
+
* Requires a User access token with `pages_show_list` or equivalent page permissions.
|
|
2691
|
+
*/
|
|
2692
|
+
declare function metaFetchUserManagedPages(userAccessToken: string): Promise<FacebookMeAccountsResponse>;
|
|
2693
|
+
type MetaGraphMutationResponse = {
|
|
2694
|
+
id?: string;
|
|
2695
|
+
post_id?: string;
|
|
2696
|
+
error?: {
|
|
2697
|
+
message?: string;
|
|
2698
|
+
type?: string;
|
|
2699
|
+
code?: number;
|
|
2700
|
+
fbtrace_id?: string;
|
|
2701
|
+
};
|
|
2702
|
+
};
|
|
2703
|
+
/** Resolves the long-lived page access token for a Page ID from `/me/accounts` data. */
|
|
2704
|
+
declare function metaResolvePageAccessToken(accounts: FacebookMeAccountsResponse, pageId: string): string | null;
|
|
2705
|
+
/**
|
|
2706
|
+
* Upload a photo to a Page timeline (multipart).
|
|
2707
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/page/photos#Creating
|
|
2708
|
+
*/
|
|
2709
|
+
declare function metaPostPagePhoto(opts: {
|
|
2710
|
+
pageId: string;
|
|
2711
|
+
pageAccessToken: string;
|
|
2712
|
+
imageBuffer: Buffer;
|
|
2713
|
+
contentType: string;
|
|
2714
|
+
caption: string;
|
|
2715
|
+
}): Promise<MetaGraphMutationResponse>;
|
|
2716
|
+
/**
|
|
2717
|
+
* Publish a text-only post to the Page feed (when no JPEG/PNG image is available).
|
|
2718
|
+
* @see https://developers.facebook.com/docs/graph-api/reference/page/feed#Creating
|
|
2719
|
+
*/
|
|
2720
|
+
declare function metaPostPageFeed(opts: {
|
|
2721
|
+
pageId: string;
|
|
2722
|
+
pageAccessToken: string;
|
|
2723
|
+
message: string;
|
|
2724
|
+
}): Promise<MetaGraphMutationResponse>;
|
|
2725
|
+
|
|
2726
|
+
interface SocialMediaPluginConfig {
|
|
2727
|
+
/** Set to false to skip registering the plugin instance (API routes still work if wired in the app handler). */
|
|
2728
|
+
enabled?: boolean;
|
|
2729
|
+
}
|
|
2730
|
+
/**
|
|
2731
|
+
* Optional CMS plugin instance for `getPlugin('social_media')`.
|
|
2732
|
+
* LinkedIn publishing is implemented in {@link createSocialMediaHandlers} and mounted from the CMS API handler.
|
|
2733
|
+
*/
|
|
2734
|
+
declare function socialMediaPlugin(config?: SocialMediaPluginConfig): CmsPlugin<{
|
|
2735
|
+
name: string;
|
|
2736
|
+
} | undefined>;
|
|
2737
|
+
|
|
2738
|
+
declare function cn(...inputs: ClassValue[]): string;
|
|
2739
|
+
declare function generateSlug(title: string): string;
|
|
2740
|
+
declare function validateSlug(slug: string): boolean;
|
|
2741
|
+
declare function formatDate(date: Date | string): string;
|
|
2742
|
+
declare function formatDateTime(date: Date | string): string;
|
|
2743
|
+
declare function formatDateOnly(date: Date | string): string;
|
|
2744
|
+
declare function truncateText(text: string, maxLength: number): string;
|
|
2745
|
+
|
|
2746
|
+
/** Minimal SEO row shape (DB or API). */
|
|
2747
|
+
type SeoLike = {
|
|
2748
|
+
title?: string | null;
|
|
2749
|
+
description?: string | null;
|
|
2750
|
+
keywords?: string | null;
|
|
2751
|
+
ogTitle?: string | null;
|
|
2752
|
+
ogDescription?: string | null;
|
|
2753
|
+
ogImage?: string | null;
|
|
2754
|
+
};
|
|
2755
|
+
type SeoMetadataOverrides = {
|
|
2756
|
+
title?: string;
|
|
2757
|
+
description?: string;
|
|
2758
|
+
keywords?: string;
|
|
2759
|
+
ogTitle?: string;
|
|
2760
|
+
ogDescription?: string;
|
|
2761
|
+
ogImage?: string;
|
|
2762
|
+
};
|
|
2763
|
+
/** Per-field: join row wins over slug row. */
|
|
2764
|
+
declare function mergeSeoBySlug(join: SeoLike | null | undefined, bySlug: SeoLike | null): SeoLike | null;
|
|
2765
|
+
declare function fetchSeoBySlug(dataSource: DataSource, entityMap: EntityMap$2, slug: string): Promise<SeoLike | null>;
|
|
2766
|
+
/**
|
|
2767
|
+
* Build Next.js Metadata from merged SEO + optional layers.
|
|
2768
|
+
* `overrides` win over SEO; `fallbacks` apply when SEO (and overrides) omit a field.
|
|
2769
|
+
* Returns a partial object; omit fields so the root layout defaults apply.
|
|
2770
|
+
*/
|
|
2771
|
+
declare function resolvePublicMetadata(args: {
|
|
2772
|
+
dataSource: DataSource;
|
|
2773
|
+
entityMap: EntityMap$2;
|
|
2774
|
+
slug: string;
|
|
2775
|
+
seoFromJoin?: SeoLike | null;
|
|
2776
|
+
overrides?: SeoMetadataOverrides;
|
|
2777
|
+
fallbacks?: SeoMetadataOverrides;
|
|
2778
|
+
canonicalPath?: string;
|
|
2779
|
+
metadataBase?: URL;
|
|
2780
|
+
}): Promise<Metadata>;
|
|
2781
|
+
|
|
2782
|
+
/** Links an unclaimed contact (same email, no userId) to the new user after signup or invite. */
|
|
2783
|
+
declare function linkUnclaimedContactToUser(dataSource: DataSource, contactsEntity: EntityTarget<ObjectLiteral>, userId: number, email: string): Promise<void>;
|
|
2784
|
+
|
|
2785
|
+
type EnsureCustomerUserInput = {
|
|
2786
|
+
id: number;
|
|
2787
|
+
name: string;
|
|
2788
|
+
email: string;
|
|
2789
|
+
phone?: string | null;
|
|
2790
|
+
};
|
|
2791
|
+
/** Stable unique placeholder when no phone is available (customer.phone is NOT NULL + UNIQUE). */
|
|
2792
|
+
declare function customerPhoneForUser(userId: number, phone?: string | null): string;
|
|
2793
|
+
/**
|
|
2794
|
+
* Ensures a `customer` row exists for the given user (idempotent by userId / email).
|
|
2795
|
+
* Returns null when customer entity is missing or email belongs to another user.
|
|
2796
|
+
*/
|
|
2797
|
+
declare function ensureCustomerForUser(dsOrEm: DataSource | EntityManager, customerEntity: EntityTarget<ObjectLiteral>, user: EnsureCustomerUserInput, overrides?: {
|
|
2798
|
+
phone?: string | null;
|
|
2799
|
+
}): Promise<{
|
|
2800
|
+
id: number;
|
|
2801
|
+
} | null>;
|
|
2802
|
+
|
|
2803
|
+
/** Parse stored config value into a list of emails (JSON array, or comma/semicolon-separated string). */
|
|
2804
|
+
declare function parseEmailRecipientsFromConfig(raw: string | undefined | null): string[];
|
|
2805
|
+
/** Serialize email list for config storage (JSON array in DB). */
|
|
2806
|
+
declare function serializeEmailRecipients(emails: string[]): string;
|
|
2807
|
+
/** Join for SMTP `to` header (multiple recipients). */
|
|
2808
|
+
declare function joinRecipientsForSend(emails: string[]): string | null;
|
|
2809
|
+
|
|
2810
|
+
type OtpPurpose = 'login' | 'verify_email' | 'verify_phone';
|
|
2811
|
+
type OtpChannel = 'email' | 'sms';
|
|
2812
|
+
declare function hashOtpCode(code: string, purpose: string, identifier: string, pepper?: string): string;
|
|
2813
|
+
declare function verifyOtpCodeHash(code: string, storedHash: string, purpose: string, identifier: string, pepper?: string): boolean;
|
|
2814
|
+
declare function generateNumericOtp(length?: number): string;
|
|
2815
|
+
/** Normalize to E.164-like +digits */
|
|
2816
|
+
declare function normalizePhoneE164(raw: string, defaultCountryCode?: string): string | null;
|
|
2817
|
+
type EntityMap$1 = Record<string, EntityTarget<ObjectLiteral>>;
|
|
2818
|
+
declare function countRecentOtpSends(dataSource: DataSource, entityMap: EntityMap$1, purpose: OtpPurpose, identifier: string, since: Date): Promise<number>;
|
|
2819
|
+
declare function createOtpChallenge(dataSource: DataSource, entityMap: EntityMap$1, input: {
|
|
2820
|
+
purpose: OtpPurpose;
|
|
2821
|
+
channel: OtpChannel;
|
|
2822
|
+
identifier: string;
|
|
2823
|
+
code: string;
|
|
2824
|
+
pepper?: string;
|
|
2825
|
+
}): Promise<{
|
|
2826
|
+
ok: true;
|
|
2827
|
+
} | {
|
|
2828
|
+
ok: false;
|
|
2829
|
+
error: string;
|
|
2830
|
+
status: number;
|
|
2831
|
+
}>;
|
|
2832
|
+
declare function verifyAndConsumeOtpChallenge(dataSource: DataSource, entityMap: EntityMap$1, input: {
|
|
2833
|
+
purpose: OtpPurpose;
|
|
2834
|
+
identifier: string;
|
|
2835
|
+
code: string;
|
|
2836
|
+
pepper?: string;
|
|
2837
|
+
}): Promise<{
|
|
2838
|
+
ok: true;
|
|
2839
|
+
} | {
|
|
2840
|
+
ok: false;
|
|
2841
|
+
error: string;
|
|
2842
|
+
status: number;
|
|
2843
|
+
}>;
|
|
2844
|
+
|
|
2845
|
+
/** Returns true if request is allowed; false if rate limited. */
|
|
2846
|
+
declare function allowRateLimit(key: string): Promise<boolean>;
|
|
2847
|
+
type ExtraPublicWriteRule = (method: string, segments: string[]) => boolean;
|
|
2848
|
+
/** Segments are path parts after `/api/` (e.g. `['form-submissions']`). */
|
|
2849
|
+
declare function shouldRateLimitPublicWrite(method: string, segments: string[], extraRule?: ExtraPublicWriteRule): boolean;
|
|
2850
|
+
declare function rateLimitKeyForApiRequest(req: Request, segments: string[]): string;
|
|
2851
|
+
declare function rateLimitPublicApiIfNeeded(req: Request, method: string, segments: string[], options?: {
|
|
2852
|
+
extraRule?: ExtraPublicWriteRule;
|
|
2853
|
+
}): Promise<Response | null>;
|
|
2854
|
+
declare function rateLimitCheckoutPost(req: Request): Promise<Response | null>;
|
|
2855
|
+
|
|
2856
|
+
interface EntityMapLike$1 {
|
|
2857
|
+
configs: unknown;
|
|
2858
|
+
orders: unknown;
|
|
2859
|
+
order_items: unknown;
|
|
2860
|
+
}
|
|
2861
|
+
interface SendOrderPlacedEmailDeps {
|
|
2862
|
+
getDataSource: () => Promise<DataSource>;
|
|
2863
|
+
entityMap: EntityMapLike$1;
|
|
2864
|
+
getCms: () => Promise<CmsApp>;
|
|
2865
|
+
}
|
|
2866
|
+
/** After payment confirmation: email customer + each sales team address from plugin settings. */
|
|
2867
|
+
declare function sendOrderPlacedEmailsAfterConfirmation(orderId: number, deps: SendOrderPlacedEmailDeps): Promise<void>;
|
|
2868
|
+
|
|
2869
|
+
type VendorOnboardedActivation = 'invite' | 'password';
|
|
2870
|
+
type VendorOnboardedKind = 'vendor_onboard' | 'team_invite';
|
|
2871
|
+
|
|
2872
|
+
interface EntityMapLike {
|
|
2873
|
+
configs: unknown;
|
|
2874
|
+
}
|
|
2875
|
+
interface SendVendorOnboardEmailInput {
|
|
2876
|
+
vendorName: string;
|
|
2877
|
+
vendorSlug?: string;
|
|
2878
|
+
ownerName: string;
|
|
2879
|
+
ownerEmail: string;
|
|
2880
|
+
activation: VendorOnboardedActivation;
|
|
2881
|
+
inviteLink?: string;
|
|
2882
|
+
signInLink: string;
|
|
2883
|
+
kind?: VendorOnboardedKind;
|
|
2884
|
+
/** When false, skips owner email but still notifies internal recipients. Default true. */
|
|
2885
|
+
sendToOwner?: boolean;
|
|
2886
|
+
}
|
|
2887
|
+
interface SendVendorOnboardEmailDeps {
|
|
2888
|
+
getDataSource: () => Promise<DataSource>;
|
|
2889
|
+
entityMap: EntityMapLike;
|
|
2890
|
+
getCms: () => Promise<CmsAppLike$3>;
|
|
2891
|
+
}
|
|
2892
|
+
/** After vendor onboard / team invite: email owner + platform team from plugin settings. */
|
|
2893
|
+
declare function sendVendorOnboardEmails(input: SendVendorOnboardEmailInput, deps: SendVendorOnboardEmailDeps): Promise<{
|
|
2894
|
+
ownerEmailSent: boolean;
|
|
2895
|
+
}>;
|
|
2896
|
+
|
|
2897
|
+
interface DataSourceManager {
|
|
2898
|
+
getDataSource: () => DataSource;
|
|
2899
|
+
getDataSourceInitialized: () => Promise<DataSource>;
|
|
2900
|
+
resetDataSource: () => void;
|
|
2901
|
+
registerOnReset: (cb: () => void) => void;
|
|
2902
|
+
isConnectionError: (e: unknown) => boolean;
|
|
2903
|
+
}
|
|
2904
|
+
declare function createDataSourceManager(entityMap: Record<string, unknown>, options?: {
|
|
2905
|
+
databaseUrl?: string;
|
|
2906
|
+
idleTimeoutMillis?: number;
|
|
2907
|
+
}): DataSourceManager;
|
|
2908
|
+
|
|
2909
|
+
interface SeedEntityMap {
|
|
2910
|
+
users: unknown;
|
|
2911
|
+
user_groups: unknown;
|
|
2912
|
+
}
|
|
2913
|
+
declare function seedDefaultAdmin(ds: DataSource, entityMap: SeedEntityMap, opts?: {
|
|
2914
|
+
email?: string;
|
|
2915
|
+
password?: string;
|
|
2916
|
+
}): Promise<void>;
|
|
2917
|
+
|
|
2918
|
+
type UserVendorContext = {
|
|
2919
|
+
vendorIds: number[];
|
|
2920
|
+
activeVendorId: number | null;
|
|
2921
|
+
/** @deprecated legacy vendor_users.role */
|
|
2922
|
+
vendorRole: VendorUserRole | null;
|
|
2923
|
+
vendorRoleId: number | null;
|
|
2924
|
+
vendorRoleName: string | null;
|
|
2925
|
+
isVendorRoleOwner: boolean;
|
|
2926
|
+
vendorEntityPerms: Record<string, EntityPermissionFlags>;
|
|
2927
|
+
};
|
|
2928
|
+
/** Load vendor membership + active vendor role permissions for session. */
|
|
2929
|
+
declare function loadUserVendorContext(dataSource: DataSource, userId: number, preferredVendorId?: number | null): Promise<UserVendorContext>;
|
|
2930
|
+
|
|
2931
|
+
/**
|
|
2932
|
+
* Build NextAuth options for credentials auth. App can extend/override via extend().
|
|
2933
|
+
*/
|
|
2934
|
+
|
|
2935
|
+
interface NextAuthUser {
|
|
2936
|
+
id: number;
|
|
2937
|
+
email: string;
|
|
2938
|
+
name: string | null;
|
|
2939
|
+
password: string | null;
|
|
2940
|
+
blocked?: boolean;
|
|
2941
|
+
deleted?: boolean;
|
|
2942
|
+
groupId?: number | null;
|
|
2943
|
+
adminAccess?: boolean;
|
|
2944
|
+
group?: {
|
|
2945
|
+
name?: string;
|
|
2946
|
+
permissions?: Array<{
|
|
2947
|
+
entity: string;
|
|
2948
|
+
canCreate: boolean;
|
|
2949
|
+
canRead: boolean;
|
|
2950
|
+
canUpdate: boolean;
|
|
2951
|
+
canDelete: boolean;
|
|
2952
|
+
}>;
|
|
2953
|
+
};
|
|
2954
|
+
vendorIds?: number[];
|
|
2955
|
+
activeVendorId?: number | null;
|
|
2956
|
+
vendorRole?: 'owner' | 'staff' | null;
|
|
2957
|
+
vendorRoleId?: number | null;
|
|
2958
|
+
vendorRoleName?: string | null;
|
|
2959
|
+
isVendorRoleOwner?: boolean;
|
|
2960
|
+
vendorEntityPerms?: Record<string, {
|
|
2961
|
+
c: boolean;
|
|
2962
|
+
r: boolean;
|
|
2963
|
+
u: boolean;
|
|
2964
|
+
d: boolean;
|
|
2965
|
+
}>;
|
|
2966
|
+
}
|
|
2967
|
+
interface AuthorizeOtpInput {
|
|
2968
|
+
identifier: string;
|
|
2969
|
+
channel: 'email' | 'sms';
|
|
2970
|
+
code: string;
|
|
1819
2971
|
}
|
|
1820
|
-
|
|
1821
|
-
|
|
1822
|
-
|
|
1823
|
-
|
|
1824
|
-
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
|
|
1828
|
-
|
|
1829
|
-
|
|
1830
|
-
|
|
1831
|
-
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
|
|
2972
|
+
interface NextAuthOptionsConfig {
|
|
2973
|
+
/** Resolve user by email (e.g. from TypeORM). Return null if not found. */
|
|
2974
|
+
getUserByEmail: (email: string) => Promise<NextAuthUser | null>;
|
|
2975
|
+
comparePassword: (plain: string, hash: string) => Promise<boolean>;
|
|
2976
|
+
signInPage?: string;
|
|
2977
|
+
secret?: string;
|
|
2978
|
+
extend?: (options: NextAuthOptions) => NextAuthOptions;
|
|
2979
|
+
/** When false, password CredentialsProvider is omitted. Default true. */
|
|
2980
|
+
enablePasswordLogin?: boolean;
|
|
2981
|
+
/** When true, registers CredentialsProvider id `otp`. Requires authorizeOtp. Default false. */
|
|
2982
|
+
enableOtpLogin?: boolean;
|
|
2983
|
+
/** Validate OTP and return user (same shape as password flow) or null. */
|
|
2984
|
+
authorizeOtp?: (input: AuthorizeOtpInput) => Promise<NextAuthUser | null>;
|
|
2985
|
+
/**
|
|
2986
|
+
* Customer group sign-in policy for credentials/OTP on a shared `/api/auth` route:
|
|
2987
|
+
* - `true` — always allow (dedicated storefront auth)
|
|
2988
|
+
* - `false` — always block
|
|
2989
|
+
* - omitted — auto: allow unless `callbackUrl` targets `/admin` (storefront `/signin` works unchanged)
|
|
2990
|
+
*/
|
|
2991
|
+
allowCustomerLogin?: boolean;
|
|
1835
2992
|
}
|
|
2993
|
+
declare function getNextAuthOptions(config: NextAuthOptionsConfig): NextAuthOptions;
|
|
2994
|
+
/** Storefront sign-in: allows Customer group; use with signInPage `/signin`. */
|
|
2995
|
+
declare function getStorefrontNextAuthOptions(config: Omit<NextAuthOptionsConfig, 'allowCustomerLogin'>): NextAuthOptions;
|
|
1836
2996
|
|
|
1837
|
-
|
|
1838
|
-
declare
|
|
1839
|
-
|
|
1840
|
-
|
|
1841
|
-
|
|
1842
|
-
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
|
|
1855
|
-
|
|
1856
|
-
|
|
1857
|
-
|
|
1858
|
-
|
|
1859
|
-
|
|
1860
|
-
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
1865
|
-
|
|
1866
|
-
|
|
1867
|
-
|
|
1868
|
-
|
|
1869
|
-
|
|
2997
|
+
/** Attach vendor membership + role permissions for NextAuth (use in app getUserByEmail). */
|
|
2998
|
+
declare function enrichUserWithVendorContext(dataSource: DataSource, user: NextAuthUser | null): Promise<NextAuthUser | null>;
|
|
2999
|
+
|
|
3000
|
+
/** Merge DB group + vendor_users into session (JWT often missing these). Server/API only. */
|
|
3001
|
+
declare function hydrateVendorSessionUser(dataSource: DataSource, user: SessionUser | null | undefined): Promise<SessionUser | null | undefined>;
|
|
3002
|
+
|
|
3003
|
+
interface NavItem {
|
|
3004
|
+
id: string;
|
|
3005
|
+
label: string;
|
|
3006
|
+
url: string;
|
|
3007
|
+
openInNewTab?: boolean;
|
|
3008
|
+
/** When set, url is derived from the linked page slug. */
|
|
3009
|
+
pageId?: number;
|
|
3010
|
+
children?: NavItem[];
|
|
3011
|
+
}
|
|
3012
|
+
interface NavbarConfig {
|
|
3013
|
+
logo: string;
|
|
3014
|
+
items: NavItem[];
|
|
3015
|
+
ctaLabel?: string;
|
|
3016
|
+
ctaUrl?: string;
|
|
3017
|
+
/** Optional variant for theme-specific layout (e.g. "page2"). */
|
|
3018
|
+
variant?: string;
|
|
3019
|
+
}
|
|
3020
|
+
interface FooterConfig {
|
|
3021
|
+
copyright: string;
|
|
3022
|
+
columns: {
|
|
3023
|
+
title: string;
|
|
3024
|
+
links: {
|
|
3025
|
+
label: string;
|
|
3026
|
+
url: string;
|
|
3027
|
+
}[];
|
|
3028
|
+
}[];
|
|
3029
|
+
socialLinks: {
|
|
3030
|
+
icon: string;
|
|
3031
|
+
url: string;
|
|
3032
|
+
}[];
|
|
3033
|
+
/** When set, footer shows this logo (e.g. same as navbar). */
|
|
3034
|
+
logo?: string;
|
|
1870
3035
|
}
|
|
1871
3036
|
|
|
1872
|
-
|
|
1873
|
-
|
|
1874
|
-
|
|
1875
|
-
|
|
1876
|
-
|
|
1877
|
-
|
|
1878
|
-
conversation: ChatConversation;
|
|
3037
|
+
interface PublicThemeSettingsPayload {
|
|
3038
|
+
activeThemeId: string;
|
|
3039
|
+
primaryColor: string;
|
|
3040
|
+
secondaryColor: string;
|
|
3041
|
+
navbarConfig: NavbarConfig;
|
|
3042
|
+
footerOverrides: Partial<FooterConfig>;
|
|
1879
3043
|
}
|
|
3044
|
+
declare function loadPublicThemeSettings(config: {
|
|
3045
|
+
dataSource: DataSource;
|
|
3046
|
+
entityMap: EntityMap$2;
|
|
3047
|
+
encryptionKey?: string;
|
|
3048
|
+
defaultActiveThemeId?: string;
|
|
3049
|
+
defaultPrimaryColor?: string;
|
|
3050
|
+
defaultSecondaryColor?: string;
|
|
3051
|
+
}): Promise<PublicThemeSettingsPayload>;
|
|
1880
3052
|
|
|
1881
|
-
|
|
3053
|
+
/** Normalize a logical media folder path: no leading/trailing slashes, no ".." segments, max length. */
|
|
3054
|
+
declare function sanitizeMediaFolderPath(input: unknown): string;
|
|
3055
|
+
/** Single path segment for storage (folder name or legacy path segment). */
|
|
3056
|
+
declare function sanitizeStorageSegment(name: string): string;
|
|
3057
|
+
|
|
3058
|
+
type EntityMap = Record<string, EntityTarget<ObjectLiteral>>;
|
|
3059
|
+
/** Build `a/b/c` path under `uploads/` from the chain of folder rows up to root. */
|
|
3060
|
+
declare function relativePathFromMediaParentId(dataSource: DataSource, entityMap: EntityMap, parentId: number | null): Promise<string>;
|
|
3061
|
+
|
|
3062
|
+
declare const ZIP_MIME_TYPES: Set<string>;
|
|
3063
|
+
declare function isZipMedia(mime: string | null | undefined, filename: string): boolean;
|
|
3064
|
+
|
|
3065
|
+
/**
|
|
3066
|
+
* Executes `fn` inside a transaction where the PostgreSQL GUC
|
|
3067
|
+
* `app.vendor_id` is set for the duration of that transaction.
|
|
3068
|
+
*
|
|
3069
|
+
* This activates the `vendor_isolation` RLS policy added by the
|
|
3070
|
+
* `VendorRls1775940000000` migration.
|
|
3071
|
+
*
|
|
3072
|
+
* vendorId = 0 → admin / all-access (policy allows everything)
|
|
3073
|
+
* vendorId > 0 → only rows whose `vendorId` column matches
|
|
3074
|
+
*
|
|
3075
|
+
* Example:
|
|
3076
|
+
* const orders = await withVendorRlsContext(dataSource, 4, (ds) =>
|
|
3077
|
+
* ds.getRepository(Order).find({ where: { deleted: false } })
|
|
3078
|
+
* );
|
|
3079
|
+
*/
|
|
3080
|
+
declare function withVendorRlsContext<T>(dataSource: DataSource, vendorId: number, fn: (dataSource: DataSource) => Promise<T>): Promise<T>;
|
|
3081
|
+
/**
|
|
3082
|
+
* Convenience wrapper: sets admin mode (vendor_id = '0') so all rows are
|
|
3083
|
+
* visible regardless of their vendorId. Use for platform-admin queries.
|
|
3084
|
+
*/
|
|
3085
|
+
declare function withAdminRlsContext<T>(dataSource: DataSource, fn: (dataSource: DataSource) => Promise<T>): Promise<T>;
|
|
3086
|
+
|
|
3087
|
+
type EnsureVendorCustomerDetails = {
|
|
3088
|
+
name: string;
|
|
3089
|
+
email: string;
|
|
3090
|
+
phone?: string | null;
|
|
3091
|
+
};
|
|
3092
|
+
declare function isCustomerTypeContact(type: unknown): boolean;
|
|
3093
|
+
/** Restrict contact list to rows linked in `vendor_customers` with type customer. */
|
|
3094
|
+
declare function applyVendorCustomersContactFilter(qb: SelectQueryBuilder<typeorm.ObjectLiteral>, contactAlias: string, scope: VendorScope, vendorIdFilter: number | null): void;
|
|
3095
|
+
declare function contactIsVendorCustomer(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number, contactId: number): Promise<boolean>;
|
|
3096
|
+
/** Returns an error message when the contact is not a vendor-linked customer; otherwise null. */
|
|
3097
|
+
declare function assertContactAllowedForVendorOrder(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number, contactId: number): Promise<string | null>;
|
|
3098
|
+
declare function resolveVendorIdForContactCheck(scope: VendorScope, bodyOrRow: Record<string, unknown>): number | null;
|
|
3099
|
+
/**
|
|
3100
|
+
* When an order is placed for a manually entered customer, ensure they appear in
|
|
3101
|
+
* vendor customers: customer row, vendor_customers link, and contact type.
|
|
3102
|
+
*/
|
|
3103
|
+
declare function ensureVendorCustomerForOrderContact(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number, contactId: number, details: EnsureVendorCustomerDetails): Promise<void>;
|
|
3104
|
+
|
|
3105
|
+
/** One band: refund % when cancellation falls N days before event start. */
|
|
3106
|
+
type RefundPolicyTier = {
|
|
3107
|
+
/** Inclusive lower bound (days before event start; 0 = event day). */
|
|
3108
|
+
fromDaysBefore: number;
|
|
3109
|
+
/** Exclusive upper bound, or null for open-ended (e.g. 20+ days). */
|
|
3110
|
+
toDaysBefore: number | null;
|
|
3111
|
+
percentage: number;
|
|
3112
|
+
};
|
|
3113
|
+
type RefundPolicyType = 'percentage' | 'event_tiers';
|
|
3114
|
+
type RefundPolicyLike = {
|
|
3115
|
+
id?: number;
|
|
3116
|
+
type: RefundPolicyType;
|
|
3117
|
+
value: number;
|
|
3118
|
+
refundWindowDays: number;
|
|
3119
|
+
tiers?: RefundPolicyTier[] | null;
|
|
3120
|
+
};
|
|
3121
|
+
type RefundCalculationResult = {
|
|
3122
|
+
amount: number;
|
|
3123
|
+
percentage: number;
|
|
3124
|
+
daysBeforeEvent: number | null;
|
|
3125
|
+
daysSincePurchase: number | null;
|
|
3126
|
+
policyId: number | null;
|
|
3127
|
+
summary: string;
|
|
3128
|
+
/** Order cancelled without policy-based refund (no policy on event). */
|
|
3129
|
+
directCancellation?: boolean;
|
|
3130
|
+
eventId?: number | null;
|
|
3131
|
+
eventName?: string | null;
|
|
3132
|
+
};
|
|
3133
|
+
declare function normalizeRefundTiers(raw: unknown): RefundPolicyTier[];
|
|
3134
|
+
declare function validateRefundTiers(tiers: RefundPolicyTier[]): string | null;
|
|
3135
|
+
declare function daysBeforeEventStart(eventStart: Date, asOf?: Date): number;
|
|
3136
|
+
declare function formatTierRange(tier: RefundPolicyTier): string;
|
|
3137
|
+
declare function describeEventTierPolicy(tiers: RefundPolicyTier[]): string;
|
|
3138
|
+
declare function calculateRefundFromPolicy(policy: RefundPolicyLike | null | undefined, orderTotal: number, options?: {
|
|
3139
|
+
orderCreatedAt?: Date | null;
|
|
3140
|
+
eventStartDate?: Date | null;
|
|
3141
|
+
asOf?: Date;
|
|
3142
|
+
}): RefundCalculationResult;
|
|
3143
|
+
|
|
3144
|
+
type PolicyRow = RefundPolicyLike & {
|
|
1882
3145
|
id: number;
|
|
1883
|
-
|
|
3146
|
+
};
|
|
3147
|
+
declare function calculateOrderRefundPreview(dataSource: DataSource, entityMap: EntityMap$2, order: {
|
|
3148
|
+
id: number;
|
|
3149
|
+
vendorId?: number | null;
|
|
3150
|
+
total?: number | null;
|
|
3151
|
+
createdAt?: Date | string | null;
|
|
3152
|
+
}, asOf?: Date): Promise<RefundCalculationResult & {
|
|
3153
|
+
eventStartDate: string | null;
|
|
3154
|
+
directCancellation: boolean;
|
|
3155
|
+
eventId: number | null;
|
|
3156
|
+
eventName: string | null;
|
|
3157
|
+
}>;
|
|
3158
|
+
/** @deprecated Use event-attached policy via calculateOrderRefundPreview. */
|
|
3159
|
+
declare function findActiveRefundPolicyForVendor(dataSource: DataSource, entityMap: EntityMap$2, vendorId: number | null | undefined): Promise<PolicyRow | null>;
|
|
3160
|
+
|
|
3161
|
+
declare class OtpChallenge {
|
|
3162
|
+
id: number;
|
|
3163
|
+
purpose: string;
|
|
3164
|
+
channel: string;
|
|
3165
|
+
identifier: string;
|
|
3166
|
+
codeHash: string;
|
|
3167
|
+
expiresAt: Date;
|
|
3168
|
+
attempts: number;
|
|
3169
|
+
consumedAt: Date | null;
|
|
1884
3170
|
createdAt: Date;
|
|
1885
|
-
updatedAt: Date;
|
|
1886
|
-
/** Set when a chat lead email was sent for this conversation (intent tool). */
|
|
1887
|
-
leadEmailSentAt: Date | null;
|
|
1888
|
-
contact: Contact;
|
|
1889
|
-
messages: ChatMessage[];
|
|
1890
3171
|
}
|
|
1891
3172
|
|
|
1892
|
-
declare class
|
|
3173
|
+
declare class PasswordResetToken {
|
|
1893
3174
|
id: number;
|
|
1894
|
-
name: string;
|
|
1895
3175
|
email: string;
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
company: string | null;
|
|
1899
|
-
taxId: string | null;
|
|
1900
|
-
notes: string | null;
|
|
3176
|
+
token: string;
|
|
3177
|
+
expiresAt: Date;
|
|
1901
3178
|
createdAt: Date;
|
|
1902
|
-
updatedAt: Date;
|
|
1903
|
-
deletedAt: Date | null;
|
|
1904
|
-
deleted: boolean;
|
|
1905
|
-
createdBy: number | null;
|
|
1906
|
-
updatedBy: number | null;
|
|
1907
|
-
deletedBy: number | null;
|
|
1908
|
-
userId: number | null;
|
|
1909
|
-
user: User | null;
|
|
1910
|
-
form_submissions: FormSubmission[];
|
|
1911
|
-
addresses: Address[];
|
|
1912
|
-
orders: Order[];
|
|
1913
|
-
payments: Payment[];
|
|
1914
|
-
chatConversations: ChatConversation[];
|
|
1915
|
-
orderAddresses: OrderAddresses[];
|
|
1916
3179
|
}
|
|
1917
3180
|
|
|
1918
3181
|
declare class Config {
|
|
@@ -2211,7 +3474,8 @@ declare class RssFeed {
|
|
|
2211
3474
|
declare class VendorCustomer {
|
|
2212
3475
|
id: number;
|
|
2213
3476
|
vendorId: number;
|
|
2214
|
-
contactId: number;
|
|
3477
|
+
contactId: number | null;
|
|
3478
|
+
customerId: number;
|
|
2215
3479
|
/** Optional vendor-specific notes about this customer. */
|
|
2216
3480
|
notes: string | null;
|
|
2217
3481
|
/** Optional vendor-specific tags/labels. */
|
|
@@ -2219,10 +3483,252 @@ declare class VendorCustomer {
|
|
|
2219
3483
|
createdAt: Date;
|
|
2220
3484
|
updatedAt: Date;
|
|
2221
3485
|
vendor: Vendor;
|
|
2222
|
-
contact: Contact;
|
|
3486
|
+
contact: Contact | null;
|
|
3487
|
+
customer: Customer;
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
declare enum ComboItemType {
|
|
3491
|
+
FIXED = "fixed",
|
|
3492
|
+
ADDONS = "addons"
|
|
3493
|
+
}
|
|
3494
|
+
declare class ComboItem {
|
|
3495
|
+
id: number;
|
|
3496
|
+
comboId: number;
|
|
3497
|
+
combo: Combo;
|
|
3498
|
+
productId: number;
|
|
3499
|
+
product: Product;
|
|
3500
|
+
type: ComboItemType;
|
|
3501
|
+
}
|
|
3502
|
+
|
|
3503
|
+
declare enum ComboStatus {
|
|
3504
|
+
ACTIVE = "active",
|
|
3505
|
+
INACTIVE = "inactive",
|
|
3506
|
+
DRAFT = "draft"
|
|
3507
|
+
}
|
|
3508
|
+
declare class Combo {
|
|
3509
|
+
id: number;
|
|
3510
|
+
name: string;
|
|
3511
|
+
desc?: string;
|
|
3512
|
+
eventId: number;
|
|
3513
|
+
event: Event;
|
|
3514
|
+
price: number;
|
|
3515
|
+
currencyPrices: Record<string, number> | null;
|
|
3516
|
+
minSelectableItems: number;
|
|
3517
|
+
maxSelectableItems: number;
|
|
3518
|
+
status: ComboStatus;
|
|
3519
|
+
startsAt?: Date;
|
|
3520
|
+
endsAt?: Date;
|
|
3521
|
+
metadata?: Record<string, any>;
|
|
3522
|
+
items: ComboItem[];
|
|
3523
|
+
createdAt: Date;
|
|
3524
|
+
updatedAt: Date;
|
|
3525
|
+
deletedAt?: Date;
|
|
3526
|
+
deleted: boolean;
|
|
3527
|
+
createdBy?: number;
|
|
3528
|
+
updatedBy?: number;
|
|
3529
|
+
deletedBy?: number;
|
|
3530
|
+
}
|
|
3531
|
+
|
|
3532
|
+
declare enum RefundMethod {
|
|
3533
|
+
CARD = "card",
|
|
3534
|
+
UPI = "upi",
|
|
3535
|
+
NET_BANKING = "net_banking"
|
|
3536
|
+
}
|
|
3537
|
+
declare enum RefundRequestStatus {
|
|
3538
|
+
REQUESTED = "requested",
|
|
3539
|
+
APPROVED = "approved",
|
|
3540
|
+
REJECTED = "rejected",
|
|
3541
|
+
REFUNDED = "refunded"
|
|
3542
|
+
}
|
|
3543
|
+
declare class RefundRequest {
|
|
3544
|
+
id: number;
|
|
3545
|
+
refundPolicyId: number;
|
|
3546
|
+
refundPolicy: RefundPolicy;
|
|
3547
|
+
orderId: number;
|
|
3548
|
+
order: Order;
|
|
3549
|
+
customerId: number;
|
|
3550
|
+
customer: Customer;
|
|
3551
|
+
reason?: string;
|
|
3552
|
+
refundMethod: RefundMethod;
|
|
3553
|
+
status: RefundRequestStatus;
|
|
3554
|
+
expectedRefundAmount: number;
|
|
3555
|
+
approvedRefundAmount?: number;
|
|
3556
|
+
}
|
|
3557
|
+
|
|
3558
|
+
declare class Attendee {
|
|
3559
|
+
id: number;
|
|
3560
|
+
displayName: string;
|
|
3561
|
+
email: string;
|
|
3562
|
+
contactId: number | null;
|
|
3563
|
+
contact: Contact | null;
|
|
2223
3564
|
}
|
|
2224
3565
|
|
|
2225
3566
|
/** Map API resource segment (e.g. "blogs", "form_submissions") to entity. Used by CRUD handler. */
|
|
2226
3567
|
declare const CMS_ENTITY_MAP: Record<string, EntityTarget<typeorm.ObjectLiteral>>;
|
|
2227
3568
|
|
|
2228
|
-
|
|
3569
|
+
/** Minimal DB handle for RBAC debug (avoids importing `typeorm` in the auth bundle). */
|
|
3570
|
+
type RbacDebugDataSource = {
|
|
3571
|
+
query: (sql: string, parameters?: unknown[]) => Promise<unknown>;
|
|
3572
|
+
};
|
|
3573
|
+
/** Set `CMS_RBAC_DEBUG=true` in `.env` to log permission decisions (server console). */
|
|
3574
|
+
declare function isRbacDebugEnabled(): boolean;
|
|
3575
|
+
declare function logRbac(message: string, data?: Record<string, unknown>): void;
|
|
3576
|
+
declare function summarizeEntityPerms(entityPerms: Record<string, EntityPermissionFlags> | undefined): Record<string, {
|
|
3577
|
+
c: boolean;
|
|
3578
|
+
r: boolean;
|
|
3579
|
+
u: boolean;
|
|
3580
|
+
d: boolean;
|
|
3581
|
+
}>;
|
|
3582
|
+
interface EntityAccessExplanation {
|
|
3583
|
+
allowed: boolean;
|
|
3584
|
+
reason: string;
|
|
3585
|
+
userSnapshot: Record<string, unknown>;
|
|
3586
|
+
}
|
|
3587
|
+
/** Same rules as `sessionHasEntityAccess`, but returns why access was granted or denied. */
|
|
3588
|
+
declare function explainSessionEntityAccess(user: SessionUser | null | undefined, entity: string, action: EntityCrudAction): EntityAccessExplanation;
|
|
3589
|
+
declare function logEntityAccessDecision(dataSource: RbacDebugDataSource | undefined, context: string, user: SessionUser | null | undefined, entity: string, action: EntityCrudAction, extra?: Record<string, unknown>): Promise<void>;
|
|
3590
|
+
|
|
3591
|
+
/** Platform super admin (`user_groups.id = 1` or Administrator group). */
|
|
3592
|
+
declare const SUPER_ADMIN_GROUP_ID = 1;
|
|
3593
|
+
/** Vendor store admin (`user_groups.id = 5` or vendor-linked portal users). */
|
|
3594
|
+
declare const VENDOR_ADMIN_GROUP_ID = 5;
|
|
3595
|
+
declare function isSuperAdmin(user: SessionUser | null | undefined): boolean;
|
|
3596
|
+
declare function isVendorAdmin(user: SessionUser | null | undefined): boolean;
|
|
3597
|
+
|
|
3598
|
+
/**
|
|
3599
|
+
* Ensures the Administrator group has full CRUD on every permissionable entity
|
|
3600
|
+
* for the given entity map. Idempotent: upserts per entity.
|
|
3601
|
+
*/
|
|
3602
|
+
declare function seedAdministratorPermissions(dataSource: DataSource, entityMap: Record<string, unknown>): Promise<void>;
|
|
3603
|
+
|
|
3604
|
+
interface CmsMiddlewareRequest {
|
|
3605
|
+
nextUrl: {
|
|
3606
|
+
pathname: string;
|
|
3607
|
+
};
|
|
3608
|
+
url: string;
|
|
3609
|
+
method: string;
|
|
3610
|
+
cookies: {
|
|
3611
|
+
get: (name: string) => {
|
|
3612
|
+
value?: string;
|
|
3613
|
+
} | undefined;
|
|
3614
|
+
};
|
|
3615
|
+
/**
|
|
3616
|
+
* Full Next.js request (e.g. `NextRequest`). When provided, session is resolved via
|
|
3617
|
+
* `getToken()` so chunked `next-auth.session-token.N` cookies work.
|
|
3618
|
+
*/
|
|
3619
|
+
req?: Parameters<typeof getToken>[0]['req'];
|
|
3620
|
+
}
|
|
3621
|
+
interface CmsMiddlewareConfig {
|
|
3622
|
+
publicAdminPaths?: string[];
|
|
3623
|
+
publicApiPaths?: string[];
|
|
3624
|
+
/** path -> allowed methods */
|
|
3625
|
+
publicApiMethods?: Record<string, string[]>;
|
|
3626
|
+
signInPath?: string;
|
|
3627
|
+
/** @deprecated Prefer passing `req` on the request; used only when `req` is omitted. */
|
|
3628
|
+
getSessionToken?: (request: CmsMiddlewareRequest) => string | undefined;
|
|
3629
|
+
secret?: string;
|
|
3630
|
+
}
|
|
3631
|
+
/** Default public API paths (no auth). Sites should extend this with their own routes. */
|
|
3632
|
+
declare const defaultPublicApiMethods: Record<string, string[]>;
|
|
3633
|
+
/**
|
|
3634
|
+
* Returns middleware logic. Use from Next.js middleware:
|
|
3635
|
+
* import { createCmsMiddleware } from '@infuro/cms-core';
|
|
3636
|
+
* export async function middleware(request: NextRequest) {
|
|
3637
|
+
* const result = await cmsMiddleware({ ...request fields, req: request });
|
|
3638
|
+
* ...
|
|
3639
|
+
* }
|
|
3640
|
+
* export const config = { matcher: ['/admin/:path*', '/api/:path*'] };
|
|
3641
|
+
*/
|
|
3642
|
+
declare function createCmsMiddleware(config?: CmsMiddlewareConfig): (request: CmsMiddlewareRequest) => Promise<{
|
|
3643
|
+
type: "next";
|
|
3644
|
+
} | {
|
|
3645
|
+
type: "redirect";
|
|
3646
|
+
url: string;
|
|
3647
|
+
} | {
|
|
3648
|
+
type: "json";
|
|
3649
|
+
status: number;
|
|
3650
|
+
body: unknown;
|
|
3651
|
+
}>;
|
|
3652
|
+
|
|
3653
|
+
/** Set `CMS_AUTH_DEBUG=false` to silence server auth logs in development. */
|
|
3654
|
+
declare function isAuthDebugEnabled(): boolean;
|
|
3655
|
+
/** Browser console logs; set `NEXT_PUBLIC_CMS_AUTH_DEBUG=false` to silence. */
|
|
3656
|
+
declare function isAuthDebugClientEnabled(): boolean;
|
|
3657
|
+
declare function logAuth(message: string, data?: Record<string, unknown>): void;
|
|
3658
|
+
declare function logAuthClient(message: string, data?: Record<string, unknown>): void;
|
|
3659
|
+
declare function summarizeSessionUserForLog(user: unknown): Record<string, unknown>;
|
|
3660
|
+
declare function nextAuthCookieDebugInfo(): Record<string, unknown>;
|
|
3661
|
+
|
|
3662
|
+
type VendorOwnerActivation = 'invite' | 'password';
|
|
3663
|
+
interface VendorOnboardHandlersConfig {
|
|
3664
|
+
dataSource: DataSource;
|
|
3665
|
+
entityMap: EntityMap$2;
|
|
3666
|
+
json: (body: unknown, init?: {
|
|
3667
|
+
status?: number;
|
|
3668
|
+
}) => Response;
|
|
3669
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
3670
|
+
baseUrl: string;
|
|
3671
|
+
getCms?: () => Promise<{
|
|
3672
|
+
getPlugin: (name: string) => unknown;
|
|
3673
|
+
}>;
|
|
3674
|
+
hashPassword?: (plain: string) => Promise<string>;
|
|
3675
|
+
minPasswordLength?: number;
|
|
3676
|
+
}
|
|
3677
|
+
declare function createVendorOnboardHandlers(config: VendorOnboardHandlersConfig): {
|
|
3678
|
+
/** POST /api/admin/vendors/onboard — create vendor + owner user + vendor_users + invite */
|
|
3679
|
+
onboard(req: Request): Promise<Response>;
|
|
3680
|
+
/** POST /api/admin/vendor/switch — set active vendor in session (JWT update via client) */
|
|
3681
|
+
switchVendor(req: Request): Promise<Response>;
|
|
3682
|
+
/** GET /api/admin/vendor/team */
|
|
3683
|
+
listTeam(): Promise<Response>;
|
|
3684
|
+
/** POST /api/admin/vendor/team — add staff to vendor */
|
|
3685
|
+
addTeamMember(req: Request): Promise<Response>;
|
|
3686
|
+
/** PATCH /api/admin/vendor/team/:userId — change member store role */
|
|
3687
|
+
updateTeamMemberRole(req: Request, userIdStr: string): Promise<Response>;
|
|
3688
|
+
/** DELETE /api/admin/vendor/team/:userId */
|
|
3689
|
+
removeTeamMember(_req: Request, userIdStr: string): Promise<Response>;
|
|
3690
|
+
};
|
|
3691
|
+
|
|
3692
|
+
interface StorefrontOtpFlags {
|
|
3693
|
+
login?: boolean;
|
|
3694
|
+
verifyEmail?: boolean;
|
|
3695
|
+
verifyPhone?: boolean;
|
|
3696
|
+
}
|
|
3697
|
+
interface StorefrontApiConfig {
|
|
3698
|
+
dataSource: DataSource;
|
|
3699
|
+
entityMap: EntityMap$2;
|
|
3700
|
+
json: (body: unknown, init?: {
|
|
3701
|
+
status?: number;
|
|
3702
|
+
headers?: HeadersInit;
|
|
3703
|
+
}) => Response;
|
|
3704
|
+
getSessionUser: () => Promise<SessionUser | null>;
|
|
3705
|
+
guestCookieName?: string;
|
|
3706
|
+
/** Required for POST storefront/register */
|
|
3707
|
+
hashPassword?: (plain: string) => Promise<string>;
|
|
3708
|
+
/** When set, new registrations are blocked until email is verified and a signup email is sent. */
|
|
3709
|
+
getCms?: () => Promise<{
|
|
3710
|
+
getPlugin: (name: string) => unknown;
|
|
3711
|
+
}>;
|
|
3712
|
+
getCompanyDetails?: () => Promise<CompanyDetails>;
|
|
3713
|
+
/** Origin for verify links (e.g. process.env.NEXTAUTH_URL). Required with getCms for verification URLs. */
|
|
3714
|
+
publicSiteUrl?: string;
|
|
3715
|
+
/** When a flag is true, the corresponding OTP storefront route is enabled. */
|
|
3716
|
+
otpFlags?: StorefrontOtpFlags;
|
|
3717
|
+
/** Defaults to OTP_PEPPER or NEXTAUTH_SECRET. */
|
|
3718
|
+
otpPepper?: string;
|
|
3719
|
+
defaultPhoneCountryCode?: string;
|
|
3720
|
+
/** When false, login OTP send accepts email only (no phone). Default true. */
|
|
3721
|
+
otpAllowPhoneLogin?: boolean;
|
|
3722
|
+
}
|
|
3723
|
+
declare function createStorefrontApiHandler(config: StorefrontApiConfig): {
|
|
3724
|
+
handle(method: string, path: string[], req: Request): Promise<Response>;
|
|
3725
|
+
};
|
|
3726
|
+
|
|
3727
|
+
interface AdminNavItem {
|
|
3728
|
+
href: string;
|
|
3729
|
+
label: string;
|
|
3730
|
+
icon?: string;
|
|
3731
|
+
}
|
|
3732
|
+
declare const DEFAULT_ADMIN_NAV: AdminNavItem[];
|
|
3733
|
+
|
|
3734
|
+
export { ADMIN_GROUP_NAME, Address, type AdminNavItem, type AnalyticsHandlerConfig, type AnalyticsPluginConfig, Attendee, Attribute, type AuthHandlersConfig, type AuthHelpers, type AuthorizeOtpInput, BLOG_GENERATOR_AGENT_NAME, BLOG_GENERATOR_DEFAULT_SYSTEM_INSTRUCTION, BLOG_GENERATOR_DEFAULT_VALIDATION_RULES, BLOG_GENERATOR_LLM_AGENT_SLUG, BLOG_GENERATOR_MARKDOWN_ARTICLE_SEPARATOR, BLOG_METADATA_ENRICHER_AGENT_NAME, BLOG_METADATA_ENRICHER_DEFAULT_SYSTEM_INSTRUCTION, BLOG_METADATA_ENRICHER_DEFAULT_VALIDATION_RULES, BLOG_METADATA_ENRICHER_LLM_AGENT_SLUG, Blog, type BlogBySlugConfig, type BlogGeneratorBlogDraft, type BlogGeneratorDraftParseMode, type BlogGeneratorPluginConfig, type BlogGeneratorSeoDraft, BlogGeneratorService, Brand, CMS_ENTITY_MAP, type CachePluginConfig, type CacheService, type CaptchaProviderId, type CaptchaPublicConfig, CaptchaService, type CaptchaVerifyResult, Cart, CartItem, Category, type ChangePasswordConfig, ChatConversation, ChatMessage, type ChatPublicConfig, type CmsApiHandlerConfig, type CmsApp, type CmsGetter, type CmsMiddlewareConfig, type CmsMiddlewareRequest, type CmsPlugin, Collection, Combo, ComboItem, Comment, type CompanyDetails, Config, Contact, type CreateCmsAppOptions, type CrudHandlerOptions, Currency, CurrencyExchange, Customer, Customer_Contacts, DEFAULT_ADMIN_NAV, type DashboardStatsConfig, type DataSourceManager, Discount, DiscountRules, type ERPPluginConfig, type ERPPluginInstance, ERPSubmissionService, EVENT_ORDER_MESSAGE_TEMPLATE_DEFAULTS, EVENT_ORDER_TEMPLATE_KEY, EVENT_ORDER_TEMPLATE_VARIABLES, type EcommerceAnalyticsConfig, type EmailData, type EmailJobPayload, type EmailPluginConfig, EmailService, type EmailServiceInterface, type EmailTemplateName, type EmailTemplateResult, type EnsureCustomerUserInput, type EnsureVendorCustomerDetails, type EntityCrudAction, type EntityMap$2 as EntityMap, type EntityPermissionFlags, type ErpContactSyncInput, type ErpCreateContactPayload, type ErpJobPayload, type ErpPaidOrderDataSource, type ErpPaidOrderEntityMap, Event, type EventNotificationHandlersConfig, type EventOrderMessageTemplateHandlersConfig, type EventOrderNotificationChannel$1 as EventOrderNotificationChannel, type EventOrderNotificationTemplates, type EventOrderTemplateOverride$1 as EventOrderTemplateOverride, EventProduct, type ExtraPublicWriteRule, type FacebookMeAccountsResponse, type FacebookPageAccount, type ForgotPasswordConfig, Form, type FormBySlugConfig, FormField, FormSubmission, type GetPublicSettingsGroupConfig, type GetPublicSettingsGroupDataSource, type GetSession, type InviteAcceptConfig, JOB_RUNNER_QUEUE, type CmsAppLike as JobRunnerCmsAppLike, type JobRunnerDeps, type JobRunnerPayload, JobSchedule, type JobScheduleApiConfig, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, type LatestArticleFromFeed, LlmAgent, type LlmAgentKnowledgeApiConfig, type LlmAgentOptions, type LlmAgentValidationRulesJson, type LlmChatOptions, type LlmEmbeddingProvider, type LlmMessage, type LlmPluginConfig, LlmService, type LlmServiceEmbedOptions, type LlmServiceInterface, type LocalStoragePluginConfig, type Logger, Media, MessageTemplate, type MetaGraphMutationResponse, type NextAuthOptionsConfig, type NextAuthUser, OPEN_ENDPOINTS, Order, OrderAddresses, OrderDiscounts, OrderItem, type OrderPlacedEmailPayload, type OrderPlacedLineItem, OtpChallenge, type OtpChannel, type OtpPurpose, PERMISSION_REQUIRED_ENDPOINTS, Page, type ParsedLlmAgentValidation, PasswordResetToken, Payment, type PaymentIntent, type PaymentPluginConfig, type PaymentServiceInterface, Permission, type PgBossPluginConfig, PgBossService, type PipelineNames, type PluginContext, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, type PublicThemeSettingsPayload, type QueuePluginConfig, type QueueService, RBAC_ADMIN_ONLY_ENTITIES, type RefundCalculationResult, RefundPolicy, type RefundPolicyLike, type RefundPolicyTier, RefundRequest, type RenderEmailOptions, type RenderedEmail, RssArticle, RssFeed, type S3StoragePluginConfig, SUPER_ADMIN_GROUP_ID, type SendVendorOnboardEmailInput, Seo, type SeoLike, type SeoMetadataOverrides, type SessionUser, type SetPasswordConfig, type SettingsApiConfig, type SmsJobPayload, type SmsPluginConfig, type SmsProviderChoice, type SmsProviderId, type SmsServiceConfig, type SmsServiceInterface, type SocialLinkItem, type SocialMediaPluginConfig, type StorageService, type StorefrontApiConfig, type StorefrontOtpFlags, Tag, Tax, type TemplateContext, type UploadHandlerConfig, User, type UserAuthApiConfig, type UserAvatarConfig, UserGroup, type UserProfileConfig, type UsersApiConfig, VENDOR_ADMIN_GROUP_ID, VENDOR_OWNER_GROUP_NAME, VENDOR_SCOPED_STORE_ENTITIES, VENDOR_STORE_RBAC_ENTITIES, Vendor, VendorCustomer, type VendorDashboardConfig, type VendorOnboardHandlersConfig, type VendorOwnerActivation, VendorRole, VendorRolePermission, VendorUser, type WhatsAppJobPayload, type WhatsAppPluginConfig, type WhatsAppServiceConfig, type WhatsAppServiceInterface, Wishlist, WishlistItem, ZIP_MIME_TYPES, allowRateLimit, analyticsPlugin, applyVendorCustomersContactFilter, assertCaptchaOk, assertContactAllowedForVendorOrder, blogGeneratorPlugin, buildBlogMetadataUserPrompt, buildCaptchaPublicConfig, buildCronFromSchedule, buildEventOrderTemplateVariables, buildRssUserPromptFromFeeds, cachePlugin, calculateOrderRefundPreview, calculateRefundFromPolicy, canManageRoles, canManageVendorRoles, canManageVendorTeam, canOnboardVendors, captchaPlugin, cn, contactIsVendorCustomer, countRecentOtpSends, createAnalyticsHandlers, createAuthHelpers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAuthBundle, createCmsMiddleware, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createDataSourceManager, createEcommerceAnalyticsHandler, createEventNotificationHandlers, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, customerPhoneForUser, daysBeforeEventStart, defaultPublicApiMethods, describeEventTierPolicy, dispatchEventOrderNotifications, emailPlugin, emailTemplates, enrichUserWithVendorContext, ensureCustomerForUser, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, erpPlugin, explainSessionEntityAccess, fetchSeoBySlug, findActiveRefundPolicyForVendor, formatDate, formatDateOnly, formatDateTime, formatTierRange, generateNumericOtp, generateSlug, getCompanyDetailsFromSettings, getNextAuthOptions, getPermissionableEntityKeys, getPublicSettingsGroup, getRequiredPermission, getRssArticleSummaryFromItem, getStorefrontNextAuthOptions, hasEntityPermission, hashOtpCode, hydrateVendorSessionUser, isAuthDebugClientEnabled, isAuthDebugEnabled, isCustomerTypeContact, isOpenEndpoint, isPlatformAdministrator, isPublicMethod, isRbacDebugEnabled, isSuperAdmin, isSuperAdminGroupName, isVendorAdmin, isVendorGroupName, isVendorOwner, isVendorPortalUser, isVendorStaff, isZipMedia, joinRecipientsForSend, linkUnclaimedContactToUser, llmAgentToChatAgentOptions, llmPlugin, loadPublicThemeSettings, loadUserVendorContext, localStoragePlugin, logAuth, logAuthClient, logEntityAccessDecision, logRbac, mergeEmailLayoutCompanyDetails, mergeGuardrailsIntoSystemPrompt, mergeSeoBySlug, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, nextAuthCookieDebugInfo, normalizePhoneE164, normalizeRefundTiers, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseEmailRecipientsFromConfig, parseHfInferenceEmbeddingBody, parseLlmAgentValidationRules, paymentPlugin, permissionRowsToRecord, pgBossPlugin, pgBossScheduleNameForId, queueEmail, queueErp, queueErpCreateContactIfEnabled, queueErpPaidOrderForOrderId, queueJobScheduleNow, queueOrderPlacedEmails, queuePlugin, queueSms, queueVendorOnboardEmails, queueWhatsApp, rateLimitCheckoutPost, rateLimitKeyForApiRequest, rateLimitPublicApiIfNeeded, registerEmailQueueProcessor, registerErpQueueProcessor, registerJobRunnerWorker, registerSmsQueueProcessor, registerWhatsAppQueueProcessor, relativePathFromMediaParentId, renderEmail, renderLayout, resolveBlogCategoryIdByName, resolveEventOrderTemplate, resolvePublicMetadata, resolveVendorIdForContactCheck, resolveVendorScopeFromSessionUser, s3StoragePlugin, sanitizeMediaFolderPath, sanitizeStorageSegment, seedAdministratorPermissions, seedDefaultAdmin, sendOrderPlacedEmailsAfterConfirmation, sendVendorOnboardEmails, serializeEmailRecipients, sessionHasEntityAccess, shouldRateLimitPublicWrite, simpleDecrypt, simpleEncrypt, smsPlugin, socialMediaPlugin, summarizeEntityPerms, summarizeSessionUserForLog, syncJobScheduleToPgBoss, truncateText, validateRefundTiers, validateScheduleInput, validateSlug, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, vendorPortalFlagsFromUser, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, withAdminRlsContext, withVendorRlsContext };
|