astro-ghostcms/packages/astro-ghostcms/index.ts

269 lines
10 KiB
TypeScript

import type { AstroIntegration } from "astro";
import type { SafeParseError, SafeParseSuccess } from "astro/zod";
import { UserConfigSchema } from "./src/schemas";
import type { UserConfig } from "./types";
import ghostSitemap from "./src/integrations/sitemap";
import ghostRobots from "./src/integrations/robots-txt";
import { loadEnv } from 'vite';
import { fromZodError } from "zod-validation-error";
import { addVirtualImport } from "./src/utils/add-virtual-import";
export * from "./types.js"
/** INTERNAL CONSTANTS */
const IC = {
/** INTERNAL PACKAGE NAME */
PKG:'@matthiesenxyz/astro-ghostcms',
/** INTERNAL PACKAGE NAME (THEME) */
DT:'@matthiesenxyz/astro-ghostcms-theme-default',
/** INTERNAL STRING */
CHECK_ENV:"Checking for Environment Variables...",
/** SET ENV GRABBER MODE */
MODE: 'all',
/** SET ENV GRABBER PREFIXES */
PREFIXES: 'CONTENT_API',
/** INTERNAL STRING */
KEY_MISSING:"CONTENT_API_KEY Missing from .env/environment variables",
/** INTERNAL STRING */
URL_MISSING:"CONTENT_API_URL Missing from .env/environment variables or ghostURL under the integration settings in `astro.config.mjs`",
/** INTERNAL STRING */
IT:"Injecting Theme: ",
/** INTERNAL STRING */
IDR:"Injecting Default Routes...",
/** INTERNAL STRING */
ITR:"Injecting Default Theme Routes...",
/** INTERNAL STRING */
IRD:"Route Injection Disabled - Skipping...",
/** INTERNAL STRING */
IIR:"Injecting Integration Route: ",
/** INTERNAL STRING */
II:"Injecting Integration: ",
/** INTERNAL STRING */
AIbU:"Already Imported by User: ",
/** INTERNAL STRING */
CF:"Checking for ",
/** INTERNAL STRING */
CONFSETUPDONE:"GhostCMS Injection Complete. Integration is now ready.",
/** INTERNAL STRING */
F0FR: "Inject `/404` Route",
/** INTERNAL STRING */
RSS: "Injecting `/rss.xml` Route and `@astrojs/rss` Integration",
/** INTERNAL STRING */
NOURL: "No Ghost URL defined in User Config: Falling back to environment variables.",
/** INTERNAL STRING */
id404: "404 Injection Disabled",
/** INTERNAL STRING */
idRSS: "RSS Injection Disabled",
/** INTERNAL STRING */
satori_e: "Injecting Satori-OpenGraph Generator",
/** INTERNAL STRING */
satori_d: "Satori Injection disabled"
}
/** CONTENT API ENVIRONMENT VARIABLES */
const ENV = loadEnv(IC.MODE, process.cwd(), IC.PREFIXES);
/** Astro-GhostCMS Integration
* @ For more information and to see the docs check
* @see https://astro-ghostcms.xyz
*/
export default function GhostCMS(options: UserConfig): AstroIntegration {
return {
name: IC.PKG,
hooks: {
'astro:config:setup': async ({
injectRoute,
config,
updateConfig,
logger,
}) => {
// CHECK USER CONFIG AND MAKE AVAILBLE TO INTEGRATIONS
logger.info("Checking Config...")
const GhostUserConfig = UserConfigSchema.safeParse(options || {}) as SafeParseSuccess<UserConfig>;
if (!GhostUserConfig.success) {
const validationError = fromZodError((GhostUserConfig as unknown as SafeParseError<UserConfig>).error);
logger.error(`Config Error - ${ validationError }`);
throw Error("");
}
const GhostConfig = GhostUserConfig.data;
const GCD = {
theme: GhostConfig.theme,
dRI: GhostConfig.disableRouteInjection,
dCO: GhostConfig.disableConsoleOutput,
SM: GhostConfig.sitemap,
RTXT: GhostConfig.robotstxt,
gSite: GhostConfig.ghostURL,
dRSS: GhostConfig.disableRSS,
d404: GhostConfig.disable404,
dOG: GhostConfig.disableSatoriOG
}
// Check For ENV Variables
if(!GCD.dCO) {logger.info(IC.CHECK_ENV)}
// CHECK FOR API KEY
if(ENV.CONTENT_API_KEY === undefined){
logger.error(IC.KEY_MISSING);
throw IC.KEY_MISSING;
}
// CHECK FOR API URL
if(GCD.gSite === undefined){
logger.warn(IC.NOURL)
if(ENV.CONTENT_API_URL === undefined){
logger.error(IC.URL_MISSING);
throw IC.URL_MISSING;
}
}
if(!GCD.dRI){
// THEME SELECTOR
if ( GCD.theme === IC.DT ) {
if( !GCD.dCO ) { logger.info( IC.IT + IC.DT )}
} else {
if( !GCD.dCO ) { logger.info( IC.IT + GCD.theme )}
}
// INJECT ROUTES
// DEFAULT PROGRAM ROUTES
if( !GCD.dCO ) { logger.info( IC.IDR )}
if( !GCD.d404 ){
if( !GCD.dCO ) { logger.info( IC.F0FR )}
injectRoute({
pattern: '/404',
entrypoint: `${IC.PKG}/404.astro`
});
} else { if( !GCD.dCO ) { logger.info(IC.id404)}}
if( !GCD.dRSS ) {
if( !GCD.dCO ) { logger.info( IC.RSS )}
injectRoute({
pattern: '/rss.xml',
entrypoint: `${IC.PKG}/rss.xml.ts`
});
} else { if( !GCD.dCO ) { logger.info(IC.idRSS)}}
if ( !GCD.dOG ) {
if( !GCD.dCO ) { logger.info( IC.satori_e )}
injectRoute({
pattern: '/open-graph/[slug].png',
entrypoint: `${IC.PKG}/open-graph/[slug].png.ts`
});
injectRoute({
pattern: '/open-graph/index.png',
entrypoint: `${IC.PKG}/open-graph/index.png.ts`
});
injectRoute({
pattern: '/open-graph/authors.png',
entrypoint: `${IC.PKG}/open-graph/authors.png.ts`
});
injectRoute({
pattern: '/open-graph/author/[slug].png',
entrypoint: `${IC.PKG}/open-graph/author/[slug].png.ts`
});
injectRoute({
pattern: '/open-graph/tags.png',
entrypoint: `${IC.PKG}/open-graph/tags.png.ts`
});
injectRoute({
pattern: '/open-graph/tag/[slug].png',
entrypoint: `${IC.PKG}/open-graph/tag/[slug].png.ts`
});
} else { if( !GCD.dCO ) { logger.info( IC.satori_d )}}
// THEME ROUTES
if( !GCD.dCO ) { logger.info( IC.ITR )}
injectRoute({
pattern: '/',
entrypoint: `${GCD.theme}/index.astro`
});
injectRoute({
pattern: '/[slug]',
entrypoint: `${GCD.theme}/[slug].astro`
});
injectRoute({
pattern: '/tags',
entrypoint: `${GCD.theme}/tags.astro`
});
injectRoute({
pattern: '/authors',
entrypoint: `${GCD.theme}/authors.astro`
});
injectRoute({
pattern: '/tag/[slug]',
entrypoint: `${GCD.theme}/tag/[slug].astro`
});
injectRoute({
pattern: '/author/[slug]',
entrypoint: `${GCD.theme}/author/[slug].astro`
});
injectRoute({
pattern: '/archives/[...page]',
entrypoint: `${GCD.theme}/archives/[...page].astro`
});
} else { if( !GCD.dCO ) { logger.info( IC.IRD )} }
// IMPORT INTEGRATIONS & INTEGRATION ROUTES
const integrations = [...config.integrations];
// IMPORT INTEGRATION: @ASTROJS/SITEMAP
if( !GCD.dCO ) { logger.info( `${IC.CF}@astrojs/sitemap` )}
if (!integrations.find(({ name }) => name === '@astrojs/sitemap' )) {
if( !GCD.dCO ) { logger.info( `${IC.II}@astrojs/sitemap` )}
integrations.push(ghostSitemap(GCD.SM));
} else { if( !GCD.dCO ) { logger.info( `${IC.AIbU}@astrojs/sitemap` )}
};
// IMPORT INTEGRATION: ASTRO-ROBOTS-TXT
if( !GCD.dCO ) { logger.info( `${IC.CF}astro-robots-txt` )}
if (!integrations.find(({ name }) => name === 'astro-robots-txt' )) {
if( !GCD.dCO ) { logger.info( `${IC.II}astro-robots-txt` )}
integrations.push(ghostRobots(GCD.RTXT));
} else {
if( !GCD.dCO ) { logger.info( `${IC.AIbU}astro-robots-txt` )}
};
// FINAL STEP TO KEEP INTEGRATION LIVE
try { updateConfig( {
// UPDATE ASTRO CONFIG WITH INTEGRATED INTEGRATIONS
integrations: [
ghostSitemap(GCD.SM),
ghostRobots(GCD.RTXT)
],
vite: {
optimizeDeps: {
exclude: ["@resvg/resvg-js"],
}
}
// LOAD VITE AND SETUP viteGhostCMS Configs
}) } catch ( e ) {
logger.error( e as string );
throw e;
};
addVirtualImport({
name: 'virtual:@matthiesenxyz/astro-ghostcms/config',
content: `export default ${ JSON.stringify(GhostUserConfig.data) }`,
updateConfig
})
},
'astro:config:done': async ({ logger }) => {
logger.info(IC.CONFSETUPDONE);
}
}
}
}