@stacksjs/cms 0.71.2 → 0.72.0
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/authors/destroy.js +1 -0
- package/dist/authors/fetch.js +1 -0
- package/dist/authors/index.js +1 -0
- package/dist/authors/store.js +1 -0
- package/dist/authors/update.js +1 -0
- package/dist/blocks/defaults.js +1 -0
- package/dist/blocks/registry.js +1 -0
- package/dist/blocks/types.js +0 -0
- package/dist/build.d.ts +6 -0
- package/dist/build.js +876 -0
- package/dist/categorizables/destroy.js +1 -0
- package/dist/categorizables/fetch.js +1 -0
- package/dist/categorizables/index.js +1 -0
- package/dist/categorizables/store.js +1 -0
- package/dist/categorizables/update.js +1 -0
- package/dist/commentables/destroy.js +1 -0
- package/dist/commentables/fetch.js +1 -0
- package/dist/commentables/index.js +1 -0
- package/dist/commentables/store.js +1 -0
- package/dist/commentables/update.js +1 -0
- package/dist/database.js +1 -0
- package/dist/index.js +1 -3
- package/dist/menus/index.js +1 -0
- package/dist/pages/destroy.js +1 -0
- package/dist/pages/document.js +1 -0
- package/dist/pages/fetch.js +1 -0
- package/dist/pages/index.js +1 -0
- package/dist/pages/store.js +1 -0
- package/dist/pages/update.js +1 -0
- package/dist/posts/destroy.js +1 -0
- package/dist/posts/fetch.js +1 -0
- package/dist/posts/index.js +1 -0
- package/dist/posts/store.js +1 -0
- package/dist/posts/update.js +1 -0
- package/dist/public/fallback.js +1 -0
- package/dist/public/render.js +2 -0
- package/dist/public/resolve.js +1 -0
- package/dist/public/sanitize.js +1 -0
- package/dist/publish/index.js +1 -0
- package/dist/redirects/index.js +1 -0
- package/dist/results.js +1 -0
- package/dist/revisions/index.js +1 -0
- package/dist/taggables/destroy.js +1 -0
- package/dist/taggables/fetch.js +1 -0
- package/dist/taggables/index.js +1 -0
- package/dist/taggables/store.js +1 -0
- package/dist/taggables/update.js +1 -0
- package/dist/tests/setup.d.ts +5 -0
- package/dist/tests/setup.js +100 -0
- package/package.json +3 -3
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getDb}from"../database";export async function destroy(id){const db=await getDb();try{const result=await db.deleteFrom("authors").where("id","=",id).returningAll().executeTakeFirst();if(!result)throw Error(`Author with ID ${id} not found`);return result}catch(error){if(error instanceof Error)throw TypeError(`Author with ID ${id} not found`);throw error}}export async function destroyMany(ids){const db=await getDb();try{const result=await db.deleteFrom("authors").where("id","in",ids).execute();return Number(result)||0}catch(error){if(error instanceof Error)throw TypeError(`Failed to delete authors: ${error.message}`);throw error}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getDb}from"../database";export async function fetchById(id){return await(await getDb()).selectFrom("authors").where("id","=",id).selectAll().executeTakeFirst()}export async function fetchAll(){return await(await getDb()).selectFrom("authors").selectAll().execute()}export async function findByName(name){return await(await getDb()).selectFrom("authors").where("name","=",name).selectAll().executeTakeFirst()}export async function findByEmail(email){return await(await getDb()).selectFrom("authors").where("email","=",email).selectAll().executeTakeFirst()}export async function findByUuid(uuid){return await(await getDb()).selectFrom("authors").where("uuid","=",uuid).selectAll().executeTakeFirst()}export async function findByUserId(userId){return await(await getDb()).selectFrom("authors").where("user_id","=",userId).selectAll().executeTakeFirst()}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export{destroy}from"./destroy";export{fetchAll,fetchById,findByEmail,findByName,findByUserId,findByUuid}from"./fetch";export{findOrCreate,store}from"./store";export{update}from"./update";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{randomUUIDv7}from"bun";import{getDb}from"../database";import{resolveWrittenRow}from"../results";import{HttpError}from"@stacksjs/error-handling";import{formatDate,isUniqueViolation}from"@stacksjs/orm";export async function findOrCreate(data){const db=await getDb();try{const existingAuthor=await db.selectFrom("authors").where("email","=",data.email).orWhere("name","=",data.name).selectAll().executeTakeFirst();if(existingAuthor)return existingAuthor;let user=await db.selectFrom("users").where("email","=",data.email).selectAll().executeTakeFirst();if(!user){const result=await db.insertInto("users").values({email:data.email,name:data.name,password:randomUUIDv7(),uuid:randomUUIDv7(),created_at:formatDate(new Date),updated_at:formatDate(new Date)}).returningAll().executeTakeFirst();user=await resolveWrittenRow(db,"users",result);if(!user)throw Error("Failed to create user")}const authorData={user_id:user.id,name:data.name,email:data.email,created_at:formatDate(new Date),updated_at:formatDate(new Date)},result=await db.insertInto("authors").values(authorData).returningAll().executeTakeFirst(),author=await resolveWrittenRow(db,"authors",result);if(!author)throw Error("Failed to create author");return author}catch(error){if(error instanceof HttpError)throw error;if(isUniqueViolation(error))throw new HttpError(409,"An author with this email already exists");if(error instanceof Error)throw TypeError(`Failed to find or create author: ${error.message}`);throw error}}export async function store(data){const db=await getDb();try{const existingAuthor=await db.selectFrom("authors").where("email","=",data.email).orWhere("name","=",data.name).selectAll().executeTakeFirst();if(existingAuthor)return existingAuthor;const authorData={user_id:data.user_id,name:data.name,email:data.email,created_at:formatDate(new Date),updated_at:formatDate(new Date)},result=await db.insertInto("authors").values(authorData).returningAll().executeTakeFirst(),author=await resolveWrittenRow(db,"authors",result);if(!author)throw Error("Failed to create author");return author}catch(error){if(error instanceof HttpError)throw error;if(isUniqueViolation(error))throw new HttpError(409,"An author with this email already exists");if(error instanceof Error)throw TypeError(`Failed to find or create author: ${error.message}`);throw error}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{getDb}from"../database";import{fetchById}from"./fetch";import{isRow}from"../results";import{HttpError}from"@stacksjs/error-handling";import{formatDate,isUniqueViolation}from"@stacksjs/orm";export async function update(id,data){const db=await getDb();try{const updateData={...data,updated_at:formatDate(new Date)},result=await db.updateTable("authors").set(updateData).where("id","=",id).returningAll().executeTakeFirst();if(isRow(result))return result;return await fetchById(id)}catch(error){if(error instanceof HttpError)throw error;if(isUniqueViolation(error))throw new HttpError(409,"An author with this email already exists");if(error instanceof Error)throw TypeError(`Failed to update author: ${error.message}`);throw error}}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{schema}from"@stacksjs/validation";import{defineBlock,registerBlocks}from"./registry";const string=(max=1000)=>({validate:async(value)=>typeof value==="string"&&value.length<=max}),url=()=>({validate:async(value)=>{if(typeof value!=="string"||!value)return!1;if(value.startsWith("/"))return!0;try{const result=await schema.string().url().validate(value);return typeof result==="boolean"?result:Boolean(result.valid)}catch{return!1}}}),oneOf=(values)=>(value)=>typeof value==="string"&&values.includes(value)?!0:`must be one of ${values.join(", ")}`;export const defaultBlocks=[defineBlock({type:"hero",label:"Hero",component:"cms/blocks/hero",icon:"i-hugeicons-layout-top",schema:{heading:{rule:string(300),required:!0},subheading:{rule:string(600)},imageUrl:{rule:url()},ctaLabel:{rule:string(80)},ctaHref:{rule:url()},align:{rule:oneOf(["left","center"])}}}),defineBlock({type:"rich-text",label:"Text",component:"cms/blocks/rich-text",icon:"i-hugeicons-text",schema:{html:{rule:string(1e5),required:!0}}}),defineBlock({type:"image",label:"Image",component:"cms/blocks/image",icon:"i-hugeicons-image-01",schema:{src:{rule:url(),required:!0},alt:{rule:string(300),required:!0},caption:{rule:string(500)},width:{rule:oneOf(["content","wide","full"])}}}),defineBlock({type:"columns",label:"Columns",component:"cms/blocks/columns",icon:"i-hugeicons-layout-3-column",schema:{columns:{rule:(value)=>Array.isArray(value)&&value.length>=1&&value.length<=4&&value.every((col)=>col&&typeof col==="object"&&typeof col.html==="string")?!0:"1-4 columns, each with an html string",required:!0}}}),defineBlock({type:"cta",label:"Call to action",component:"cms/blocks/cta",icon:"i-hugeicons-cursor-pointer-02",schema:{heading:{rule:string(300),required:!0},body:{rule:string(1000)},buttonLabel:{rule:string(80),required:!0},buttonHref:{rule:url(),required:!0}}}),defineBlock({type:"embed",label:"Embed",component:"cms/blocks/embed",icon:"i-hugeicons-embed",schema:{src:{rule:url(),required:!0},title:{rule:string(300),required:!0},aspect:{rule:oneOf(["16:9","4:3","1:1"])}}}),defineBlock({type:"form",label:"Form",component:"cms/blocks/form",icon:"i-hugeicons-checklist",schema:{formUuid:{rule:(value)=>typeof value==="string"&&/^[0-9a-f-]{36}$/i.test(value)?!0:"must be a form uuid",required:!0}}})];export function registerDefaultBlocks(){registerBlocks(defaultBlocks)}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const REGISTRY_KEY=Symbol.for("stacks.cms.blockRegistry"),registry=globalThis[REGISTRY_KEY]??=new Map;export function defineBlock(definition){return definition}export function registerBlocks(definitions){for(const definition of definitions)registry.set(definition.type,definition)}export function getBlock(type){return registry.get(type)}export function allBlocks(){return[...registry.values()]}async function checkProp(definition,prop,value){const propDef=definition.schema[prop];if(!propDef)return`unknown prop "${prop}"`;const rule=propDef.rule;if(typeof rule==="function"){const result=rule(value);if(result===!0)return null;return typeof result==="string"?result:`invalid value for "${prop}"`}return await rule.validate(value)?null:`invalid value for "${prop}"`}export async function validateBlocks(input){if(!Array.isArray(input))return{ok:!1,errors:[{index:-1,message:"blocks must be an array"}]};const errors=[],blocks=[];for(const[index,raw]of input.entries()){if(!raw||typeof raw!=="object"||Array.isArray(raw)){errors.push({index,message:"block must be an object"});continue}const candidate=raw,type=typeof candidate.type==="string"?candidate.type:"",definition=type?getBlock(type):void 0;if(!definition){errors.push({index,type,message:type?`unknown block type "${type}"`:"block is missing a type"});continue}const id=typeof candidate.id==="string"&&candidate.id?candidate.id:crypto.randomUUID(),props=candidate.props&&typeof candidate.props==="object"&&!Array.isArray(candidate.props)?candidate.props:{};for(const[prop,value]of Object.entries(props)){const message=await checkProp(definition,prop,value);if(message)errors.push({index,type,prop,message})}for(const[prop,propDef]of Object.entries(definition.schema))if(propDef.required&&props[prop]===void 0)errors.push({index,type,prop,message:`missing required prop "${prop}"`});blocks.push({id,type,props})}return errors.length>0?{ok:!1,errors}:{ok:!0,blocks}}export function parseStoredBlocks(stored){let value=stored;if(typeof value==="string"&&value)try{value=JSON.parse(value)}catch{return[]}if(!Array.isArray(value))return[];return value.filter((block)=>!!block&&typeof block==="object"&&typeof block.type==="string")}
|
|
File without changes
|