import type { Core } from '@strapi/strapi'; const DEMO_EMAIL = 'demo@strapi-demo.local'; const DEMO_PASSWORD = 'Demo1234!'; type PermissionMap = Record; async function ensurePermissions( strapi: Core.Strapi, roleType: 'public' | 'authenticated', permissions: PermissionMap, ) { const role = await strapi.db.query('plugin::users-permissions.role').findOne({ where: { type: roleType }, }); if (!role) return; for (const [uid, actions] of Object.entries(permissions)) { for (const action of actions) { const permissionAction = `${uid}.${action}`; const existing = await strapi.db.query('plugin::users-permissions.permission').findOne({ where: { action: permissionAction, role: role.id }, }); if (!existing) { await strapi.db.query('plugin::users-permissions.permission').create({ data: { action: permissionAction, role: role.id }, }); } } } } async function ensureDemoUser(strapi: Core.Strapi) { const existing = await strapi.db.query('plugin::users-permissions.user').findOne({ where: { email: DEMO_EMAIL }, }); if (existing) return; const authenticatedRole = await strapi.db.query('plugin::users-permissions.role').findOne({ where: { type: 'authenticated' }, }); if (!authenticatedRole) return; await strapi.plugin('users-permissions').service('user').add({ username: 'demo', email: DEMO_EMAIL, password: DEMO_PASSWORD, role: authenticatedRole.id, confirmed: true, provider: 'local', }); strapi.log.info(`Demo user created: ${DEMO_EMAIL} / ${DEMO_PASSWORD}`); } async function seedGlobal(strapi: Core.Strapi) { const existing = await strapi.documents('api::global.global').findFirst({}); const data = { siteName: 'Strapi Demo', siteDescription: 'A small demo site powered by Strapi and Vue.', heroTitle: 'Content managed in Strapi', heroSubtitle: 'Edit copy, blog posts, and member-only pages from the Strapi admin — no redeploy needed.', heroCtaLabel: 'Explore the blog', defaultSeo: { metaTitle: 'Strapi Demo', metaDescription: 'See what Strapi can do with a Vue frontend.', }, }; if (!existing) { await strapi.documents('api::global.global').create({ data }); } else { await strapi.documents('api::global.global').update({ documentId: existing.documentId, data, }); } } async function seedAbout(strapi: Core.Strapi) { const existing = await strapi.documents('api::about.about').findFirst({}); if (!existing) { await strapi.documents('api::about.about').create({ data: { title: 'About this demo', blocks: [ { __component: 'shared.rich-text', body: 'This site is a minimal showcase of Strapi as a headless CMS. Public pages load content from the Strapi REST API. The member area is protected — only logged-in users can fetch that content.', }, { __component: 'shared.quote', title: 'Why Strapi?', body: 'Give editors a friendly admin panel while developers keep building with their favorite frontend framework.', }, ], } as never, }); } } async function seedBlogPosts(strapi: Core.Strapi) { const posts = [ { title: 'What is a headless CMS?', slug: 'what-is-a-headless-cms', excerpt: 'Separate content from presentation and deliver it anywhere via APIs.', body: '

A headless CMS stores structured content and exposes it through APIs. Your Vue app (or mobile app, or another site) decides how to display it.

', }, { title: 'Why teams pick Strapi', slug: 'why-teams-pick-strapi', excerpt: 'Open source, customizable, and quick to set up for prototypes and production.', body: '

Strapi gives you content types, roles, media library, and plugins out of the box — perfect for demos like this one.

', }, { title: 'Connecting Vue to Strapi', slug: 'connecting-vue-to-strapi', excerpt: 'Use the REST API and JWT auth from your frontend.', body: '

This demo uses fetch with a JWT stored in localStorage. Public endpoints need no token; protected content sends Authorization: Bearer …

', }, ]; for (const post of posts) { const existing = await strapi.documents('api::blog-post.blog-post').findFirst({ filters: { slug: post.slug }, }); if (existing) { if (!existing.publishedAt) { await strapi.documents('api::blog-post.blog-post').publish({ documentId: existing.documentId, }); } continue; } await strapi.documents('api::blog-post.blog-post').create({ data: post, status: 'published', }); } const testPost = await strapi.documents('api::blog-post.blog-post').findFirst({ filters: { slug: 'test' }, }); if (testPost) { await strapi.documents('api::blog-post.blog-post').delete({ documentId: testPost.documentId, }); } } async function seedMemberArea(strapi: Core.Strapi) { const existing = await strapi.documents('api::member-area.member-area').findFirst({}); const data = { title: 'Welcome, member!', content: '

This page is loaded from Strapi’s Member Area single type. The Public role cannot read it — you had to log in so the API returns this content.

Try changing this text in the Strapi admin under Content Manager → Member Area.

', }; if (!existing) { await strapi.documents('api::member-area.member-area').create({ data }); } } export async function setupDemo(strapi: Core.Strapi) { await ensurePermissions(strapi, 'public', { 'api::global.global': ['find'], 'api::about.about': ['find'], 'api::blog-post.blog-post': ['find', 'findOne'], }); await ensurePermissions(strapi, 'authenticated', { 'api::member-area.member-area': ['find'], }); await ensureDemoUser(strapi); await seedGlobal(strapi); await seedAbout(strapi); await seedBlogPosts(strapi); await seedMemberArea(strapi); strapi.log.info('Demo content and permissions are ready.'); } export { DEMO_EMAIL, DEMO_PASSWORD };