UNPKG

@npio/cli

Version:

A free visual website editor, powered with your own SolidJS components.

602 lines (567 loc) 17.5 kB
import { confirm, group, intro, outro, spinner } from "@clack/prompts"; import { createId } from "@paralleldrive/cuid2"; import { rgbVal } from "nitropage/internals"; import { hashPassword, useDatabase } from "nitropage/server"; import c from "picocolors"; import type sade from "sade"; export const demoCommands = function (prog: sade.Sade) { prog .command("demo") .describe( "Cleans up the database, media and fonts and seeds the database with example data", ) .option( "--force, -f", "Don't show a confirmation dialog before deleting everything", ) .action(async function ({ force }) { intro("Demo mode preparation"); if (!force) { const result = await group( { ask1: () => confirm({ message: `Do you really wanna ${c.bold( "delete all data", )} and replace it with example data?`, initialValue: false, }), ask2: () => confirm({ message: `Are you 100% sure?`, initialValue: false, }), }, { onCancel(opts) { outro("That was close!"); process.exit(); }, }, ); if (!result.ask1 || !result.ask2) { outro("That was close!"); process.exit(); } } const s = spinner(); s.start("Cleaning up all existing data"); const client = useDatabase(); // Delete tables with no dependencies await client.nitroElement.deleteMany(); await client.nitroElementSlot.deleteMany(); await client.nitroFontFace.deleteMany(); await client.nitroLayoutSlot.deleteMany(); await client.nitroMedia.deleteMany(); await client.nitroPageRevision.deleteMany(); await client.nitroPreset.deleteMany(); await client.nitroSetting.deleteMany(); // Delete all other tables await client.nitroElementHistory.deleteMany(); // After NitroElement await client.nitroFont.deleteMany(); // After NitroFontFace await client.nitroPage.deleteMany(); // After NitroLayoutSlot, NitroPageRevision, NitroElementHistory await client.nitroProject.deleteMany(); // After NitroPage await client.nitroUser.deleteMany(); // After NitroProject s.stop("Cleanup done."); s.start("Seeding example data"); const hashedPassword = await hashPassword(`1234`); const user = await client.nitroUser.create({ data: { email: "demo@example.com", username: "admin", password: hashedPassword, admin: true, }, }); const project = await client.nitroProject.create({ data: { title: "Demo", domain: "", publicId: createId(), }, }); const colors = { white: { css: "", rgb: { r: 255, g: 255, b: 255 }, id: "rp33x4o7czcumt74fu529o2l", }, accent: { css: "", rgb: { r: 68, g: 21, b: 112 }, id: "ozkonvsv3eeb839w3quu70sn", }, accent2: { css: "", rgb: { r: 145, g: 71, b: 237 }, id: "w4d4isw49js3waaiwxsdi9fw", }, accent3: { css: "", rgb: { r: 181, g: 144, b: 249 }, id: "fgytns2iopaiwk0w63lze1fw", }, slate: { css: "", rgb: { r: 229, g: 231, b: 235 }, id: "ajwmhd2ql2shvwue35fqz0bv", }, }; for (const color of Object.keys(colors)) { let c = color as keyof typeof colors; colors[c].css = rgbVal(colors[c].rgb)!; } await client.nitroSetting.create({ data: { name: "colors", value: JSON.stringify({ [colors.white.id]: { light: colors.white.rgb }, [colors.accent.id]: { light: colors.accent.rgb }, [colors.accent2.id]: { light: colors.accent2.rgb }, [colors.accent3.id]: { light: colors.accent3.rgb }, [colors.slate.id]: { light: colors.slate.rgb }, }), project: { connect: { id: project.id, }, }, }, }); const INTRO_BUTTON_DATA = ({ href: url, text, icon, }: { href: string; text: string; icon: string; }) => ({ link: { override: true, value: { content: url } }, iconSvg: { override: true, value: { content: icon, }, }, content: { override: true, value: { content: `<span class="block">${text}</span>` }, }, size: { override: true, value: { selected: "lg" } }, textColor: { override: true, value: colors.accent, }, bgColor: { override: true, value: { ...colors.white, alpha: 0.9, }, }, bgColorHover: { override: true, value: colors.white, }, }); const HEADER_BLUEPRINT = "pynj0gs5qlwztg60j596bkgm"; const FOOTER_BLUEPRINT = "b0ailno63q17afjl6wr83xz1"; const SECTION_BLUEPRINT = "usedfsqfwa4g4aedh2wjkqkp"; const INTRO_BLUEPRINT = "ae8f3r696oky0tpbdlu1accp"; const BUTTON_BLUEPRINT = "m2vqbubuu61s8cu8l9z3cllu"; const CONTAINER_BLUEPRINT = "oyf5ut4svjmudc6kl6hhm69h"; const HEADING_BLUEPRINT = "zk7vp8rahquyz034aec4h2on"; const FEATURE_BLUEPRINT = "vt5a4mjfbbbzn5d6y08pho35"; const NARROW_BLUEPRINT = "ba0jpedvc304eoz55l5mkgpu"; const MARKDOWN_BLUEPRINT = "zcvngz3018ov60rtf8kdgqgs"; const [titleFont, bodyFont, serifFont] = await client.nitroFont.createManyAndReturn({ data: [ { publicId: createId(), family: "Jost", cdn: true, projectId: project.id, }, { publicId: createId(), family: "Barlow", cdn: true, projectId: project.id, }, { publicId: createId(), family: "Noto Serif", cdn: true, projectId: project.id, }, ], }); await client.nitroSetting.create({ data: { name: "defaultFont", value: JSON.stringify(bodyFont.id), projectId: project.id, }, }); await client.nitroSetting.create({ data: { name: "rteTextColors", value: JSON.stringify({ dyn1: colors.accent2 }), projectId: project.id, }, }); await client.nitroSetting.create({ data: { name: "blueprintDefaults", value: JSON.stringify({ [HEADER_BLUEPRINT]: { title: { value: { content: "Nitropage Demo", }, }, titleFont: { value: { id: titleFont.id, publicId: titleFont.publicId, }, }, titleColor: { value: colors.white, }, linkColor: { value: colors.white, }, overlayColor: { value: colors.accent2, }, links: { value: { byId: { vvvkcdop6jbb9nwb3ifb7rhs: { url: { content: "/" }, text: { content: '<span class="block">Home</span>' }, }, plohqpgsy6hgqhlrjiz8j0jd: { url: { content: "https://nitropage.org" }, text: { content: '<span class="block">Visit nitropage.org</span>', }, }, }, ids: ["vvvkcdop6jbb9nwb3ifb7rhs", "plohqpgsy6hgqhlrjiz8j0jd"], }, }, }, [FOOTER_BLUEPRINT]: { title: { value: { content: "Nitropage Demo" }, }, titleFont: { value: { id: titleFont.id, publicId: titleFont.publicId, }, }, copyrightPrefix: { value: { content: "Nitropage" }, }, copyrightSuffix: { value: { content: "" }, }, }, [INTRO_BLUEPRINT]: { titleFont: { value: { id: titleFont.id, publicId: titleFont.publicId, }, }, }, [CONTAINER_BLUEPRINT]: { topPadding: { value: { selected: "lg" } }, bottomPadding: { value: { selected: "lg" } }, }, [HEADING_BLUEPRINT]: { font: { value: { id: titleFont.id, publicId: titleFont.publicId, }, }, size: { value: { selected: "lg" }, override: true }, }, [MARKDOWN_BLUEPRINT]: { headingFont: { value: { id: titleFont.id, publicId: titleFont.publicId, }, }, }, }), project: { connect: { id: project.id, }, }, }, }); const page = await client.nitroPage.create({ data: { project: { connect: { id: project.id, }, }, }, }); const revision = await client.nitroPageRevision.create({ data: { title: "Nitropage Demo", urlPath: "/", publishedPage: { connect: { id: page.id, }, }, page: { connect: { id: page.id, }, }, }, }); const createSlot = async (key: string, revision?: any) => { return await client.nitroElementSlot.create({ data: { key, parentPageRevision: revision ? { connect: { id: revision.id, }, } : undefined, }, }); }; const slotPositions = {} as Record<string, number>; const createElement = async function ( blueprint: string, data: any, parentSlot: { id: string }, slot?: { id: string }, ) { slotPositions[parentSlot.id] ??= 0; const position = slotPositions[parentSlot.id]++; return await client.nitroElement.create({ data: { blueprintId: blueprint, position, data: JSON.stringify(data), page: { connect: { id: revision.id, }, }, parentSlot: { connect: { id: parentSlot.id, }, }, slots: slot ? { connect: { id: slot.id, }, } : undefined, history: { create: { page: { connect: { id: page.id, }, }, }, }, }, }); }; const mainSlot = await createSlot("default", revision); const introSectionSlot = await createSlot("default"); const introSlot = await createSlot("default"); await createElement(HEADER_BLUEPRINT, {}, mainSlot); await createElement( SECTION_BLUEPRINT, { backgroundColor: { value: colors.accent, override: true, }, zIndex: { value: { content: 1 }, override: true }, shadow: { value: { selected: "md" }, override: true }, bottomMask: { value: { selected: "wavy3" }, override: true }, }, mainSlot, introSectionSlot, ); await createElement( INTRO_BLUEPRINT, { title: { value: { content: '<span class="block">Nitropage Demo</span>', }, override: true, }, titleColor: { value: colors.white, override: true, }, descriptionColor: { value: colors.accent3, override: true, }, description: { value: { content: '<span class="block">Welcome to the Nitropage demo instance!</span><span class="block">Try it out without hesitation, completely for free.</span>', }, override: true, }, }, introSectionSlot, introSlot, ); await createElement( BUTTON_BLUEPRINT, INTRO_BUTTON_DATA({ text: "Open the Administration", href: `/admin/project/${project.id}`, icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-login"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M15 8v-2a2 2 0 0 0 -2 -2h-7a2 2 0 0 0 -2 2v12a2 2 0 0 0 2 2h7a2 2 0 0 0 2 -2v-2" /><path d="M21 12h-13l3 -3" /><path d="M11 15l-3 -3" /></svg>', }), introSlot, ); await createElement( BUTTON_BLUEPRINT, INTRO_BUTTON_DATA({ text: "Edit this page", href: `/admin/editor/${page.id}`, icon: '<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-tabler icons-tabler-outline icon-tabler-edit"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M7 7h-1a2 2 0 0 0 -2 2v9a2 2 0 0 0 2 2h9a2 2 0 0 0 2 -2v-1" /><path d="M20.385 6.585a2.1 2.1 0 0 0 -2.97 -2.97l-8.415 8.385v3h3l8.385 -8.415z" /><path d="M16 5l3 3" /></svg>', }), introSlot, ); const featureSectionSlot = await createSlot("default"); await createElement( SECTION_BLUEPRINT, { backgroundColor: { value: colors.slate, override: true, }, }, mainSlot, featureSectionSlot, ); const featureContainerSlot = await createSlot("default"); await createElement( CONTAINER_BLUEPRINT, { topPadding: { value: { selected: "xl" }, override: true }, }, featureSectionSlot, featureContainerSlot, ); await createElement( HEADING_BLUEPRINT, { content: { value: { content: '<span class="block">A <strong class="ql-color-g1"><em>hairy</em></strong> headline</span>', }, override: true, }, }, featureContainerSlot, ); await createElement( FEATURE_BLUEPRINT, { textColor: { override: true, value: colors.accent, }, iconColor: { value: colors.accent2, override: true, }, iconBackgroundColor: { value: colors.white, override: true, }, }, featureContainerSlot, ); const markdownSectionSlot = await createSlot("default"); await createElement( SECTION_BLUEPRINT, { backgroundColor: { value: colors.accent3, override: true, }, shadow: { value: { selected: "md" }, override: true }, }, mainSlot, markdownSectionSlot, ); const markdownContainerSlot = await createSlot("default"); await createElement( CONTAINER_BLUEPRINT, {}, markdownSectionSlot, markdownContainerSlot, ); const markdownNarrowSlot = await createSlot("default"); await createElement( NARROW_BLUEPRINT, {}, markdownContainerSlot, markdownNarrowSlot, ); await createElement( MARKDOWN_BLUEPRINT, { content: { value: { content: `> There is only one corner of the universe you can be certain of improving, and that's your own self. > > &mdash; Aldous Huxley`, }, override: true, }, font: { value: { id: serifFont.id, publicId: serifFont.publicId, }, override: true, }, borderColor: { value: colors.accent, override: true, }, }, markdownNarrowSlot, ); await createElement(FOOTER_BLUEPRINT, {}, mainSlot); s.stop("Seeding finished."); outro("Everything done."); }); };