create-fullstack-scaffold 0.4.2 → 0.4.4
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/cli/index.js +513 -122
- package/dist/cli/index.js.map +1 -1
- package/package.json +1 -1
- package/template/dist/cli/index.js +237 -94
- package/template/dist/cli/index.js.map +1 -1
- package/template/dist/client/admin.html +15 -10
- package/template/dist/client/assets/App-BpFUIC-5.js +114 -0
- package/template/dist/client/assets/{CartPage-DESSHkaG.js → CartPage-DgDZP-R5.js} +2 -2
- package/template/dist/client/assets/{CategoriesPage-DqLZ_Mom.js → CategoriesPage-fuYNiSmE.js} +2 -2
- package/template/dist/client/assets/ContentDetailPage-BvvFU1Mr.js +1 -0
- package/template/dist/client/assets/ContentListPage-ShPxo6WG.js +1 -0
- package/template/dist/client/assets/DashboardPage-C1rZzZo4.js +11 -0
- package/template/dist/client/assets/{DeveloperDashboardPage-Cum7zFwO.js → DeveloperDashboardPage-_WtmbVoA.js} +2 -2
- package/template/dist/client/assets/{EmptyState-BK7ttK8D.js → EmptyState-DEyOQjbY.js} +1 -1
- package/template/dist/client/assets/LoadingSpinner-BcHjaM1m.js +6 -0
- package/template/dist/client/assets/LoginPage-CjeQqDdO.js +1 -0
- package/template/dist/client/assets/LogoutOutlined-ColFAHdd.js +1 -0
- package/template/dist/client/assets/NotificationPage-DRkEv02s.js +1 -0
- package/template/dist/client/assets/OrdersPage-7I3vPWLP.js +11 -0
- package/template/dist/client/assets/{PluginDetailPage-Br24YS4P.js → PluginDetailPage-CWyxdVCg.js} +3 -13
- package/template/dist/client/assets/PluginsPage-DRgWLeJT.js +6 -0
- package/template/dist/client/assets/ProfilePage-2FFkaii8.js +16 -0
- package/template/dist/client/assets/PublishPage-DW7yvROx.js +1 -0
- package/template/dist/client/assets/{RegisterPage-rPFG4Sry.js → RegisterPage-Dvaf9b0e.js} +2 -2
- package/template/dist/client/assets/SaveOutlined-CLQ2tsSY.js +2 -0
- package/template/dist/client/assets/{SearchPage-DQl1U5Uy.js → SearchPage-DvnEyswS.js} +2 -2
- package/template/dist/client/assets/{SettingsPage-DaYE80wj.js → SettingsPage-IrU-L9Zr.js} +2 -2
- package/template/dist/client/assets/{StatusBadge-BJ3W2Zc7.js → StatusBadge-CG7wVqpu.js} +1 -1
- package/template/dist/client/assets/{TodoPage-zC5wWNBa.js → TodoPage-B7D-bl65.js} +3 -3
- package/template/dist/client/assets/TopicsPage-CYCNr-mn.js +6 -0
- package/template/dist/client/assets/{WebSocketPage-B4NLdz1w.js → WebSocketPage-CGEg6QJE.js} +2 -2
- package/template/dist/client/assets/{activity-B94BUAsD.js → activity-CgTz9Mrd.js} +1 -1
- package/template/dist/client/assets/admin-D2iHWNOg.js +1 -0
- package/template/dist/client/assets/api-request-DIJocPxr.js +356 -0
- package/template/dist/client/assets/{arrow-left-H5JH0iU1.js → arrow-left-DtLQ3tTk.js} +1 -1
- package/template/dist/client/assets/{chevron-down-DwRh_wjD.js → chevron-down-CpIAV_yr.js} +1 -1
- package/template/dist/client/assets/{chevron-right-CpIWaqAL.js → chevron-right-CnU7oPQs.js} +1 -1
- package/template/dist/client/assets/{circle-check-big-CSElLscG.js → circle-check-big-CrZdwS75.js} +1 -1
- package/template/dist/client/assets/{circle-x-CYxr4RAw.js → circle-x-CvN9r3fW.js} +1 -1
- package/template/dist/client/assets/{clock-BseUJ7ex.js → clock-CTeSZBiH.js} +1 -1
- package/template/dist/client/assets/{download-BsGC_Xhq.js → download-OSVfVuNV.js} +1 -1
- package/template/dist/client/assets/{external-link-UTDzdjq8.js → external-link-fBsuHMby.js} +1 -1
- package/template/dist/client/assets/{eye-nR10ui7i.js → eye-CwlZZEsj.js} +1 -1
- package/template/dist/client/assets/index-09IqiOaE.css +1 -0
- package/template/dist/client/assets/index-B3CRby6r.js +51 -0
- package/template/dist/client/assets/index-CC_zy73y.js +17 -0
- package/template/dist/client/assets/main-Cn4IDo2I.js +92 -0
- package/template/dist/client/assets/merchant-DDDN9bMu.js +40 -0
- package/template/dist/client/assets/{message-square-CwWGL-Bh.js → message-square-BRaZfgbJ.js} +1 -1
- package/template/dist/client/assets/pluginStore-DDsWJPe6.js +1 -0
- package/template/dist/client/assets/{plus-pZld_nUL.js → plus-DDZfPiDJ.js} +1 -1
- package/template/dist/client/assets/sse-client-DGQ072hl.js +64 -0
- package/template/dist/client/assets/star-C7tO6w4H.js +11 -0
- package/template/dist/client/assets/{tag-DsiUPF90.js → tag-DBfpQDuJ.js} +1 -1
- package/template/dist/client/assets/tenant-CizbLaLJ.js +1 -0
- package/template/dist/client/assets/{trash-2-DRblNbnA.js → trash-2-BP7fkd5b.js} +1 -1
- package/template/dist/client/assets/{triangle-alert-D1CLh-Vd.js → triangle-alert-CrOQEdJ2.js} +1 -1
- package/template/dist/client/assets/{wifi-BwXjnCqI.js → wifi-CwYSE0J4.js} +1 -1
- package/template/dist/client/assets/{x-BH2rJdFq.js → x-t615pnNR.js} +1 -1
- package/template/dist/client/content/index.html +5 -4
- package/template/dist/client/index.html +4 -3
- package/template/dist/client/merchant.html +18 -0
- package/template/dist/client/notifications/index.html +6 -5
- package/template/dist/client/tenant.html +18 -0
- package/template/dist/client/todos/index.html +6 -5
- package/template/dist/client/websocket/index.html +6 -5
- package/template/dist/cloudflare/chunk-HX7DVRDX.js +1 -0
- package/template/dist/cloudflare/{chunk-QBHAPWIA.js → chunk-IXJL2LE4.js} +1 -1
- package/template/dist/cloudflare/chunk-Q34AN3RF.js +14 -0
- package/template/dist/cloudflare/{chunk-BHPTQ4K2.js → chunk-ZAMVL4EG.js} +2 -2
- package/template/dist/cloudflare/cloudflare.js +35 -29
- package/template/dist/cloudflare/db-4AQOSFAX.js +1 -0
- package/template/dist/cloudflare/{migrator-2ZYYKNI5.js → migrator-TEPBVUFO.js} +1 -1
- package/template/dist/cloudflare/permission-service-impl-RE7NPW3Q.js +1 -0
- package/template/dist/cloudflare/schema-DVEMT3X2.js +1 -0
- package/template/dist/cloudflare/test-setup-Z2RYE5B4.js +265 -0
- package/template/dist/server/chunk-27SIJSPF.js +1 -0
- package/template/dist/server/chunk-37QNGBQU.js +1 -0
- package/template/dist/server/chunk-FIY4CGJJ.js +1 -0
- package/template/dist/server/chunk-HZUDBIT4.js +1 -0
- package/template/dist/server/chunk-I6OBDFDU.js +1 -0
- package/template/dist/server/chunk-JHNYLNG7.js +1 -0
- package/template/dist/server/chunk-MDOVVKKD.js +1 -0
- package/template/dist/server/chunk-NSOCT7E5.js +1 -0
- package/template/dist/server/chunk-OU5IGVVO.js +1 -0
- package/template/dist/server/chunk-OYCBNRMK.js +1 -0
- package/template/dist/server/chunk-P2RJNNGD.js +1 -0
- package/template/dist/server/chunk-UMAQLNPE.js +1 -0
- package/template/dist/server/chunk-XZZTSRSN.js +1 -0
- package/template/dist/server/content-service-5QVHDR5X.js +1 -0
- package/template/dist/server/db-FLI5L5DD.js +1 -0
- package/template/dist/server/dispute-service-E2FCYUEM.js +1 -0
- package/template/dist/server/init-72JXJV3I.js +46 -0
- package/template/dist/server/init-FWYXSKPX.js +46 -0
- package/template/dist/server/node.js +34 -28
- package/template/dist/server/order-service-TKGG5S5K.js +1 -0
- package/template/dist/server/permission-service-impl-M3AKEYNY.js +1 -0
- package/template/dist/server/schema-V4UG7HMU.js +1 -0
- package/template/dist/server/tenant-service-JG6UUWXQ.js +1 -0
- package/template/dist/server/tenant-service-XJWZSEDX.js +1 -0
- package/template/dist/{cloudflare/test-setup-NMZJZLRV.js → server/test-setup-VFOPBGYM.js} +83 -2
- package/template/dist/server/ticket-service-3RSW7V2Z.js +1 -0
- package/template/dist/server/todo-service-S6BGIO7D.js +1 -0
- package/template/package.json +1 -1
- package/template/src/client/App.tsx +3 -1
- package/template/src/client/pages/ContentListPage.tsx +36 -4
- package/template/src/client/pages/PluginsPage.tsx +112 -20
- package/template/src/client/pages/TodoPage.tsx +9 -1
- package/template/src/client/preset-ui-config.ts +79 -2
- package/template/src/merchant/pages/DisputesPage.tsx +11 -11
- package/template/src/merchant/pages/OrdersPage.tsx +4 -3
- package/template/src/merchant/pages/ProductsPage.tsx +2 -2
- package/template/src/merchant/stores/merchantStore.ts +11 -6
- package/template/src/server/db/init.ts +5 -253
- package/template/src/server/module-content/routes/topics-routes.ts +250 -0
- package/template/src/server/module-content/services/content-service.ts +1 -1
- package/template/src/server/module-plugin/services/plugin-seed-service.ts +623 -0
- package/template/src/server/module-tenant/routes/tenant-routes.ts +2 -2
- package/template/src/server/module-tenant/services/tenant-service.ts +63 -17
- package/template/src/server/module-todos/services/todo-service.ts +1 -1
- package/template/src/shared/modules/merchant/index.ts +9 -0
- package/template/src/shared/modules/merchant/schemas.ts +37 -0
- package/template/src/shared/modules/tenant/index.ts +2 -0
- package/template/src/shared/schemas/index.ts +27 -0
- package/template/src/tenant/layouts/Header.tsx +1 -1
- package/template/src/tenant/layouts/Sidebar.tsx +1 -1
- package/template/src/tenant/pages/SettingsPage.tsx +4 -8
- package/template/src/tenant/stores/tenantStore.ts +41 -302
- package/template/tsconfig.json +1 -0
- package/template/tsup.config.ts +11 -3
- package/template/dist/client/assets/ContentDetailPage-DdltMANL.js +0 -1
- package/template/dist/client/assets/ContentListPage-B63sUB6N.js +0 -1
- package/template/dist/client/assets/DashboardPage-tUMilc7Z.js +0 -11
- package/template/dist/client/assets/LoadingSpinner-DVYOLSRM.js +0 -6
- package/template/dist/client/assets/LoginPage-g9mSLIMC.js +0 -6
- package/template/dist/client/assets/NotificationPage-COTzp-HD.js +0 -1
- package/template/dist/client/assets/OrdersPage-BsPh4oEI.js +0 -11
- package/template/dist/client/assets/PluginsPage-BNtAe_yo.js +0 -6
- package/template/dist/client/assets/ProfilePage-dL_iSuZN.js +0 -16
- package/template/dist/client/assets/PublishPage-D96FnbLA.js +0 -1
- package/template/dist/client/assets/TopicsPage-DyLjZa4D.js +0 -6
- package/template/dist/client/assets/admin-Bh1vfz_L.js +0 -486
- package/template/dist/client/assets/index-1bA-ixFv.js +0 -114
- package/template/dist/client/assets/index-CWh3vXC_.css +0 -1
- package/template/dist/client/assets/main-DHnArIp_.js +0 -82
- package/template/dist/client/assets/pluginStore-XQfsm3iR.js +0 -1
- package/template/dist/client/content/content-1/index.html +0 -18
- package/template/dist/client/content/content-13/index.html +0 -18
- package/template/dist/client/content/content-14/index.html +0 -18
- package/template/dist/client/content/content-15/index.html +0 -18
- package/template/dist/client/content/content-19/index.html +0 -18
- package/template/dist/client/content/content-2/index.html +0 -18
- package/template/dist/client/content/content-20/index.html +0 -18
- package/template/dist/cloudflare/chunk-YY6FRMAQ.js +0 -14
- package/template/dist/cloudflare/db-7J42RQ3T.js +0 -1
- package/template/dist/cloudflare/permission-service-impl-TGXVSSSA.js +0 -1
|
@@ -14,8 +14,8 @@ export const ProductsPage: FC = () => {
|
|
|
14
14
|
setLoading(true)
|
|
15
15
|
try {
|
|
16
16
|
const response = await fetch('/api/merchant/products')
|
|
17
|
-
const result = await response.json()
|
|
18
|
-
if (result.success) {
|
|
17
|
+
const result = (await response.json()) as { success?: boolean; data?: Product[] }
|
|
18
|
+
if (result.success === true && result.data) {
|
|
19
19
|
setProducts(result.data)
|
|
20
20
|
}
|
|
21
21
|
} catch (error) {
|
|
@@ -13,6 +13,8 @@ interface MerchantState {
|
|
|
13
13
|
stats: MerchantStats | null
|
|
14
14
|
loading: boolean
|
|
15
15
|
error: string | null
|
|
16
|
+
startLoading: (message?: string) => void
|
|
17
|
+
stopLoading: () => void
|
|
16
18
|
checkAuth: () => Promise<void>
|
|
17
19
|
login: (username: string, password: string) => Promise<void>
|
|
18
20
|
logout: () => void
|
|
@@ -28,12 +30,15 @@ export const useMerchantStore = create<MerchantState>(set => ({
|
|
|
28
30
|
loading: false,
|
|
29
31
|
error: null,
|
|
30
32
|
|
|
33
|
+
startLoading: (_message?: string) => set({ loading: true }),
|
|
34
|
+
stopLoading: () => set({ loading: false }),
|
|
35
|
+
|
|
31
36
|
checkAuth: async () => {
|
|
32
37
|
set({ loading: true, error: null })
|
|
33
38
|
try {
|
|
34
39
|
const response = await fetch('/api/merchant/me')
|
|
35
|
-
const result = await response.json()
|
|
36
|
-
if (result.success) {
|
|
40
|
+
const result = (await response.json()) as { success?: boolean; data?: User }
|
|
41
|
+
if (result.success === true && result.data) {
|
|
37
42
|
set({ user: result.data, isAuthenticated: true })
|
|
38
43
|
} else {
|
|
39
44
|
set({ user: null, isAuthenticated: false })
|
|
@@ -56,8 +61,8 @@ export const useMerchantStore = create<MerchantState>(set => ({
|
|
|
56
61
|
},
|
|
57
62
|
body: JSON.stringify({ username, password }),
|
|
58
63
|
})
|
|
59
|
-
const result = await response.json()
|
|
60
|
-
if (result.success) {
|
|
64
|
+
const result = (await response.json()) as { success?: boolean; data?: User; error?: string }
|
|
65
|
+
if (result.success === true && result.data) {
|
|
61
66
|
set({ user: result.data, isAuthenticated: true })
|
|
62
67
|
} else {
|
|
63
68
|
set({ error: result.error || 'Login failed' })
|
|
@@ -78,8 +83,8 @@ export const useMerchantStore = create<MerchantState>(set => ({
|
|
|
78
83
|
set({ loading: true, error: null })
|
|
79
84
|
try {
|
|
80
85
|
const response = await fetch('/api/merchant/stats')
|
|
81
|
-
const result = await response.json()
|
|
82
|
-
if (result.success) {
|
|
86
|
+
const result = (await response.json()) as { success?: boolean; data?: MerchantStats }
|
|
87
|
+
if (result.success === true && result.data) {
|
|
83
88
|
set({ stats: result.data })
|
|
84
89
|
}
|
|
85
90
|
} catch (error) {
|
|
@@ -363,8 +363,8 @@ async function seedDevelopersIfEmpty() {
|
|
|
363
363
|
|
|
364
364
|
log.info({}, 'Seeding developers...')
|
|
365
365
|
|
|
366
|
-
const demoPasswordHash = await hash('demo123')
|
|
367
|
-
const adminPasswordHash = await hash('admin123')
|
|
366
|
+
const demoPasswordHash = await hash('demo123', 10)
|
|
367
|
+
const adminPasswordHash = await hash('admin123', 10)
|
|
368
368
|
|
|
369
369
|
const sampleDevelopers = [
|
|
370
370
|
{
|
|
@@ -372,7 +372,7 @@ async function seedDevelopersIfEmpty() {
|
|
|
372
372
|
username: 'demo',
|
|
373
373
|
email: 'demo@biomimic.app',
|
|
374
374
|
passwordHash: demoPasswordHash,
|
|
375
|
-
role: 'developer',
|
|
375
|
+
role: 'developer' as const,
|
|
376
376
|
apiKey: generateUUID(),
|
|
377
377
|
},
|
|
378
378
|
{
|
|
@@ -380,7 +380,7 @@ async function seedDevelopersIfEmpty() {
|
|
|
380
380
|
username: 'superadmin',
|
|
381
381
|
email: 'admin@biomimic.app',
|
|
382
382
|
passwordHash: adminPasswordHash,
|
|
383
|
-
role: 'admin',
|
|
383
|
+
role: 'admin' as const,
|
|
384
384
|
apiKey: generateUUID(),
|
|
385
385
|
},
|
|
386
386
|
]
|
|
@@ -401,254 +401,6 @@ async function seedDevelopersIfEmpty() {
|
|
|
401
401
|
}
|
|
402
402
|
}
|
|
403
403
|
|
|
404
|
-
async function seedPluginsIfEmpty() {
|
|
405
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any -- dynamic import for presets that may not have plugin module
|
|
406
|
-
let plugins: any
|
|
407
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
408
|
-
let pluginVersions: any
|
|
409
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
410
|
-
let pluginCategories: any
|
|
411
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
412
|
-
let pluginCategoryMappings: any
|
|
413
|
-
try {
|
|
414
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
415
|
-
const schema = (await import('./schema')) as Record<string, any>
|
|
416
|
-
plugins = schema.plugins
|
|
417
|
-
pluginVersions = schema.pluginVersions
|
|
418
|
-
pluginCategories = schema.pluginCategories
|
|
419
|
-
pluginCategoryMappings = schema.pluginCategoryMappings
|
|
420
|
-
if (!plugins) return
|
|
421
|
-
} catch {
|
|
422
|
-
return
|
|
423
|
-
}
|
|
424
|
-
|
|
425
|
-
const db = await getDb()
|
|
426
|
-
|
|
427
|
-
const existing = await db.select().from(plugins)
|
|
428
|
-
if (existing.length > 0) return
|
|
429
|
-
|
|
430
|
-
log.info({}, 'Seeding plugins...')
|
|
431
|
-
|
|
432
|
-
const sampleCategories = [
|
|
433
|
-
{
|
|
434
|
-
id: generateUUID(),
|
|
435
|
-
name: 'UI & Design',
|
|
436
|
-
slug: 'ui-design',
|
|
437
|
-
description: 'Visual customization and theming',
|
|
438
|
-
icon: 'palette',
|
|
439
|
-
sortOrder: 1,
|
|
440
|
-
},
|
|
441
|
-
{
|
|
442
|
-
id: generateUUID(),
|
|
443
|
-
name: 'Analytics',
|
|
444
|
-
slug: 'analytics',
|
|
445
|
-
description: 'Data tracking and reporting',
|
|
446
|
-
icon: 'chart',
|
|
447
|
-
sortOrder: 2,
|
|
448
|
-
},
|
|
449
|
-
{
|
|
450
|
-
id: generateUUID(),
|
|
451
|
-
name: 'SEO & Marketing',
|
|
452
|
-
slug: 'seo-marketing',
|
|
453
|
-
description: 'Search optimization and growth tools',
|
|
454
|
-
icon: 'trending-up',
|
|
455
|
-
sortOrder: 3,
|
|
456
|
-
},
|
|
457
|
-
{
|
|
458
|
-
id: generateUUID(),
|
|
459
|
-
name: 'Developer Tools',
|
|
460
|
-
slug: 'developer-tools',
|
|
461
|
-
description: 'Utilities for developers',
|
|
462
|
-
icon: 'code',
|
|
463
|
-
sortOrder: 4,
|
|
464
|
-
},
|
|
465
|
-
{
|
|
466
|
-
id: generateUUID(),
|
|
467
|
-
name: 'Integration',
|
|
468
|
-
slug: 'integration',
|
|
469
|
-
description: 'Third-party service integrations',
|
|
470
|
-
icon: 'plug',
|
|
471
|
-
sortOrder: 5,
|
|
472
|
-
},
|
|
473
|
-
]
|
|
474
|
-
|
|
475
|
-
await db.insert(pluginCategories).values(sampleCategories)
|
|
476
|
-
|
|
477
|
-
const samplePlugins = [
|
|
478
|
-
{
|
|
479
|
-
id: generateUUID(),
|
|
480
|
-
name: 'Theme Engine',
|
|
481
|
-
slug: 'theme-engine',
|
|
482
|
-
description:
|
|
483
|
-
'Advanced theming system with dark mode, custom color palettes, and responsive layout controls.',
|
|
484
|
-
readme:
|
|
485
|
-
'# Theme Engine\n\nA powerful theming plugin for customizing the look and feel of your application.',
|
|
486
|
-
authorId: '1',
|
|
487
|
-
authorName: 'superadmin',
|
|
488
|
-
repositoryUrl: 'https://github.com/example/theme-engine',
|
|
489
|
-
homepageUrl: 'https://theme-engine.example.com',
|
|
490
|
-
license: 'MIT',
|
|
491
|
-
version: '2.1.0',
|
|
492
|
-
status: 'approved' as const,
|
|
493
|
-
downloadCount: 1520,
|
|
494
|
-
viewCount: 4320,
|
|
495
|
-
featured: true,
|
|
496
|
-
screenshotUrl: 'https://picsum.photos/seed/theme/800/400',
|
|
497
|
-
tags: '["theme","dark-mode","customization"]',
|
|
498
|
-
},
|
|
499
|
-
{
|
|
500
|
-
id: generateUUID(),
|
|
501
|
-
slug: 'analytics-dashboard',
|
|
502
|
-
name: 'Analytics Dashboard',
|
|
503
|
-
description:
|
|
504
|
-
'Real-time analytics dashboard with charts, heatmaps, and user behavior tracking.',
|
|
505
|
-
readme: '# Analytics Dashboard\n\nTrack user engagement and visualize data in real time.',
|
|
506
|
-
authorId: '1',
|
|
507
|
-
authorName: 'superadmin',
|
|
508
|
-
repositoryUrl: 'https://github.com/example/analytics-dashboard',
|
|
509
|
-
homepageUrl: 'https://analytics.example.com',
|
|
510
|
-
license: 'Apache-2.0',
|
|
511
|
-
version: '1.5.3',
|
|
512
|
-
status: 'approved' as const,
|
|
513
|
-
downloadCount: 980,
|
|
514
|
-
viewCount: 2100,
|
|
515
|
-
featured: true,
|
|
516
|
-
screenshotUrl: 'https://picsum.photos/seed/analytics/800/400',
|
|
517
|
-
tags: '["analytics","dashboard","charts"]',
|
|
518
|
-
},
|
|
519
|
-
{
|
|
520
|
-
id: generateUUID(),
|
|
521
|
-
slug: 'seo-optimizer',
|
|
522
|
-
name: 'SEO Optimizer',
|
|
523
|
-
description:
|
|
524
|
-
'Automated SEO optimization with meta tags, sitemap generation, and structured data support.',
|
|
525
|
-
authorId: '2',
|
|
526
|
-
authorName: 'customerservice',
|
|
527
|
-
repositoryUrl: 'https://github.com/example/seo-optimizer',
|
|
528
|
-
license: 'MIT',
|
|
529
|
-
version: '1.2.0',
|
|
530
|
-
status: 'approved' as const,
|
|
531
|
-
downloadCount: 740,
|
|
532
|
-
viewCount: 1800,
|
|
533
|
-
featured: false,
|
|
534
|
-
screenshotUrl: 'https://picsum.photos/seed/seo/800/400',
|
|
535
|
-
tags: '["seo","meta","sitemap"]',
|
|
536
|
-
},
|
|
537
|
-
{
|
|
538
|
-
id: generateUUID(),
|
|
539
|
-
slug: 'api-toolkit',
|
|
540
|
-
name: 'API Toolkit',
|
|
541
|
-
description:
|
|
542
|
-
'Developer toolkit for building and testing REST APIs with auto-documentation and mock servers.',
|
|
543
|
-
authorId: '2',
|
|
544
|
-
authorName: 'customerservice',
|
|
545
|
-
repositoryUrl: 'https://github.com/example/api-toolkit',
|
|
546
|
-
homepageUrl: 'https://api-toolkit.example.com',
|
|
547
|
-
license: 'MIT',
|
|
548
|
-
version: '3.0.1',
|
|
549
|
-
status: 'approved' as const,
|
|
550
|
-
downloadCount: 2100,
|
|
551
|
-
viewCount: 5600,
|
|
552
|
-
featured: true,
|
|
553
|
-
screenshotUrl: 'https://picsum.photos/seed/apitoolkit/800/400',
|
|
554
|
-
tags: '["api","developer","testing","documentation"]',
|
|
555
|
-
},
|
|
556
|
-
{
|
|
557
|
-
id: generateUUID(),
|
|
558
|
-
slug: 'notification-hub',
|
|
559
|
-
name: 'Notification Hub',
|
|
560
|
-
description:
|
|
561
|
-
'Unified notification management supporting email, SMS, push, and in-app notifications.',
|
|
562
|
-
authorId: '3',
|
|
563
|
-
authorName: 'user1',
|
|
564
|
-
repositoryUrl: 'https://github.com/example/notification-hub',
|
|
565
|
-
license: 'ISC',
|
|
566
|
-
version: '1.0.0',
|
|
567
|
-
status: 'pending' as const,
|
|
568
|
-
downloadCount: 0,
|
|
569
|
-
viewCount: 50,
|
|
570
|
-
featured: false,
|
|
571
|
-
screenshotUrl: 'https://picsum.photos/seed/notify/800/400',
|
|
572
|
-
tags: '["notification","email","push"]',
|
|
573
|
-
},
|
|
574
|
-
]
|
|
575
|
-
|
|
576
|
-
await db.insert(plugins).values(samplePlugins)
|
|
577
|
-
|
|
578
|
-
const sampleVersions = [
|
|
579
|
-
{
|
|
580
|
-
id: generateUUID(),
|
|
581
|
-
pluginId: samplePlugins[0].id,
|
|
582
|
-
version: '2.1.0',
|
|
583
|
-
changelog: 'Added responsive layout controls',
|
|
584
|
-
status: 'approved' as const,
|
|
585
|
-
},
|
|
586
|
-
{
|
|
587
|
-
id: generateUUID(),
|
|
588
|
-
pluginId: samplePlugins[0].id,
|
|
589
|
-
version: '2.0.0',
|
|
590
|
-
changelog: 'Major rewrite with dark mode support',
|
|
591
|
-
status: 'approved' as const,
|
|
592
|
-
},
|
|
593
|
-
{
|
|
594
|
-
id: generateUUID(),
|
|
595
|
-
pluginId: samplePlugins[1].id,
|
|
596
|
-
version: '1.5.3',
|
|
597
|
-
changelog: 'Fixed heatmap rendering',
|
|
598
|
-
status: 'approved' as const,
|
|
599
|
-
},
|
|
600
|
-
{
|
|
601
|
-
id: generateUUID(),
|
|
602
|
-
pluginId: samplePlugins[1].id,
|
|
603
|
-
version: '1.5.0',
|
|
604
|
-
changelog: 'Added real-time tracking',
|
|
605
|
-
status: 'approved' as const,
|
|
606
|
-
},
|
|
607
|
-
{
|
|
608
|
-
id: generateUUID(),
|
|
609
|
-
pluginId: samplePlugins[2].id,
|
|
610
|
-
version: '1.2.0',
|
|
611
|
-
changelog: 'Structured data support',
|
|
612
|
-
status: 'approved' as const,
|
|
613
|
-
},
|
|
614
|
-
{
|
|
615
|
-
id: generateUUID(),
|
|
616
|
-
pluginId: samplePlugins[3].id,
|
|
617
|
-
version: '3.0.1',
|
|
618
|
-
changelog: 'Auto-documentation improvements',
|
|
619
|
-
status: 'approved' as const,
|
|
620
|
-
},
|
|
621
|
-
{
|
|
622
|
-
id: generateUUID(),
|
|
623
|
-
pluginId: samplePlugins[3].id,
|
|
624
|
-
version: '3.0.0',
|
|
625
|
-
changelog: 'Major version with mock server',
|
|
626
|
-
status: 'approved' as const,
|
|
627
|
-
},
|
|
628
|
-
{
|
|
629
|
-
id: generateUUID(),
|
|
630
|
-
pluginId: samplePlugins[4].id,
|
|
631
|
-
version: '1.0.0',
|
|
632
|
-
changelog: 'Initial release',
|
|
633
|
-
status: 'pending' as const,
|
|
634
|
-
},
|
|
635
|
-
]
|
|
636
|
-
|
|
637
|
-
await db.insert(pluginVersions).values(sampleVersions)
|
|
638
|
-
|
|
639
|
-
const sampleMappings = [
|
|
640
|
-
{ pluginId: samplePlugins[0].id, categoryId: sampleCategories[0].id },
|
|
641
|
-
{ pluginId: samplePlugins[1].id, categoryId: sampleCategories[1].id },
|
|
642
|
-
{ pluginId: samplePlugins[2].id, categoryId: sampleCategories[2].id },
|
|
643
|
-
{ pluginId: samplePlugins[3].id, categoryId: sampleCategories[3].id },
|
|
644
|
-
{ pluginId: samplePlugins[4].id, categoryId: sampleCategories[4].id },
|
|
645
|
-
]
|
|
646
|
-
|
|
647
|
-
await db.insert(pluginCategoryMappings).values(sampleMappings)
|
|
648
|
-
|
|
649
|
-
log.info({}, 'Plugin seeding complete!')
|
|
650
|
-
}
|
|
651
|
-
|
|
652
404
|
export async function initializeDatabase() {
|
|
653
405
|
const db = await getDb()
|
|
654
406
|
|
|
@@ -705,7 +457,7 @@ export async function initializeDatabase() {
|
|
|
705
457
|
() => import('../module-dispute/services/dispute-service').then(m => m.seedDisputesIfEmpty()),
|
|
706
458
|
() => import('../module-content/services/content-service').then(m => m.seedContentsIfEmpty()),
|
|
707
459
|
() => import('../module-tenant/services/tenant-service').then(m => m.seedTenantsIfEmpty()),
|
|
708
|
-
() => seedPluginsIfEmpty(),
|
|
460
|
+
() => import('../module-plugin/services/plugin-seed-service').then(m => m.seedPluginsIfEmpty()),
|
|
709
461
|
]
|
|
710
462
|
await Promise.all(moduleSeeders.map(fn => fn().catch(() => {})))
|
|
711
463
|
log.info({}, 'Module data seeding complete!')
|
|
@@ -101,6 +101,256 @@ const MOCK_TOPICS = [
|
|
|
101
101
|
author: { name: 'Emma Wilson', initials: 'EW' },
|
|
102
102
|
createdAt: '12h ago',
|
|
103
103
|
},
|
|
104
|
+
{
|
|
105
|
+
id: '7',
|
|
106
|
+
title: 'Optimizing React components with useMemo and useCallback',
|
|
107
|
+
excerpt:
|
|
108
|
+
'Understanding when and how to use React hooks for performance optimization. Real-world examples and benchmarks showing measurable improvements.',
|
|
109
|
+
votes: 45,
|
|
110
|
+
replyCount: 15,
|
|
111
|
+
viewCount: 678,
|
|
112
|
+
status: 'discussion' as const,
|
|
113
|
+
tags: [
|
|
114
|
+
{ label: 'React', color: 'bg-cyan-100 text-cyan-700' },
|
|
115
|
+
{ label: 'Performance', color: 'bg-amber-100 text-amber-700' },
|
|
116
|
+
],
|
|
117
|
+
author: { name: '张伟', initials: 'ZW' },
|
|
118
|
+
createdAt: '1d ago',
|
|
119
|
+
},
|
|
120
|
+
{
|
|
121
|
+
id: '8',
|
|
122
|
+
title: 'PostgreSQL query optimization for large datasets',
|
|
123
|
+
excerpt:
|
|
124
|
+
'Strategies for handling millions of rows with efficient indexing, query planning, and materialized views. Includes EXPLAIN ANALYZE walkthrough.',
|
|
125
|
+
votes: 89,
|
|
126
|
+
replyCount: 23,
|
|
127
|
+
viewCount: 1567,
|
|
128
|
+
status: 'hot' as const,
|
|
129
|
+
tags: [
|
|
130
|
+
{ label: 'PostgreSQL', color: 'bg-blue-100 text-blue-700' },
|
|
131
|
+
{ label: 'Database', color: 'bg-indigo-100 text-indigo-700' },
|
|
132
|
+
{ label: 'Performance', color: 'bg-amber-100 text-amber-700' },
|
|
133
|
+
],
|
|
134
|
+
author: { name: 'Raj Sharma', initials: 'RS' },
|
|
135
|
+
createdAt: '1d ago',
|
|
136
|
+
},
|
|
137
|
+
{
|
|
138
|
+
id: '9',
|
|
139
|
+
title: 'Implementing JWT authentication with refresh tokens',
|
|
140
|
+
excerpt:
|
|
141
|
+
'Secure authentication flow with JWT access tokens and refresh tokens. Best practices for token storage, rotation, and revocation.',
|
|
142
|
+
votes: 72,
|
|
143
|
+
replyCount: 18,
|
|
144
|
+
viewCount: 1245,
|
|
145
|
+
status: 'solved' as const,
|
|
146
|
+
tags: [
|
|
147
|
+
{ label: 'Auth', color: 'bg-rose-100 text-rose-700' },
|
|
148
|
+
{ label: 'Security', color: 'bg-red-100 text-red-700' },
|
|
149
|
+
{ label: 'JWT', color: 'bg-pink-100 text-pink-700' },
|
|
150
|
+
],
|
|
151
|
+
author: { name: '田中太郎', initials: 'TT' },
|
|
152
|
+
createdAt: '2d ago',
|
|
153
|
+
},
|
|
154
|
+
{
|
|
155
|
+
id: '10',
|
|
156
|
+
title: 'Building microservices with Docker and Kubernetes',
|
|
157
|
+
excerpt:
|
|
158
|
+
'Complete guide to containerizing Node.js applications and orchestrating them with Kubernetes. Includes service discovery, load balancing, and autoscaling.',
|
|
159
|
+
votes: 103,
|
|
160
|
+
replyCount: 31,
|
|
161
|
+
viewCount: 1890,
|
|
162
|
+
status: 'hot' as const,
|
|
163
|
+
tags: [
|
|
164
|
+
{ label: 'Docker', color: 'bg-sky-100 text-sky-700' },
|
|
165
|
+
{ label: 'Kubernetes', color: 'bg-blue-100 text-blue-700' },
|
|
166
|
+
{ label: 'Microservices', color: 'bg-violet-100 text-violet-700' },
|
|
167
|
+
],
|
|
168
|
+
author: { name: 'Marie Dubois', initials: 'MD' },
|
|
169
|
+
createdAt: '2d ago',
|
|
170
|
+
},
|
|
171
|
+
{
|
|
172
|
+
id: '11',
|
|
173
|
+
title: 'Writing accessible React applications',
|
|
174
|
+
excerpt:
|
|
175
|
+
'Essential ARIA patterns and semantic HTML for building inclusive web apps. Screen reader testing checklist and common accessibility pitfalls.',
|
|
176
|
+
votes: 58,
|
|
177
|
+
replyCount: 14,
|
|
178
|
+
viewCount: 923,
|
|
179
|
+
status: 'open' as const,
|
|
180
|
+
tags: [
|
|
181
|
+
{ label: 'Accessibility', color: 'bg-emerald-100 text-emerald-700' },
|
|
182
|
+
{ label: 'React', color: 'bg-cyan-100 text-cyan-700' },
|
|
183
|
+
{ label: 'A11y', color: 'bg-lime-100 text-lime-700' },
|
|
184
|
+
],
|
|
185
|
+
author: { name: '김민수', initials: 'KM' },
|
|
186
|
+
createdAt: '3d ago',
|
|
187
|
+
},
|
|
188
|
+
{
|
|
189
|
+
id: '12',
|
|
190
|
+
title: 'TypeScript utility types explained with examples',
|
|
191
|
+
excerpt:
|
|
192
|
+
'Deep dive into TypeScript utility types like Pick, Omit, Partial, Record, and more. Practical examples for everyday use.',
|
|
193
|
+
votes: 81,
|
|
194
|
+
replyCount: 22,
|
|
195
|
+
viewCount: 1456,
|
|
196
|
+
status: 'hot' as const,
|
|
197
|
+
tags: [
|
|
198
|
+
{ label: 'TypeScript', color: 'bg-blue-100 text-blue-700' },
|
|
199
|
+
{ label: 'Guide', color: 'bg-emerald-100 text-emerald-700' },
|
|
200
|
+
],
|
|
201
|
+
author: { name: 'Anna Müller', initials: 'AM' },
|
|
202
|
+
createdAt: '3d ago',
|
|
203
|
+
},
|
|
204
|
+
{
|
|
205
|
+
id: '13',
|
|
206
|
+
title: 'Redis caching strategies for high-traffic APIs',
|
|
207
|
+
excerpt:
|
|
208
|
+
'Implementing Redis caching layers for REST APIs. Cache invalidation strategies, TTL policies, and handling cache stampedes.',
|
|
209
|
+
votes: 64,
|
|
210
|
+
replyCount: 9,
|
|
211
|
+
viewCount: 1012,
|
|
212
|
+
status: 'solved' as const,
|
|
213
|
+
tags: [
|
|
214
|
+
{ label: 'Redis', color: 'bg-red-100 text-red-700' },
|
|
215
|
+
{ label: 'Caching', color: 'bg-orange-100 text-orange-700' },
|
|
216
|
+
{ label: 'API', color: 'bg-sky-100 text-sky-700' },
|
|
217
|
+
],
|
|
218
|
+
author: { name: 'Carlos Silva', initials: 'CS' },
|
|
219
|
+
createdAt: '3d ago',
|
|
220
|
+
},
|
|
221
|
+
{
|
|
222
|
+
id: '14',
|
|
223
|
+
title: 'GraphQL Federation for microservices architecture',
|
|
224
|
+
excerpt:
|
|
225
|
+
'Combining multiple GraphQL services into a unified API with Apollo Federation. Schema stitching, type composition, and distributed tracing.',
|
|
226
|
+
votes: 47,
|
|
227
|
+
replyCount: 0,
|
|
228
|
+
viewCount: 623,
|
|
229
|
+
status: 'unanswered' as const,
|
|
230
|
+
tags: [
|
|
231
|
+
{ label: 'GraphQL', color: 'bg-pink-100 text-pink-700' },
|
|
232
|
+
{ label: 'Microservices', color: 'bg-violet-100 text-violet-700' },
|
|
233
|
+
],
|
|
234
|
+
author: { name: '李明', initials: 'LM' },
|
|
235
|
+
createdAt: '4h ago',
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
id: '15',
|
|
239
|
+
title: 'Testing React components with Vitest and Testing Library',
|
|
240
|
+
excerpt:
|
|
241
|
+
'Modern testing setup with Vitest and React Testing Library. Writing maintainable tests, mocking external dependencies, and snapshot testing.',
|
|
242
|
+
votes: 76,
|
|
243
|
+
replyCount: 17,
|
|
244
|
+
viewCount: 1234,
|
|
245
|
+
status: 'discussion' as const,
|
|
246
|
+
tags: [
|
|
247
|
+
{ label: 'Testing', color: 'bg-amber-100 text-amber-700' },
|
|
248
|
+
{ label: 'React', color: 'bg-cyan-100 text-cyan-700' },
|
|
249
|
+
{ label: 'Vitest', color: 'bg-purple-100 text-purple-700' },
|
|
250
|
+
],
|
|
251
|
+
author: { name: 'Elena Popova', initials: 'EP' },
|
|
252
|
+
createdAt: '5h ago',
|
|
253
|
+
},
|
|
254
|
+
{
|
|
255
|
+
id: '16',
|
|
256
|
+
title: 'RESTful API design best practices',
|
|
257
|
+
excerpt:
|
|
258
|
+
'Comprehensive guide to designing REST APIs. Resource naming, HTTP methods, status codes, pagination, filtering, and versioning strategies.',
|
|
259
|
+
votes: 92,
|
|
260
|
+
replyCount: 28,
|
|
261
|
+
viewCount: 1678,
|
|
262
|
+
status: 'hot' as const,
|
|
263
|
+
tags: [
|
|
264
|
+
{ label: 'API Design', color: 'bg-sky-100 text-sky-700' },
|
|
265
|
+
{ label: 'REST', color: 'bg-emerald-100 text-emerald-700' },
|
|
266
|
+
{ label: 'Architecture', color: 'bg-orange-100 text-orange-700' },
|
|
267
|
+
],
|
|
268
|
+
author: { name: '佐藤健', initials: 'SK' },
|
|
269
|
+
createdAt: '6h ago',
|
|
270
|
+
},
|
|
271
|
+
{
|
|
272
|
+
id: '17',
|
|
273
|
+
title: 'CSS Grid vs Flexbox — when to use which?',
|
|
274
|
+
excerpt:
|
|
275
|
+
'Practical comparison of CSS Grid and Flexbox layouts. Use cases, browser support, and examples of combining both for complex layouts.',
|
|
276
|
+
votes: 39,
|
|
277
|
+
replyCount: 8,
|
|
278
|
+
viewCount: 567,
|
|
279
|
+
status: 'open' as const,
|
|
280
|
+
tags: [
|
|
281
|
+
{ label: 'CSS', color: 'bg-indigo-100 text-indigo-700' },
|
|
282
|
+
{ label: 'Layout', color: 'bg-purple-100 text-purple-700' },
|
|
283
|
+
],
|
|
284
|
+
author: { name: 'Olga Ivanova', initials: 'OI' },
|
|
285
|
+
createdAt: '8h ago',
|
|
286
|
+
},
|
|
287
|
+
{
|
|
288
|
+
id: '18',
|
|
289
|
+
title: 'Setting up CI/CD pipeline with GitHub Actions',
|
|
290
|
+
excerpt:
|
|
291
|
+
'Automating testing, building, and deployment with GitHub Actions. Multi-environment configs, secrets management, and deployment strategies.',
|
|
292
|
+
votes: 68,
|
|
293
|
+
replyCount: 13,
|
|
294
|
+
viewCount: 1102,
|
|
295
|
+
status: 'solved' as const,
|
|
296
|
+
tags: [
|
|
297
|
+
{ label: 'CI/CD', color: 'bg-rose-100 text-rose-700' },
|
|
298
|
+
{ label: 'GitHub', color: 'bg-slate-100 text-slate-700' },
|
|
299
|
+
{ label: 'DevOps', color: 'bg-blue-100 text-blue-700' },
|
|
300
|
+
],
|
|
301
|
+
author: { name: '黄志强', initials: 'HZ' },
|
|
302
|
+
createdAt: '30m ago',
|
|
303
|
+
},
|
|
304
|
+
{
|
|
305
|
+
id: '19',
|
|
306
|
+
title: 'Node.js event loop explained in depth',
|
|
307
|
+
excerpt:
|
|
308
|
+
'Understanding the Node.js event loop, call stack, and asynchronous operations. Performance implications and best practices for event-driven apps.',
|
|
309
|
+
votes: 55,
|
|
310
|
+
replyCount: 11,
|
|
311
|
+
viewCount: 845,
|
|
312
|
+
status: 'discussion' as const,
|
|
313
|
+
tags: [
|
|
314
|
+
{ label: 'Node.js', color: 'bg-green-100 text-green-700' },
|
|
315
|
+
{ label: 'Performance', color: 'bg-amber-100 text-amber-700' },
|
|
316
|
+
],
|
|
317
|
+
author: { name: 'Giovanni Rossi', initials: 'GR' },
|
|
318
|
+
createdAt: '45m ago',
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
id: '20',
|
|
322
|
+
title: 'Handling file uploads in multipart/form-data with Hono',
|
|
323
|
+
excerpt:
|
|
324
|
+
'Implementing secure file upload endpoints in Hono. Validation, storage with R2, handling large files, and progress tracking.',
|
|
325
|
+
votes: 71,
|
|
326
|
+
replyCount: 16,
|
|
327
|
+
viewCount: 1323,
|
|
328
|
+
status: 'solved' as const,
|
|
329
|
+
tags: [
|
|
330
|
+
{ label: 'Hono', color: 'bg-sky-100 text-sky-700' },
|
|
331
|
+
{ label: 'File Upload', color: 'bg-indigo-100 text-indigo-700' },
|
|
332
|
+
{ label: 'R2', color: 'bg-amber-100 text-amber-700' },
|
|
333
|
+
],
|
|
334
|
+
author: { name: 'Priya Patel', initials: 'PP' },
|
|
335
|
+
createdAt: '2h ago',
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
id: '21',
|
|
339
|
+
title: 'Debouncing and throttling in React applications',
|
|
340
|
+
excerpt:
|
|
341
|
+
'Implementing debouncing and throttling for search inputs, scroll events, and API calls. Custom hooks and performance considerations.',
|
|
342
|
+
votes: 33,
|
|
343
|
+
replyCount: 5,
|
|
344
|
+
viewCount: 445,
|
|
345
|
+
status: 'open' as const,
|
|
346
|
+
tags: [
|
|
347
|
+
{ label: 'React', color: 'bg-cyan-100 text-cyan-700' },
|
|
348
|
+
{ label: 'Performance', color: 'bg-amber-100 text-amber-700' },
|
|
349
|
+
{ label: 'Hooks', color: 'bg-pink-100 text-pink-700' },
|
|
350
|
+
],
|
|
351
|
+
author: { name: '山本花子', initials: 'YH' },
|
|
352
|
+
createdAt: '1w ago',
|
|
353
|
+
},
|
|
104
354
|
]
|
|
105
355
|
|
|
106
356
|
const MOCK_PROFILE_ACTIVITY = [
|
|
@@ -42,7 +42,7 @@ export async function seedContentsIfEmpty(): Promise<void> {
|
|
|
42
42
|
JSON.stringify(['最佳实践', '经验']),
|
|
43
43
|
]
|
|
44
44
|
|
|
45
|
-
for (let i = 0; i <
|
|
45
|
+
for (let i = 0; i < 25; i++) {
|
|
46
46
|
const category = randomElement(CATEGORIES)
|
|
47
47
|
const status = randomElement(STATUSES)
|
|
48
48
|
const createdAt = new Date(randomDate(new Date('2024-01-01'), new Date()))
|