@infuro/cms-core 1.0.53 → 1.0.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  export { emitOrderNotificationTrigger, fireOrderNotificationTrigger } from './chunk-MXIWUFBP.js';
2
- import { checkMultiVendorEnabled, loadUserVendorContext, getPublicSettingsGroup, BlogGeneratorService } from './chunk-UO5Q5RXB.js';
3
- export { Address, Attendee, Attribute, 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, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, LlmAgentKnowledgeDocument, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserDeviceToken, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, VendorUserProfile, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyApprovalStatusSideEffects, applyEventApprovalStatusSideEffects, applyRotatingVendorInvite, applyVendorCustomersContactFilter, applyVendorEventCreateApproval, applyVendorProductCreateApproval, assertCaptchaOk, assertContactAllowedForVendorOrder, assertEventApprovalUpdate, assertProductApprovalUpdate, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildUserInviteLink, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkAndIncrementDiscountUsage, checkEventsEnabled, checkMultiVendorEnabled, completeUserInviteAccept, consumeAppliedDiscountUsages, contactIsVendorCustomer, countDiscountOrdersForContact, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, daysBeforeEventStart, decrementDiscountUsage, describeEventTierPolicy, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findUserByInviteToken, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isMaxPerUserUsageReached, isMaxTotalUsageReached, isZipMedia, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, newUserInviteToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, recordDiscountUsage, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging } from './chunk-UO5Q5RXB.js';
2
+ import { checkMultiVendorEnabled, loadUserVendorContext, getPublicSettingsGroup, BlogGeneratorService } from './chunk-LI3CUI54.js';
3
+ export { Address, Attendee, Attribute, 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, BlogGeneratorService, Brand, CMS_ENTITY_MAP, Cart, CartItem, Category, ChatConversation, ChatMessage, Collection, Combo, ComboItem, Comment, Config, Contact, Currency, CurrencyExchange, Customer, Customer_Contacts, Discount, DiscountRules, Event, EventProduct, Form, FormField, FormSubmission, JobSchedule, JobScheduleRun, KnowledgeBaseChunk, KnowledgeBaseDocument, LlmAgent, LlmAgentKnowledgeDocument, Media, MessageTemplate, Order, OrderAddresses, OrderDiscounts, OrderItem, OrderNotificationBinding, OrderNotificationTrigger, OtpChallenge, Page, PasswordResetToken, Payment, Permission, Product, ProductAttribute, ProductCategory, ProductConfig, ProductVariant, RefundPolicy, RefundRequest, RssArticle, RssFeed, Seo, Tag, Tax, User, UserDeviceToken, UserGroup, Vendor, VendorCustomer, VendorRole, VendorRolePermission, VendorUser, VendorUserProfile, Wishlist, WishlistItem, ZIP_MIME_TYPES, applyApprovalStatusSideEffects, applyEventApprovalStatusSideEffects, applyRotatingVendorInvite, applyVendorCustomersContactFilter, applyVendorEventCreateApproval, applyVendorProductCreateApproval, assertCaptchaOk, assertContactAllowedForVendorOrder, assertEventApprovalUpdate, assertProductApprovalUpdate, buildBlogMetadataUserPrompt, buildCronFromSchedule, buildRssUserPromptFromFeeds, buildUserInviteLink, buildVendorInviteLink, calculateOrderRefundPreview, calculateRefundFromPolicy, checkAndIncrementDiscountUsage, checkEventsEnabled, checkMultiVendorEnabled, completeUserInviteAccept, consumeAppliedDiscountUsages, contactIsVendorCustomer, countDiscountOrdersForContact, countRecentOtpSends, createAnalyticsHandlers, createBlogBySlugHandler, createChangePasswordHandler, createCmsApiHandler, createCmsApp, createCmsAppWithMessaging, createCrudByIdHandler, createCrudHandler, createDashboardStatsHandler, createEcommerceAnalyticsHandler, createEventOrderMessageTemplateHandlers, createForgotPasswordHandler, createFormBySlugHandler, createInviteAcceptHandler, createJobScheduleHandlers, createLlmAgentKnowledgeHandlers, createMediaZipExtractHandler, createMessageTemplateRowLoader, createOtpChallenge, createSetPasswordHandler, createSettingsApiHandlers, createSocialMediaHandlers, createStorefrontApiHandler, createUploadHandler, createUserAuthApiRouter, createUserAvatarHandler, createUserProfileHandler, createUsersApiHandlers, createVendorDashboardHandler, createVendorOnboardHandlers, daysBeforeEventStart, decrementDiscountUsage, describeEventTierPolicy, ensureMessagingPluginsOnCms, ensureScheduleQueueWorker, ensureVendorCustomerForOrderContact, ensureVendorCustomersForOrder, findActiveRefundPolicyForVendor, findUserByInviteToken, findVendorByInviteToken, formatTierRange, generateNumericOtp, getPublicSettingsGroup, getRequireEventApproval, getRequireProductApproval, getRssArticleSummaryFromItem, getVendorCatalogCreateFlags, hashOtpCode, hydrateVendorSessionUser, invalidateEventsCache, invalidateMultiVendorCache, invalidateRequireEventApprovalCache, invalidateRequireProductApprovalCache, invalidateVendorCatalogCreateFlagsCache, isCustomerTypeContact, isMaxPerUserUsageReached, isMaxTotalUsageReached, isZipMedia, llmAgentToChatAgentOptions, loadSettingsGroupFromDb, loadUserVendorContext, mergeGuardrailsIntoSystemPrompt, messagingPlugins, metaFetchUserManagedPages, metaPostPageFeed, metaPostPagePhoto, metaResolvePageAccessToken, newUserInviteToken, normalizePhoneE164, normalizeRefundTiers, overlayCmsPlugins, parseBlogGeneratorAgentContent, parseBlogGeneratorModelOutput, parseBlogMetadataEnrichmentJson, parseLlmAgentValidationRules, pgBossScheduleNameForId, queueErpCreateContactIfEnabled, queueJobScheduleNow, queuePlugin, queueSms, recordDiscountUsage, registerJobRunnerWorker, registerMessagingQueueProcessors, registerSmsQueueProcessor, relativePathFromMediaParentId, resolveBlogCategoryIdByName, resolveSettingsEncryptionKey, resolveVendorIdForContactCheck, sanitizeMediaFolderPath, sanitizeStorageSegment, sendVendorOnboardEmails, simpleDecrypt, simpleEncrypt, syncJobScheduleToPgBoss, validateRefundTiers, validateScheduleInput, validateUserMessageAgainstAgentRules, validateUserMessageAgainstStructuredRules, verifyAndConsumeOtpChallenge, verifyOtpCodeHash, whatsappPlugin, wrapGetCmsWithMessaging } from './chunk-LI3CUI54.js';
4
4
  import { PgBossService } from './chunk-GO7PPYNU.js';
5
5
  export { JOB_RUNNER_QUEUE, PgBossService } from './chunk-GO7PPYNU.js';
6
6
  export { deductInventoryForConfirmedOrder, mergeInventoryLines, orderInventorySnapshotFromRow, orderStatusHoldsStock, reconcileOrderInventoryBetweenSnapshots, restoreInventoryForCancelledOrder, validateInventoryForConfirmedOrderLines, validateInventoryForOrderBecomingConfirmed } from './chunk-3K5AIEIZ.js';
@@ -1046,6 +1046,95 @@ function paymentPlugin(config) {
1046
1046
  __name(paymentPlugin, "paymentPlugin");
1047
1047
 
1048
1048
  // src/plugins/storage/s3.ts
1049
+ var LOG = "[s3]";
1050
+ function serializeS3Error(err) {
1051
+ if (!err || typeof err !== "object") {
1052
+ return {
1053
+ error: String(err)
1054
+ };
1055
+ }
1056
+ const e = err;
1057
+ return {
1058
+ name: e.name,
1059
+ message: e.message,
1060
+ code: e.Code ?? e.code,
1061
+ httpStatus: e.$metadata?.httpStatusCode,
1062
+ requestId: e.$metadata?.requestId,
1063
+ extendedRequestId: e.$metadata?.extendedRequestId,
1064
+ cfId: e.$metadata?.cfId
1065
+ };
1066
+ }
1067
+ __name(serializeS3Error, "serializeS3Error");
1068
+ function publicObjectUrl(config, fullKey) {
1069
+ if (config.baseUrl) {
1070
+ return `${config.baseUrl.replace(/\/$/, "")}/${fullKey}`;
1071
+ }
1072
+ return `https://s3.${config.region}.amazonaws.com/${config.bucket}/${fullKey}`;
1073
+ }
1074
+ __name(publicObjectUrl, "publicObjectUrl");
1075
+ function describeS3Config(config) {
1076
+ const base = config.baseUrl ? new URL(config.baseUrl).host : null;
1077
+ return {
1078
+ bucket: config.bucket,
1079
+ region: config.region,
1080
+ prefix: config.prefix ?? "uploads",
1081
+ hasBaseUrl: Boolean(config.baseUrl),
1082
+ baseUrlHost: base,
1083
+ accessKeyIdLast4: config.accessKeyId.slice(-4),
1084
+ envSummary: {
1085
+ AWS_BUCKET_NAME: Boolean(config.bucket),
1086
+ AWS_REGION: Boolean(config.region),
1087
+ AWS_ACCESS_KEY_ID: Boolean(config.accessKeyId),
1088
+ AWS_SECRET_ACCESS_KEY: Boolean(config.secretAccessKey),
1089
+ S3_MEDIA_URL: Boolean(config.baseUrl)
1090
+ }
1091
+ };
1092
+ }
1093
+ __name(describeS3Config, "describeS3Config");
1094
+ async function probePublicUrl(url) {
1095
+ try {
1096
+ const head = await fetch(url, {
1097
+ method: "HEAD",
1098
+ redirect: "manual"
1099
+ });
1100
+ const headInfo = {
1101
+ url,
1102
+ status: head.status,
1103
+ ok: head.ok,
1104
+ contentType: head.headers.get("content-type"),
1105
+ location: head.headers.get("location")
1106
+ };
1107
+ if (head.ok) {
1108
+ console.info(LOG, "public URL reachable (HEAD)", headInfo);
1109
+ return;
1110
+ }
1111
+ const getRes = await fetch(url, {
1112
+ method: "GET",
1113
+ headers: {
1114
+ Range: "bytes=0-0"
1115
+ },
1116
+ redirect: "manual"
1117
+ });
1118
+ let bodySnippet = "";
1119
+ try {
1120
+ bodySnippet = (await getRes.text()).slice(0, 400);
1121
+ } catch {
1122
+ }
1123
+ console.error(LOG, "public URL not readable \u2014 admin images will not display", {
1124
+ ...headInfo,
1125
+ getStatus: getRes.status,
1126
+ getOk: getRes.ok,
1127
+ getContentType: getRes.headers.get("content-type"),
1128
+ bodySnippet
1129
+ });
1130
+ } catch (err) {
1131
+ console.error(LOG, "public URL probe failed", {
1132
+ url,
1133
+ error: err instanceof Error ? err.message : String(err)
1134
+ });
1135
+ }
1136
+ }
1137
+ __name(probePublicUrl, "probePublicUrl");
1049
1138
  function getS3Storage(config) {
1050
1139
  const prefix = (config.prefix ?? "uploads").replace(/\/$/, "");
1051
1140
  const keyPrefix = prefix ? `${prefix}/` : "";
@@ -1059,17 +1148,51 @@ function getS3Storage(config) {
1059
1148
  secretAccessKey: config.secretAccessKey
1060
1149
  }
1061
1150
  });
1062
- const fullKey = keyPrefix + key.replace(/^\/+/, "");
1063
- await client.send(new PutObjectCommand({
1064
- Bucket: config.bucket,
1065
- Key: fullKey,
1066
- Body: buffer,
1067
- ContentType: contentType
1068
- }));
1069
- if (config.baseUrl) {
1070
- return `${config.baseUrl.replace(/\/$/, "")}/${fullKey}`;
1151
+ const rawKey = key.replace(/^\/+/, "");
1152
+ const fullKey = keyPrefix + rawKey;
1153
+ const publicUrl = publicObjectUrl(config, fullKey);
1154
+ const started = Date.now();
1155
+ console.info(LOG, "upload start", {
1156
+ ...describeS3Config(config),
1157
+ key: rawKey,
1158
+ fullKey,
1159
+ publicUrl,
1160
+ contentType,
1161
+ bytes: buffer.length
1162
+ });
1163
+ try {
1164
+ await client.send(new PutObjectCommand({
1165
+ Bucket: config.bucket,
1166
+ Key: fullKey,
1167
+ Body: buffer,
1168
+ ContentType: contentType
1169
+ }));
1170
+ } catch (err) {
1171
+ const errorDump = serializeS3Error(err);
1172
+ console.error(LOG, "PutObject failed", {
1173
+ ...describeS3Config(config),
1174
+ key: rawKey,
1175
+ fullKey,
1176
+ publicUrl,
1177
+ contentType,
1178
+ bytes: buffer.length,
1179
+ ...errorDump,
1180
+ rawError: err instanceof Error ? err.message : String(err)
1181
+ });
1182
+ throw err;
1071
1183
  }
1072
- return `https://s3.${config.region}.amazonaws.com/${config.bucket}/${fullKey}`;
1184
+ console.info(LOG, "PutObject ok", {
1185
+ ...describeS3Config(config),
1186
+ key: rawKey,
1187
+ fullKey,
1188
+ publicUrl,
1189
+ contentType,
1190
+ bytes: buffer.length,
1191
+ ms: Date.now() - started,
1192
+ hasCustomBaseUrl: Boolean(config.baseUrl)
1193
+ });
1194
+ void probePublicUrl(publicUrl);
1195
+ return publicUrl;
1073
1196
  }
1074
1197
  };
1075
1198
  }
@@ -1086,8 +1209,36 @@ function s3StoragePlugin(config) {
1086
1209
  const baseUrl = config.baseUrl ?? context.config.S3_MEDIA_URL ?? context.config.S3_CUSTOM_DOMAIN;
1087
1210
  const resolvedBaseUrl = typeof baseUrl === "string" && baseUrl ? baseUrl.startsWith("http") ? baseUrl : `https://${baseUrl}` : void 0;
1088
1211
  if (!region || !accessKeyId || !secretAccessKey || !bucket) {
1212
+ console.error(LOG, "plugin init missing config", {
1213
+ hasRegion: Boolean(region),
1214
+ hasAccessKeyId: Boolean(accessKeyId),
1215
+ hasSecretAccessKey: Boolean(secretAccessKey),
1216
+ hasBucket: Boolean(bucket),
1217
+ hasBaseUrl: Boolean(resolvedBaseUrl)
1218
+ });
1089
1219
  throw new Error("S3 storage plugin: missing region, accessKeyId, secretAccessKey or bucket");
1090
1220
  }
1221
+ let baseUrlHost = null;
1222
+ try {
1223
+ baseUrlHost = resolvedBaseUrl ? new URL(resolvedBaseUrl).host : null;
1224
+ } catch {
1225
+ baseUrlHost = resolvedBaseUrl ?? null;
1226
+ }
1227
+ console.info(LOG, "plugin ready", {
1228
+ region,
1229
+ bucket,
1230
+ prefix: config.prefix ?? "uploads",
1231
+ hasBaseUrl: Boolean(resolvedBaseUrl),
1232
+ baseUrlHost,
1233
+ accessKeyIdLast4: accessKeyId.slice(-4),
1234
+ envSummary: {
1235
+ AWS_BUCKET_NAME: Boolean(bucket),
1236
+ AWS_REGION: Boolean(region),
1237
+ AWS_ACCESS_KEY_ID: Boolean(accessKeyId),
1238
+ AWS_SECRET_ACCESS_KEY: Boolean(secretAccessKey),
1239
+ S3_MEDIA_URL: Boolean(resolvedBaseUrl)
1240
+ }
1241
+ });
1091
1242
  return getS3Storage({
1092
1243
  region,
1093
1244
  accessKeyId,
@@ -1121,7 +1272,14 @@ function getLocalStorage(config) {
1121
1272
  recursive: true
1122
1273
  });
1123
1274
  await fs.writeFile(filePath, buffer);
1124
- return `${publicPath.replace(/\/$/, "")}/${fileName}`;
1275
+ const url = `${publicPath.replace(/\/$/, "")}/${fileName}`;
1276
+ console.info("[storage:local] wrote file", {
1277
+ dir: fullDir,
1278
+ key: fileName,
1279
+ bytes: buffer.length,
1280
+ url
1281
+ });
1282
+ return url;
1125
1283
  }
1126
1284
  };
1127
1285
  }
@@ -1132,6 +1290,9 @@ function localStoragePlugin(config = {}) {
1132
1290
  version: "1.0.0",
1133
1291
  async init(context) {
1134
1292
  const dir = config.dir ?? context.config.UPLOAD_DIR ?? "public/uploads";
1293
+ console.info("[storage:local] plugin ready", {
1294
+ dir
1295
+ });
1135
1296
  return getLocalStorage({
1136
1297
  ...config,
1137
1298
  dir
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@infuro/cms-core",
3
- "version": "1.0.53",
3
+ "version": "1.0.55",
4
4
  "private": false,
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",