@geekron/hono 0.0.10 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (180) hide show
  1. package/dist/contract.d.ts +9 -1
  2. package/dist/contract.d.ts.map +1 -1
  3. package/dist/contract.js +14 -3
  4. package/dist/core/api/common.d.ts +2 -0
  5. package/dist/core/api/common.d.ts.map +1 -0
  6. package/dist/core/api/common.js +38 -0
  7. package/dist/core/api/inquiries.d.ts +2 -0
  8. package/dist/core/api/inquiries.d.ts.map +1 -0
  9. package/dist/core/api/inquiries.js +116 -0
  10. package/dist/core/api/inquiry.d.ts +2 -0
  11. package/dist/core/api/inquiry.d.ts.map +1 -0
  12. package/dist/core/api/inquiry.js +33 -0
  13. package/dist/core/api/visitor.d.ts +2 -0
  14. package/dist/core/api/visitor.d.ts.map +1 -0
  15. package/dist/core/api/visitor.js +152 -0
  16. package/dist/core/components/InquiryEmailTemplate.d.ts +30 -0
  17. package/dist/core/components/InquiryEmailTemplate.d.ts.map +1 -0
  18. package/dist/core/components/InquiryEmailTemplate.js +13 -0
  19. package/dist/core/components/Seo.d.ts +97 -0
  20. package/dist/core/components/Seo.d.ts.map +1 -0
  21. package/dist/core/components/Seo.js +365 -0
  22. package/dist/core/components/index.d.ts +3 -0
  23. package/dist/core/components/index.d.ts.map +1 -0
  24. package/dist/core/components/index.js +2 -0
  25. package/dist/core/index.d.ts +4 -0
  26. package/dist/core/index.d.ts.map +1 -0
  27. package/dist/core/index.js +3 -0
  28. package/dist/core/lib/constants/inquiry.d.ts +52 -0
  29. package/dist/core/lib/constants/inquiry.d.ts.map +1 -0
  30. package/dist/core/lib/constants/inquiry.js +51 -0
  31. package/dist/core/lib/constants/visitor.d.ts +29 -0
  32. package/dist/core/lib/constants/visitor.d.ts.map +1 -0
  33. package/dist/core/lib/constants/visitor.js +28 -0
  34. package/dist/core/lib/database/constants/database.d.ts +15 -0
  35. package/dist/core/lib/database/constants/database.d.ts.map +1 -0
  36. package/dist/core/lib/database/constants/database.js +14 -0
  37. package/dist/core/lib/database/database.service.d.ts +63 -0
  38. package/dist/core/lib/database/database.service.d.ts.map +1 -0
  39. package/dist/core/lib/database/database.service.js +108 -0
  40. package/dist/core/lib/database/index.d.ts +8 -0
  41. package/dist/core/lib/database/index.d.ts.map +1 -0
  42. package/dist/core/lib/database/index.js +7 -0
  43. package/dist/core/lib/database/managers/sqlite.d.ts +29 -0
  44. package/dist/core/lib/database/managers/sqlite.d.ts.map +1 -0
  45. package/dist/core/lib/database/managers/sqlite.js +55 -0
  46. package/dist/core/lib/database/managers/visitor-shard.d.ts +29 -0
  47. package/dist/core/lib/database/managers/visitor-shard.d.ts.map +1 -0
  48. package/dist/core/lib/database/managers/visitor-shard.js +83 -0
  49. package/dist/core/lib/database/repositories/inquiry.repository.d.ts +33 -0
  50. package/dist/core/lib/database/repositories/inquiry.repository.d.ts.map +1 -0
  51. package/dist/core/lib/database/repositories/inquiry.repository.js +173 -0
  52. package/dist/core/lib/database/repositories/visitor.repository.d.ts +51 -0
  53. package/dist/core/lib/database/repositories/visitor.repository.d.ts.map +1 -0
  54. package/dist/core/lib/database/repositories/visitor.repository.js +559 -0
  55. package/dist/core/lib/database/schemas/inquiry.schema.d.ts +323 -0
  56. package/dist/core/lib/database/schemas/inquiry.schema.d.ts.map +1 -0
  57. package/dist/core/lib/database/schemas/inquiry.schema.js +52 -0
  58. package/dist/core/lib/database/schemas/visitor.schema.d.ts +623 -0
  59. package/dist/core/lib/database/schemas/visitor.schema.d.ts.map +1 -0
  60. package/dist/core/lib/database/schemas/visitor.schema.js +162 -0
  61. package/dist/core/lib/services/captcha.service.d.ts +13 -0
  62. package/dist/core/lib/services/captcha.service.d.ts.map +1 -0
  63. package/dist/core/lib/services/captcha.service.js +40 -0
  64. package/dist/core/lib/services/geoip.service.d.ts +79 -0
  65. package/dist/core/lib/services/geoip.service.d.ts.map +1 -0
  66. package/dist/core/lib/services/geoip.service.js +144 -0
  67. package/dist/core/lib/services/index.d.ts +9 -0
  68. package/dist/core/lib/services/index.d.ts.map +1 -0
  69. package/dist/core/lib/services/index.js +8 -0
  70. package/dist/core/lib/services/inquiry.service.d.ts +56 -0
  71. package/dist/core/lib/services/inquiry.service.d.ts.map +1 -0
  72. package/dist/core/lib/services/inquiry.service.js +129 -0
  73. package/dist/core/lib/services/mailer.service.d.ts +23 -0
  74. package/dist/core/lib/services/mailer.service.d.ts.map +1 -0
  75. package/dist/core/lib/services/mailer.service.js +96 -0
  76. package/dist/core/lib/types/inquiry.d.ts +95 -0
  77. package/dist/core/lib/types/inquiry.d.ts.map +1 -0
  78. package/dist/core/lib/types/inquiry.js +1 -0
  79. package/dist/core/lib/types/visitor.d.ts +135 -0
  80. package/dist/core/lib/types/visitor.d.ts.map +1 -0
  81. package/dist/core/lib/types/visitor.js +1 -0
  82. package/dist/core/lib/utils/api.d.ts +25 -0
  83. package/dist/core/lib/utils/api.d.ts.map +1 -0
  84. package/dist/core/lib/utils/api.js +48 -0
  85. package/dist/core/lib/utils/request.d.ts +18 -0
  86. package/dist/core/lib/utils/request.d.ts.map +1 -0
  87. package/dist/core/lib/utils/request.js +25 -0
  88. package/dist/core/middlewares/api-guard.d.ts +39 -0
  89. package/dist/core/middlewares/api-guard.d.ts.map +1 -0
  90. package/dist/core/middlewares/api-guard.js +154 -0
  91. package/dist/core/middlewares/html-minifier.d.ts +55 -0
  92. package/dist/core/middlewares/html-minifier.d.ts.map +1 -0
  93. package/dist/core/middlewares/html-minifier.js +140 -0
  94. package/dist/core/middlewares/index.d.ts +5 -0
  95. package/dist/core/middlewares/index.d.ts.map +1 -0
  96. package/dist/core/middlewares/index.js +4 -0
  97. package/dist/core/middlewares/initializer.d.ts +11 -0
  98. package/dist/core/middlewares/initializer.d.ts.map +1 -0
  99. package/dist/core/middlewares/initializer.js +13 -0
  100. package/dist/core/middlewares/visitor-tracker.d.ts +85 -0
  101. package/dist/core/middlewares/visitor-tracker.d.ts.map +1 -0
  102. package/dist/core/middlewares/visitor-tracker.js +253 -0
  103. package/dist/core/template.d.ts +4 -0
  104. package/dist/core/template.d.ts.map +1 -0
  105. package/dist/core/template.js +7 -0
  106. package/dist/core/utils/formatDate.d.ts +3 -0
  107. package/dist/core/utils/formatDate.d.ts.map +1 -0
  108. package/dist/core/utils/formatDate.js +2 -0
  109. package/dist/core/utils/fullUrl.d.ts +2 -0
  110. package/dist/core/utils/fullUrl.d.ts.map +1 -0
  111. package/dist/core/utils/fullUrl.js +9 -0
  112. package/dist/core/utils/index.d.ts +6 -0
  113. package/dist/core/utils/index.d.ts.map +1 -0
  114. package/dist/core/utils/index.js +5 -0
  115. package/dist/core/utils/markdownify.d.ts +2 -0
  116. package/dist/core/utils/markdownify.d.ts.map +1 -0
  117. package/dist/core/utils/markdownify.js +4 -0
  118. package/dist/core/utils/params.d.ts +5 -0
  119. package/dist/core/utils/params.d.ts.map +1 -0
  120. package/dist/core/utils/params.js +14 -0
  121. package/dist/core/utils/routeUrl.d.ts +20 -0
  122. package/dist/core/utils/routeUrl.d.ts.map +1 -0
  123. package/dist/core/utils/routeUrl.js +111 -0
  124. package/dist/route/methods.d.ts +15 -0
  125. package/dist/route/methods.d.ts.map +1 -1
  126. package/dist/route/methods.js +45 -18
  127. package/dist/route/setup.d.ts +11 -12
  128. package/dist/route/setup.d.ts.map +1 -1
  129. package/dist/route/setup.js +26 -16
  130. package/dist/strapi/api/site.d.ts +2 -0
  131. package/dist/strapi/api/site.d.ts.map +1 -0
  132. package/dist/strapi/api/site.js +153 -0
  133. package/dist/strapi/cms/cms.js +1 -1
  134. package/dist/strapi/cms/common.d.ts.map +1 -1
  135. package/dist/strapi/cms/common.js +3 -1
  136. package/dist/strapi/cms/menu.d.ts +0 -9
  137. package/dist/strapi/cms/menu.d.ts.map +1 -1
  138. package/dist/strapi/cms/menu.js +3 -62
  139. package/dist/strapi/cms/setup.d.ts +2 -1
  140. package/dist/strapi/cms/setup.d.ts.map +1 -1
  141. package/dist/strapi/cms/setup.js +5 -0
  142. package/dist/strapi/cms/site.d.ts.map +1 -1
  143. package/dist/strapi/cms/site.js +3 -1
  144. package/dist/strapi/cms/translations.d.ts.map +1 -1
  145. package/dist/strapi/cms/translations.js +6 -2
  146. package/dist/strapi/i18n.d.ts +3 -0
  147. package/dist/strapi/i18n.d.ts.map +1 -0
  148. package/dist/strapi/i18n.js +27 -0
  149. package/dist/strapi/index.d.ts +1 -0
  150. package/dist/strapi/index.d.ts.map +1 -1
  151. package/dist/strapi/index.js +1 -0
  152. package/dist/strapi/interfaces/index.d.ts +1 -0
  153. package/dist/strapi/interfaces/index.d.ts.map +1 -1
  154. package/dist/strapi/interfaces/index.js +1 -0
  155. package/dist/strapi/interfaces/sitemap.d.ts +19 -0
  156. package/dist/strapi/interfaces/sitemap.d.ts.map +1 -0
  157. package/dist/strapi/interfaces/sitemap.js +1 -0
  158. package/dist/strapi/pages/sitemap/index.d.ts +2 -0
  159. package/dist/strapi/pages/sitemap/index.d.ts.map +1 -0
  160. package/dist/strapi/pages/sitemap/index.js +50 -0
  161. package/dist/strapi/pages/sitemap/index.xml +11 -0
  162. package/dist/strapi/pages/sitemap/list.d.ts +2 -0
  163. package/dist/strapi/pages/sitemap/list.d.ts.map +1 -0
  164. package/dist/strapi/pages/sitemap/list.js +123 -0
  165. package/dist/strapi/pages/sitemap/list.xml +28 -0
  166. package/dist/strapi/pages/sitemap/robots.d.ts +2 -0
  167. package/dist/strapi/pages/sitemap/robots.d.ts.map +1 -0
  168. package/dist/strapi/pages/sitemap/robots.js +19 -0
  169. package/dist/strapi/pages/sitemap/robots.txt +7 -0
  170. package/dist/strapi/pages/sitemap/style.d.ts +2 -0
  171. package/dist/strapi/pages/sitemap/style.d.ts.map +1 -0
  172. package/dist/strapi/pages/sitemap/style.js +17 -0
  173. package/dist/strapi/pages/sitemap/style.xsl +602 -0
  174. package/dist/strapi/utils/index.d.ts +1 -0
  175. package/dist/strapi/utils/index.d.ts.map +1 -1
  176. package/dist/strapi/utils/index.js +1 -0
  177. package/dist/strapi/utils/trans.d.ts +5 -0
  178. package/dist/strapi/utils/trans.d.ts.map +1 -0
  179. package/dist/strapi/utils/trans.js +7 -0
  180. package/package.json +20 -2
@@ -0,0 +1,365 @@
1
+ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "hono/jsx/jsx-runtime";
2
+ import { fullUrl } from '../../core/utils';
3
+ export const Seo = (props) => {
4
+ const baseUrl = props.site.url;
5
+ // 处理关键词
6
+ const processedKeywords = props.keywords
7
+ ? Array.isArray(props.keywords)
8
+ ? props.keywords.filter(Boolean).join(', ')
9
+ : props.keywords
10
+ : '';
11
+ // 动态决定OG类型和Twitter Card类型
12
+ const ogType = props.type === 'article'
13
+ ? 'article'
14
+ : props.type === 'product'
15
+ ? 'product'
16
+ : props.type === 'organization' || props.type === 'local-business'
17
+ ? 'website'
18
+ : 'website';
19
+ const twitterCardType = props.image?.src && props.image.width > 300
20
+ ? 'summary_large_image'
21
+ : 'summary';
22
+ // 构建核心结构化数据
23
+ const createMainEntity = () => {
24
+ switch (props.type) {
25
+ case 'article':
26
+ return {
27
+ '@context': 'https://schema.org',
28
+ '@type': 'Article',
29
+ headline: props.article?.headline || props.title,
30
+ description: props.description,
31
+ image: props.image.src,
32
+ datePublished: props.published?.toISOString(),
33
+ dateModified: props.modified?.toISOString(),
34
+ author: props.author
35
+ ? {
36
+ '@type': 'Person',
37
+ name: props.author.name,
38
+ url: fullUrl(baseUrl, props.author.url),
39
+ email: props.author.email,
40
+ }
41
+ : undefined,
42
+ publisher: {
43
+ '@type': 'Organization',
44
+ name: props.site.name,
45
+ logo: {
46
+ '@type': 'ImageObject',
47
+ url: props.site.logo,
48
+ },
49
+ },
50
+ mainEntityOfPage: {
51
+ '@type': 'WebPage',
52
+ '@id': props.url,
53
+ },
54
+ articleSection: props.article?.section,
55
+ articleBody: props.description, // 在实际应用中应使用完整文章内容
56
+ wordCount: props.article?.wordCount,
57
+ about: props.article?.tag,
58
+ };
59
+ case 'product':
60
+ return {
61
+ '@context': 'https://schema.org',
62
+ '@type': 'Product',
63
+ name: props.title,
64
+ description: props.description,
65
+ image: props.image.src,
66
+ offers: {
67
+ '@type': 'Offer',
68
+ price: props.product?.price,
69
+ priceCurrency: props.product?.priceCurrency,
70
+ availability: `https://schema.org/${props.product?.availability || 'InStock'}`,
71
+ url: props.url,
72
+ },
73
+ brand: props.product?.brand
74
+ ? {
75
+ '@type': 'Brand',
76
+ name: props.product.brand,
77
+ }
78
+ : undefined,
79
+ category: props.product?.category,
80
+ review: props.product?.reviews?.map((review) => ({
81
+ '@type': 'Review',
82
+ author: {
83
+ '@type': 'Person',
84
+ name: review.author,
85
+ },
86
+ reviewRating: {
87
+ '@type': 'Rating',
88
+ ratingValue: review.ratingValue,
89
+ },
90
+ reviewBody: review.reviewBody,
91
+ datePublished: review.datePublished?.toISOString(),
92
+ })) || undefined,
93
+ mainEntityOfPage: {
94
+ '@type': 'WebPage',
95
+ '@id': props.url,
96
+ },
97
+ };
98
+ case 'local-business':
99
+ return {
100
+ '@context': 'https://schema.org',
101
+ '@type': 'LocalBusiness',
102
+ name: props.localBusiness?.name || props.title,
103
+ description: props.description,
104
+ image: props.image.src,
105
+ url: props.url,
106
+ telephone: props.localBusiness?.telephone,
107
+ address: {
108
+ '@type': 'PostalAddress',
109
+ streetAddress: props.localBusiness?.address.streetAddress,
110
+ addressLocality: props.localBusiness?.address.addressLocality,
111
+ addressRegion: props.localBusiness?.address.addressRegion,
112
+ postalCode: props.localBusiness?.address.postalCode,
113
+ addressCountry: props.localBusiness?.address.addressCountry,
114
+ },
115
+ geo: props.localBusiness?.geo
116
+ ? {
117
+ '@type': 'GeoCoordinates',
118
+ latitude: props.localBusiness.geo.latitude,
119
+ longitude: props.localBusiness.geo.longitude,
120
+ }
121
+ : undefined,
122
+ openingHoursSpecification: props.localBusiness?.openingHours?.map((hours) => ({
123
+ '@type': 'OpeningHoursSpecification',
124
+ dayOfWeek: hours.dayOfWeek,
125
+ opens: hours.hours.split('-')[0],
126
+ closes: hours.hours.split('-')[1],
127
+ })) || undefined,
128
+ mainEntityOfPage: {
129
+ '@type': 'WebPage',
130
+ '@id': props.url,
131
+ },
132
+ };
133
+ case 'organization':
134
+ return {
135
+ '@context': 'https://schema.org',
136
+ '@type': 'Organization',
137
+ name: props.title,
138
+ description: props.description,
139
+ image: props.image.src,
140
+ url: props.url,
141
+ logo: props.site.logo,
142
+ foundingDate: props.organization?.foundingDate?.toISOString(),
143
+ memberOf: props.organization?.memberOf
144
+ ? {
145
+ '@type': 'Organization',
146
+ name: props.organization.memberOf,
147
+ }
148
+ : undefined,
149
+ numberOfEmployees: props.organization?.numberOfEmployees
150
+ ? {
151
+ '@type': 'QuantitativeValue',
152
+ value: props.organization.numberOfEmployees,
153
+ }
154
+ : undefined,
155
+ mainEntityOfPage: {
156
+ '@type': 'WebPage',
157
+ '@id': props.url,
158
+ },
159
+ };
160
+ default: // website
161
+ return {
162
+ '@context': 'https://schema.org',
163
+ '@type': 'WebPage',
164
+ name: props.title,
165
+ description: props.description,
166
+ url: props.url,
167
+ image: props.image.src,
168
+ dateModified: props.modified?.toISOString(),
169
+ publisher: {
170
+ '@type': 'Organization',
171
+ name: props.site.name,
172
+ logo: {
173
+ '@type': 'ImageObject',
174
+ url: props.site.logo,
175
+ },
176
+ },
177
+ mainEntityOfPage: {
178
+ '@type': 'WebPage',
179
+ '@id': props.url,
180
+ },
181
+ };
182
+ }
183
+ };
184
+ const baseTags = [
185
+ { name: 'viewport', content: 'width=device-width, initial-scale=1' },
186
+ { name: 'description', content: props.description },
187
+ { name: 'keywords', content: processedKeywords },
188
+ { name: 'generator', content: 'Geekron' },
189
+ ];
190
+ if (props.indexing) {
191
+ baseTags.push({ name: 'robots', content: 'index, follow' });
192
+ }
193
+ else {
194
+ baseTags.push({ name: 'robots', content: 'noindex, follow' });
195
+ }
196
+ // 添加文章特定标签
197
+ if (props.type === 'article') {
198
+ if (props.published) {
199
+ baseTags.push({
200
+ name: 'article:published_time',
201
+ content: props.published.toISOString(),
202
+ });
203
+ }
204
+ if (props.modified) {
205
+ baseTags.push({
206
+ name: 'article:modified_time',
207
+ content: props.modified.toISOString(),
208
+ });
209
+ }
210
+ if (props.author) {
211
+ baseTags.push({ name: 'article:author', content: props.author.name });
212
+ if (props.author.url) {
213
+ baseTags.push({
214
+ name: 'article:author',
215
+ content: fullUrl(baseUrl, props.author.url),
216
+ });
217
+ }
218
+ }
219
+ if (props.article?.section) {
220
+ baseTags.push({
221
+ name: 'article:section',
222
+ content: props.article.section,
223
+ });
224
+ }
225
+ if (props.article?.tag && Array.isArray(props.article.tag)) {
226
+ props.article.tag.forEach((tag) => {
227
+ baseTags.push({
228
+ name: 'article:tag',
229
+ content: tag,
230
+ });
231
+ });
232
+ }
233
+ }
234
+ // 添加产品特定标签
235
+ if (props.type === 'product') {
236
+ if (props.product?.price) {
237
+ baseTags.push({
238
+ name: 'product:price:amount',
239
+ content: String(props.product.price),
240
+ });
241
+ }
242
+ if (props.product?.priceCurrency) {
243
+ baseTags.push({
244
+ name: 'product:price:currency',
245
+ content: props.product.priceCurrency,
246
+ });
247
+ }
248
+ }
249
+ const ogTags = [
250
+ { property: 'og:url', content: props.url },
251
+ { property: 'og:type', content: ogType },
252
+ { property: 'og:title', content: props.title },
253
+ { property: 'og:description', content: props.description },
254
+ { property: 'og:image', content: props.image.src },
255
+ { property: 'og:image:alt', content: props.image.alt || props.title },
256
+ { property: 'og:image:width', content: String(props.image.width) },
257
+ { property: 'og:image:height', content: String(props.image.height) },
258
+ { property: 'og:locale', content: props.site.locale },
259
+ { property: 'og:site_name', content: props.site.name },
260
+ ];
261
+ // 添加产品特定OG标签
262
+ if (props.type === 'product') {
263
+ ogTags.push({
264
+ property: 'product:price:amount',
265
+ content: String(props.product?.price || ''),
266
+ }, {
267
+ property: 'product:price:currency',
268
+ content: props.product?.priceCurrency || '',
269
+ }, {
270
+ property: 'product:availability',
271
+ content: props.product?.availability || 'in_stock',
272
+ });
273
+ }
274
+ const twitterTags = [
275
+ { name: 'twitter:card', content: props.twitter?.card || twitterCardType },
276
+ {
277
+ name: 'twitter:site',
278
+ content: props.twitter?.site || `@${props.site.name.replace(/\s+/g, '')}`,
279
+ },
280
+ {
281
+ name: 'twitter:creator',
282
+ content: props.twitter?.creator ||
283
+ (props.author?.name ? `@${props.author.name.replace(/\s+/g, '')}` : ''),
284
+ },
285
+ { name: 'twitter:title', content: props.title },
286
+ { name: 'twitter:description', content: props.description },
287
+ { name: 'twitter:image', content: props.image.src },
288
+ { name: 'twitter:image:alt', content: props.image.alt || props.title },
289
+ ];
290
+ const metaTags = [...baseTags, ...ogTags, ...twitterTags]
291
+ .map((meta) => props.metaHandler?.(meta) || meta)
292
+ .filter(Boolean);
293
+ // 构建结构化数据数组
294
+ const structuredData = [
295
+ createMainEntity(),
296
+ {
297
+ '@context': 'https://schema.org',
298
+ '@type': 'BreadcrumbList',
299
+ itemListElement: props.breadcrumbs.map((item, index) => ({
300
+ '@type': 'ListItem',
301
+ position: index + 1,
302
+ name: item.title,
303
+ item: fullUrl(baseUrl, item.url),
304
+ })),
305
+ },
306
+ // 添加网站组织信息
307
+ {
308
+ '@context': 'https://schema.org',
309
+ '@type': 'Organization',
310
+ name: props.site.name,
311
+ url: props.site.url,
312
+ logo: props.site.logo,
313
+ contactPoint: props.site.contactPoint
314
+ ? {
315
+ '@type': 'ContactPoint',
316
+ telephone: props.site.contactPoint.telephone,
317
+ contactType: props.site.contactPoint.contactType,
318
+ areaServed: props.site.contactPoint.areaServed,
319
+ availableLanguage: props.site.contactPoint.availableLanguage,
320
+ }
321
+ : undefined,
322
+ },
323
+ ].filter((item) => item !== null);
324
+ // 构建网站图标链接标签
325
+ const iconLinks = [
326
+ // 基本favicon
327
+ { rel: 'icon', type: 'image/x-icon', href: props.site.icon },
328
+ // 不同尺寸的favicon
329
+ { rel: 'icon', type: 'image/png', sizes: '32x32', href: props.site.icon },
330
+ { rel: 'icon', type: 'image/png', sizes: '16x16', href: props.site.icon },
331
+ // Apple触控图标
332
+ props.site.appleTouchIcon && {
333
+ rel: 'apple-touch-icon',
334
+ sizes: '180x180',
335
+ href: props.site.appleTouchIcon,
336
+ },
337
+ // Android Chrome图标
338
+ { rel: 'icon', type: 'image/png', sizes: '192x192', href: props.site.icon },
339
+ { rel: 'icon', type: 'image/png', sizes: '512x512', href: props.site.icon },
340
+ // Web App Manifest
341
+ props.site.manifest && {
342
+ rel: 'manifest',
343
+ href: props.site.manifest,
344
+ },
345
+ // Safari固定标签页图标
346
+ props.site.safariPinnedTab && {
347
+ rel: 'mask-icon',
348
+ href: props.site.safariPinnedTab,
349
+ color: props.site.msApplicationTileColor || '#5bbad5',
350
+ },
351
+ // MS Application
352
+ props.site.msApplicationTileImage && {
353
+ name: 'msapplication-TileImage',
354
+ content: props.site.msApplicationTileImage,
355
+ },
356
+ // 主题色
357
+ props.site.themeColor && {
358
+ name: 'theme-color',
359
+ content: props.site.themeColor,
360
+ },
361
+ ].filter(Boolean);
362
+ return (_jsxs(_Fragment, { children: [_jsx("title", { children: props.title }), _jsx("link", { rel: "canonical", href: props.url }), iconLinks.map((link, index) => (_jsx("link", { ...link }, `icon-${index}`))), metaTags.map((tag, index) => (_jsx("meta", { ...tag }, index))), _jsx("script", { type: "application/ld+json", dangerouslySetInnerHTML: {
363
+ __html: JSON.stringify(structuredData).replace(/undefined/g, 'null'),
364
+ } })] }));
365
+ };
@@ -0,0 +1,3 @@
1
+ export * from './InquiryEmailTemplate';
2
+ export * from './Seo';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/core/components/index.tsx"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAA;AACtC,cAAc,OAAO,CAAA"}
@@ -0,0 +1,2 @@
1
+ export * from './InquiryEmailTemplate';
2
+ export * from './Seo';
@@ -0,0 +1,4 @@
1
+ export * from './middlewares';
2
+ export * from './template';
3
+ export * from './utils';
4
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/core/index.ts"],"names":[],"mappings":"AAAA,cAAc,eAAe,CAAA;AAC7B,cAAc,YAAY,CAAA;AAC1B,cAAc,SAAS,CAAA"}
@@ -0,0 +1,3 @@
1
+ export * from './middlewares';
2
+ export * from './template';
3
+ export * from './utils';
@@ -0,0 +1,52 @@
1
+ /**
2
+ * 默认分页配置
3
+ */
4
+ export declare const PAGINATION_DEFAULTS: {
5
+ /** 默认页码 */
6
+ readonly PAGE: 1;
7
+ /** 默认每页条数 */
8
+ readonly PAGE_SIZE: 20;
9
+ /** 最大每页条数 */
10
+ readonly MAX_PAGE_SIZE: 100;
11
+ };
12
+ /**
13
+ * 默认排序配置
14
+ */
15
+ export declare const SORT_DEFAULTS: {
16
+ /** 默认排序字段 */
17
+ readonly SORT_BY: "createdAt";
18
+ /** 默认排序方向 */
19
+ readonly ORDER: "desc";
20
+ };
21
+ /**
22
+ * 缓存配置
23
+ */
24
+ export declare const CACHE_CONFIG: {
25
+ /** 列表缓存 key 前缀 */
26
+ readonly LIST_PREFIX: "inquiries:list";
27
+ /** 详情缓存 key 前缀 */
28
+ readonly DETAIL_PREFIX: "inquiries:detail";
29
+ };
30
+ /**
31
+ * 错误码定义
32
+ */
33
+ export declare const ERROR_CODES: {
34
+ /** 无效的 ID */
35
+ readonly INVALID_ID: 10001;
36
+ /** 记录不存在 */
37
+ readonly NOT_FOUND: 10002;
38
+ /** 无效的参数 */
39
+ readonly INVALID_PARAMS: 10003;
40
+ /** 服务器内部错误 */
41
+ readonly INTERNAL_ERROR: 10000;
42
+ };
43
+ /**
44
+ * HTTP 状态码
45
+ */
46
+ export declare const HTTP_STATUS: {
47
+ readonly OK: 200;
48
+ readonly BAD_REQUEST: 400;
49
+ readonly NOT_FOUND: 404;
50
+ readonly INTERNAL_ERROR: 500;
51
+ };
52
+ //# sourceMappingURL=inquiry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inquiry.d.ts","sourceRoot":"","sources":["../../../../src/core/lib/constants/inquiry.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,mBAAmB;IAC/B,WAAW;;IAEX,aAAa;;IAEb,aAAa;;CAEJ,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,aAAa;IACzB,aAAa;;IAEb,aAAa;;CAEJ,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,YAAY;IACxB,kBAAkB;;IAElB,kBAAkB;;CAET,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,WAAW;IACvB,aAAa;;IAEb,YAAY;;IAEZ,YAAY;;IAEZ,cAAc;;CAEL,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,WAAW;;;;;CAKd,CAAA"}
@@ -0,0 +1,51 @@
1
+ /**
2
+ * 默认分页配置
3
+ */
4
+ export const PAGINATION_DEFAULTS = {
5
+ /** 默认页码 */
6
+ PAGE: 1,
7
+ /** 默认每页条数 */
8
+ PAGE_SIZE: 20,
9
+ /** 最大每页条数 */
10
+ MAX_PAGE_SIZE: 100,
11
+ };
12
+ /**
13
+ * 默认排序配置
14
+ */
15
+ export const SORT_DEFAULTS = {
16
+ /** 默认排序字段 */
17
+ SORT_BY: 'createdAt',
18
+ /** 默认排序方向 */
19
+ ORDER: 'desc',
20
+ };
21
+ /**
22
+ * 缓存配置
23
+ */
24
+ export const CACHE_CONFIG = {
25
+ /** 列表缓存 key 前缀 */
26
+ LIST_PREFIX: 'inquiries:list',
27
+ /** 详情缓存 key 前缀 */
28
+ DETAIL_PREFIX: 'inquiries:detail',
29
+ };
30
+ /**
31
+ * 错误码定义
32
+ */
33
+ export const ERROR_CODES = {
34
+ /** 无效的 ID */
35
+ INVALID_ID: 10001,
36
+ /** 记录不存在 */
37
+ NOT_FOUND: 10002,
38
+ /** 无效的参数 */
39
+ INVALID_PARAMS: 10003,
40
+ /** 服务器内部错误 */
41
+ INTERNAL_ERROR: 10000,
42
+ };
43
+ /**
44
+ * HTTP 状态码
45
+ */
46
+ export const HTTP_STATUS = {
47
+ OK: 200,
48
+ BAD_REQUEST: 400,
49
+ NOT_FOUND: 404,
50
+ INTERNAL_ERROR: 500,
51
+ };
@@ -0,0 +1,29 @@
1
+ /**
2
+ * 默认查询配置
3
+ */
4
+ export declare const QUERY_DEFAULTS: {
5
+ /** 默认查询条数限制 */
6
+ readonly LIMIT: 100;
7
+ /** 最大查询条数限制 */
8
+ readonly MAX_LIMIT: 1000;
9
+ };
10
+ /**
11
+ * 错误码定义
12
+ */
13
+ export declare const ERROR_CODES: {
14
+ /** 无效的查询参数 */
15
+ readonly INVALID_QUERY: 20001;
16
+ /** 查询失败 */
17
+ readonly QUERY_FAILED: 20002;
18
+ /** 服务器内部错误 */
19
+ readonly INTERNAL_ERROR: 20000;
20
+ };
21
+ /**
22
+ * HTTP 状态码
23
+ */
24
+ export declare const HTTP_STATUS: {
25
+ readonly OK: 200;
26
+ readonly BAD_REQUEST: 400;
27
+ readonly INTERNAL_ERROR: 500;
28
+ };
29
+ //# sourceMappingURL=visitor.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"visitor.d.ts","sourceRoot":"","sources":["../../../../src/core/lib/constants/visitor.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,cAAc;IAC1B,eAAe;;IAEf,eAAe;;CAEN,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,WAAW;IACvB,cAAc;;IAEd,WAAW;;IAEX,cAAc;;CAEL,CAAA;AAEV;;GAEG;AACH,eAAO,MAAM,WAAW;;;;CAId,CAAA"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 默认查询配置
3
+ */
4
+ export const QUERY_DEFAULTS = {
5
+ /** 默认查询条数限制 */
6
+ LIMIT: 100,
7
+ /** 最大查询条数限制 */
8
+ MAX_LIMIT: 1000,
9
+ };
10
+ /**
11
+ * 错误码定义
12
+ */
13
+ export const ERROR_CODES = {
14
+ /** 无效的查询参数 */
15
+ INVALID_QUERY: 20001,
16
+ /** 查询失败 */
17
+ QUERY_FAILED: 20002,
18
+ /** 服务器内部错误 */
19
+ INTERNAL_ERROR: 20000,
20
+ };
21
+ /**
22
+ * HTTP 状态码
23
+ */
24
+ export const HTTP_STATUS = {
25
+ OK: 200,
26
+ BAD_REQUEST: 400,
27
+ INTERNAL_ERROR: 500,
28
+ };
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 数据文件根目录(可通过环境变量覆盖)
3
+ */
4
+ export declare const DATA_DIR: string;
5
+ /**
6
+ * 询盘数据库文件路径
7
+ */
8
+ export declare const INQUIRY_DB_PATH: string;
9
+ /**
10
+ * 单个访客分片数据库最大容量(字节)
11
+ */
12
+ export declare const MAX_DB_SIZE_BYTES: number;
13
+ /** 访客分片策略 */
14
+ export type VisitorShardStrategy = 'sequence' | 'date';
15
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../../../../src/core/lib/database/constants/database.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,eAAO,MAAM,QAAQ,QAAuD,CAAA;AAE5E;;GAEG;AACH,eAAO,MAAM,eAAe,QAAoC,CAAA;AAEhE;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAoB,CAAA;AAElD,aAAa;AACb,MAAM,MAAM,oBAAoB,GAAG,UAAU,GAAG,MAAM,CAAA"}
@@ -0,0 +1,14 @@
1
+ import * as path from 'node:path';
2
+ import { WEBSITE_DATA_DIR } from '../../../../contract';
3
+ /**
4
+ * 数据文件根目录(可通过环境变量覆盖)
5
+ */
6
+ export const DATA_DIR = WEBSITE_DATA_DIR || path.join(process.cwd(), 'data');
7
+ /**
8
+ * 询盘数据库文件路径
9
+ */
10
+ export const INQUIRY_DB_PATH = path.join(DATA_DIR, 'inquiry.db');
11
+ /**
12
+ * 单个访客分片数据库最大容量(字节)
13
+ */
14
+ export const MAX_DB_SIZE_BYTES = 100 * 1024 * 1024;
@@ -0,0 +1,63 @@
1
+ import type { Inquiry, InquiryCreate, InquiryListParams } from './schemas/inquiry.schema';
2
+ import type { DailyPageViewStats, IpPageViewStats, PageView, PVStats, UVStats, VisitorCreate, VisitorQuery, VisitorSession, VisitorStatsBy } from './schemas/visitor.schema';
3
+ /**
4
+ * DatabaseService:聚合仓储,提供对外的业务友好 API。
5
+ */
6
+ export declare class DatabaseService {
7
+ private manager;
8
+ private inquiryRepo;
9
+ private visitorRepo;
10
+ private initialized;
11
+ constructor();
12
+ /** 初始化数据目录及各表结构 */
13
+ init(): Promise<void>;
14
+ /** 询盘:创建 */
15
+ addInquiry(data: InquiryCreate): Promise<number>;
16
+ /** 询盘:按 ID 查询 */
17
+ getInquiryById(id: number): Promise<Inquiry | null>;
18
+ /** 询盘:列表 */
19
+ listInquiries(params?: InquiryListParams): Promise<Inquiry[]>;
20
+ /** 询盘:计数 */
21
+ countInquiries(params?: InquiryListParams): Promise<number>;
22
+ /** 询盘:统计未读数量 */
23
+ countUnreadInquiries(): Promise<number>;
24
+ /** 询盘:标记已读 */
25
+ markInquiryAsRead(id: number, operatorId: number): Promise<boolean>;
26
+ /** 访客:写入 */
27
+ addVisitor(data: VisitorCreate): Promise<{
28
+ id: number;
29
+ shardPath: string;
30
+ }>;
31
+ /** 访客:查询页面浏览记录 */
32
+ queryPageViews(filter?: VisitorQuery): Promise<PageView[]>;
33
+ /** 访客:查询访客会话 */
34
+ queryVisitorSessions(filter?: VisitorQuery): Promise<VisitorSession[]>;
35
+ /** 访客:计数(页面浏览数) */
36
+ countVisitors(filter?: VisitorQuery): Promise<number>;
37
+ /** 访客:统计(向后兼容) */
38
+ visitorStats(by: VisitorStatsBy, filter?: VisitorQuery): Promise<{
39
+ key: string;
40
+ count: number;
41
+ }[]>;
42
+ /**
43
+ * 统计独立访客数(UV)
44
+ */
45
+ getUVStats(filter?: VisitorQuery, byDate?: boolean): Promise<UVStats>;
46
+ /**
47
+ * 统计页面总浏览量(PV)
48
+ */
49
+ getPVStats(filter?: VisitorQuery, groupBy?: 'page' | 'date'): Promise<PVStats>;
50
+ /**
51
+ * 统计每个页面每日的访问次数
52
+ */
53
+ getDailyPageViewStats(filter?: VisitorQuery): Promise<DailyPageViewStats[]>;
54
+ /**
55
+ * 基于 IP 的页面访问次数统计
56
+ */
57
+ getIpPageViewStats(filter?: VisitorQuery): Promise<IpPageViewStats[]>;
58
+ }
59
+ /**
60
+ * 获取数据库服务实例(单例)
61
+ */
62
+ export declare function getDatabase(): Promise<DatabaseService>;
63
+ //# sourceMappingURL=database.service.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.service.d.ts","sourceRoot":"","sources":["../../../../src/core/lib/database/database.service.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EACX,OAAO,EACP,aAAa,EACb,iBAAiB,EACjB,MAAM,0BAA0B,CAAA;AACjC,OAAO,KAAK,EACX,kBAAkB,EAClB,eAAe,EACf,QAAQ,EACR,OAAO,EACP,OAAO,EACP,aAAa,EACb,YAAY,EACZ,cAAc,EACd,cAAc,EACd,MAAM,0BAA0B,CAAA;AAEjC;;GAEG;AACH,qBAAa,eAAe;IAC3B,OAAO,CAAC,OAAO,CAAQ;IACvB,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,WAAW,CAAmB;IACtC,OAAO,CAAC,WAAW,CAAQ;;IAQ3B,mBAAmB;IACb,IAAI;IAQV,YAAY;IACZ,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC;IAIhD,iBAAiB;IACjB,cAAc,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;IAInD,YAAY;IACZ,aAAa,CAAC,MAAM,GAAE,iBAAsB,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;IAIjE,YAAY;IACZ,cAAc,CAAC,MAAM,GAAE,iBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAI/D,gBAAgB;IAChB,oBAAoB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIvC,cAAc;IACd,iBAAiB,CAAC,EAAE,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAInE,YAAY;IACZ,UAAU,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC;QAAE,EAAE,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAA;KAAE,CAAC;IAI3E,kBAAkB;IAClB,cAAc,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAI9D,gBAAgB;IAChB,oBAAoB,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IAI1E,mBAAmB;IACnB,aAAa,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,MAAM,CAAC;IAIzD,kBAAkB;IAClB,YAAY,CACX,EAAE,EAAE,cAAc,EAClB,MAAM,GAAE,YAAiB,GACvB,OAAO,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;IAI5C;;OAEG;IACH,UAAU,CAAC,MAAM,GAAE,YAAiB,EAAE,MAAM,UAAQ,GAAG,OAAO,CAAC,OAAO,CAAC;IAIvE;;OAEG;IACH,UAAU,CACT,MAAM,GAAE,YAAiB,EACzB,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GACvB,OAAO,CAAC,OAAO,CAAC;IAInB;;OAEG;IACH,qBAAqB,CACpB,MAAM,GAAE,YAAiB,GACvB,OAAO,CAAC,kBAAkB,EAAE,CAAC;IAIhC;;OAEG;IACH,kBAAkB,CAAC,MAAM,GAAE,YAAiB,GAAG,OAAO,CAAC,eAAe,EAAE,CAAC;CAGzE;AAOD;;GAEG;AACH,wBAAsB,WAAW,IAAI,OAAO,CAAC,eAAe,CAAC,CAM5D"}