diff --git a/packages/astro-ghostcms/index.ts b/packages/astro-ghostcms/index.ts
index 859f8f81..6228b76d 100644
--- a/packages/astro-ghostcms/index.ts
+++ b/packages/astro-ghostcms/index.ts
@@ -6,7 +6,7 @@ import ghostSitemap from "./src/integrations/sitemap";
import ghostRobots from "./src/integrations/robots-txt";
import { loadEnv } from 'vite';
import { fromZodError } from "zod-validation-error";
-import { viteGhostCMS } from "./src/virtual";
+import { addVirtualImport } from "./src/utils/add-virtual-import";
/** INTERNAL CONSTANTS */
const IC = {
@@ -23,7 +23,7 @@ const IC = {
/** INTERNAL STRING */
KEY_MISSING:"CONTENT_API_KEY Missing from .env/environment variables",
/** INTERNAL STRING */
- URL_MISSING:"CONTENT_API_URL Missing from .env/environment variables",
+ 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 */
@@ -55,7 +55,7 @@ const ENV = loadEnv(IC.MODE, process.cwd(), IC.PREFIXES);
* @ For more information and to see the docs check
* @see https://astro-ghostcms.xyz
*/
-export default function GhostCMS(options?: UserConfig): AstroIntegration {
+export default function GhostCMS(options: UserConfig): AstroIntegration {
return {
name: IC.PKG,
hooks: {
@@ -81,6 +81,7 @@ export default function GhostCMS(options?: UserConfig): AstroIntegration {
dCO: GhostConfig.disableConsoleOutput,
SM: GhostConfig.sitemap,
RTXT: GhostConfig.robotstxt,
+ gSite: GhostConfig.ghostURL
}
// Check For ENV Variables
@@ -93,8 +94,10 @@ export default function GhostCMS(options?: UserConfig): AstroIntegration {
}
// CHECK FOR API URL
if(ENV.CONTENT_API_URL === undefined){
- logger.error(IC.URL_MISSING);
- throw IC.URL_MISSING;
+ if(GCD.gSite === undefined){
+ logger.error(IC.URL_MISSING);
+ throw IC.URL_MISSING;
+ }
}
if(!GCD.dRI){
@@ -189,16 +192,17 @@ export default function GhostCMS(options?: UserConfig): AstroIntegration {
// UPDATE ASTRO CONFIG WITH INTEGRATED INTEGRATIONS
integrations: [ ghostSitemap( GCD.SM ), ghostRobots( GCD.RTXT ) ],
// LOAD VITE AND SETUP viteGhostCMS Configs
- vite: {
- plugins: [
- viteGhostCMS( GhostConfig, config )
- ]
- },
}) } 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);
diff --git a/packages/astro-ghostcms/package.json b/packages/astro-ghostcms/package.json
index d58d2bbd..ee9d250b 100644
--- a/packages/astro-ghostcms/package.json
+++ b/packages/astro-ghostcms/package.json
@@ -42,7 +42,8 @@
".env.demo",
"index.ts",
"tsconfig.json",
- "types.ts"
+ "types.ts",
+ "virtual.d.ts"
],
"exports": {
".": "./index.ts",
@@ -50,6 +51,7 @@
"./api-core": "./src/api/content-api",
"./404.astro": "./src/default-routes/404/404.astro",
"./rss.xml.ts": "./src/default-routes/rss.xml.ts",
+ "./config": "./src/integrations/virtual-config.ts",
"./types": "./types.ts"
},
"scripts": {
diff --git a/packages/astro-ghostcms/src/api/api-functions.ts b/packages/astro-ghostcms/src/api/api-functions.ts
index 0a826c4a..d53bb534 100644
--- a/packages/astro-ghostcms/src/api/api-functions.ts
+++ b/packages/astro-ghostcms/src/api/api-functions.ts
@@ -4,13 +4,17 @@ import { TSGhostContentAPI } from "./content-api";
// LOAD ENVIRONMENT VARIABLES
import { loadEnv } from 'vite';
+import config from "../integrations/virtual-config";
+
+const CONF_URL = config.ghostURL;
+
const {
CONTENT_API_KEY,
CONTENT_API_URL
} = loadEnv('all',process.cwd(),'CONTENT_');
const ghostApiKey = CONTENT_API_KEY;
-const ghostUrl = CONTENT_API_URL;
+const ghostUrl = CONF_URL?CONF_URL:CONTENT_API_URL;
const version = "v5.0";
const api = new TSGhostContentAPI(ghostUrl, ghostApiKey, version);
diff --git a/packages/astro-ghostcms/src/default-routes/404/404.astro b/packages/astro-ghostcms/src/default-routes/404/404.astro
index ef5f18f2..8489240a 100644
--- a/packages/astro-ghostcms/src/default-routes/404/404.astro
+++ b/packages/astro-ghostcms/src/default-routes/404/404.astro
@@ -3,8 +3,8 @@ import './404.css';
import { getSettings, invariant } from '../../api';
const settings = await getSettings();
invariant(settings, "Settings not found");
----
+---
404 | {settings.title}
diff --git a/packages/astro-ghostcms/src/integrations/virtual-config.ts b/packages/astro-ghostcms/src/integrations/virtual-config.ts
new file mode 100644
index 00000000..0aaf9a97
--- /dev/null
+++ b/packages/astro-ghostcms/src/integrations/virtual-config.ts
@@ -0,0 +1,6 @@
+import config from 'virtual:@matthiesenxyz/astro-ghostcms/config'
+import type { GhostUserConfig } from '../schemas'
+
+const UserConfig = config as GhostUserConfig
+
+export default UserConfig;
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/schemas/index.ts b/packages/astro-ghostcms/src/schemas/index.ts
index 8f4e930d..e8dd0846 100644
--- a/packages/astro-ghostcms/src/schemas/index.ts
+++ b/packages/astro-ghostcms/src/schemas/index.ts
@@ -3,27 +3,38 @@ import { SitemapSchema } from './sitemap';
import { RobotsTxtSchema } from './robots';
export const UserConfigSchema = z.object({
- /** OPTIONAL - Disable Route Injector
- * This option allows the user to disable the route injection system and utilize just the integraions other functions. Such as API, sitemap and robotstxt integrations. */
- disableRouteInjection: z.boolean().default(false),
- /** OPTIONAL - Allows the user to disable "info" console output */
- disableConsoleOutput: z.boolean().default(false),
- /** OPTIONAL - Theme Selector
- * This option allows the user to replace the included theme with an external npm module */
- theme: z.string().default('@matthiesenxyz/astro-ghostcms-theme-default'),
- /** OPTIONAL - astrojs/sitemap
- * This option allows the user to configure the included integration
- * Options shown are the availble options
- * REFERENCE https://docs.astro.build/en/guides/integrations-guide/sitemap
- */
- sitemap: SitemapSchema.optional(),
- /** OPTIONAL - astro-robots-txt
- * This option allows the user to configure the included integration
- * Options shown are the availble options
- * REFERENCE https://www.npmjs.com/package/astro-robots-txt#configuration
- */
- robotstxt: RobotsTxtSchema.optional(),
- });
+ /** OPTIONAL - Either set the URL in your .env or put it here
+ * @example
+ * // https://astro.build/config
+ * export default defineConfig({
+ * site: "https://demo.astro-ghostcms.xyz/",
+ * integrations: [ghostcms({
+ * ghostURL: "https://ghostdemo.matthiesen.xyz"
+ * })],
+ * }); */
+ ghostURL: z.string().optional(),
+ /** OPTIONAL - Disable Route Injector
+ * This option allows the user to disable the route injection system and utilize just the integraions other functions. Such as API, sitemap and robotstxt integrations. */
+ disableRouteInjection: z.boolean().default(false),
+ /** OPTIONAL - Allows the user to disable "info" console output */
+ disableConsoleOutput: z.boolean().default(false),
+ /** OPTIONAL - Theme Selector
+ * This option allows the user to replace the included theme with an external npm module */
+ theme: z.string().default('@matthiesenxyz/astro-ghostcms-theme-default'),
+ /** OPTIONAL - astrojs/sitemap
+ * This option allows the user to configure the included integration
+ * Options shown are the availble options
+ * REFERENCE https://docs.astro.build/en/guides/integrations-guide/sitemap
+ */
+ sitemap: SitemapSchema.optional(),
+ /** OPTIONAL - astro-robots-txt
+ * This option allows the user to configure the included integration
+ * Options shown are the availble options
+ * REFERENCE https://www.npmjs.com/package/astro-robots-txt#configuration
+ */
+ robotstxt: RobotsTxtSchema.optional(),
+});
/** USER CONFIGURATION SCHEMA */
-export type UserConfig = z.infer
\ No newline at end of file
+export type UserConfig = z.infer
+export type GhostUserConfig = z.infer
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/utils/add-virtual-import.test.ts b/packages/astro-ghostcms/src/utils/add-virtual-import.test.ts
new file mode 100644
index 00000000..e27475b7
--- /dev/null
+++ b/packages/astro-ghostcms/src/utils/add-virtual-import.test.ts
@@ -0,0 +1,60 @@
+import { afterEach, type Mock, describe, expect, test, vi } from "vitest";
+import { addVirtualImport } from "./add-virtual-import.js";
+import { addVitePlugin } from "./add-vite-plugin.js";
+
+vi.mock('./add-vite-plugin')
+
+const pluginNameStub = (name: T): `vite-plugin-${T}` => `vite-plugin-${name}`
+
+describe("add-virtual-import", () => {
+ const name = "test-module";
+ const content = "export default {}";
+
+ afterEach(() => {
+ vi.clearAllMocks();
+ });
+
+ test("It should call `addVitePlugin`", () => {
+ const updateConfig = vi.fn();
+
+ addVirtualImport({
+ name,
+ content,
+ updateConfig,
+ });
+
+ expect(addVitePlugin).toHaveBeenCalled();
+ });
+
+ test("`addVitePlugin` should get called with the correct plugin name", () => {
+ const updateConfig = vi.fn();
+
+ addVirtualImport({
+ name,
+ content,
+ updateConfig,
+ });
+
+ const expectedName = pluginNameStub(name)
+
+ const { plugin } = (addVitePlugin as Mock).mock.lastCall[0]
+
+ expect(plugin.name).toEqual(expectedName);
+ });
+
+ test("Virtual module should resolve correct name", () => {
+ const updateConfig = vi.fn();
+
+ addVirtualImport({
+ name,
+ content,
+ updateConfig,
+ });
+
+ const { plugin } = (addVitePlugin as Mock).mock.lastCall[0]
+
+ const resolvedVirtualModuleId = plugin.resolveId(name)
+
+ expect(resolvedVirtualModuleId).toEqual(`\0${ name }`);
+ });
+});
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/utils/add-virtual-import.ts b/packages/astro-ghostcms/src/utils/add-virtual-import.ts
new file mode 100644
index 00000000..54306799
--- /dev/null
+++ b/packages/astro-ghostcms/src/utils/add-virtual-import.ts
@@ -0,0 +1,72 @@
+import type { HookParameters } from "astro";
+import type { Plugin } from "vite";
+import { addVitePlugin } from "./add-vite-plugin.js";
+
+const resolveVirtualModuleId = (id: T): `\0${T}` => {
+ return `\0${id}`;
+};
+
+const createVirtualModule = (name: string, content: string): Plugin => {
+ const pluginName = `vite-plugin-${name}`;
+
+ return {
+ name: pluginName,
+ resolveId(id) {
+ if (id === name) {
+ return resolveVirtualModuleId(id);
+ }
+ },
+ load(id) {
+ if (id === resolveVirtualModuleId(name)) {
+ return content;
+ }
+ },
+ };
+};
+
+/**
+ * Creates a Vite virtual module and updates the Astro config.
+ * Virtual imports are useful for passing things like config options, or data computed within the integration.
+ *
+ * @param {object} params
+ * @param {string} params.name
+ * @param {string} params.content
+ * @param {import("astro").HookParameters<"astro:config:setup">["updateConfig"]} params.updateConfig
+ *
+ * @see https://astro-integration-kit.netlify.app/utilities/add-virtual-import/
+ *
+ * @example
+ * ```ts
+ * // my-integration/index.ts
+ * import { addVirtualImport } from "astro-integration-kit";
+ *
+ * addVirtualImport(
+ * name: 'virtual:my-integration/config',
+ * content: `export default ${ JSON.stringify({foo: "bar"}) }`,
+ * updateConfig
+ * );
+ * ```
+ *
+ * This is then readable anywhere else in your integration:
+ *
+ * ```ts
+ * // myIntegration/src/component/layout.astro
+ * import config from "virtual:my-integration/config";
+ *
+ * console.log(config.foo) // "bar"
+ * ```
+ */
+export const addVirtualImport = ({
+ name,
+ content,
+ updateConfig,
+}: {
+ name: string;
+ content: string;
+ updateConfig: HookParameters<"astro:config:setup">["updateConfig"];
+}) => {
+ addVitePlugin({
+ plugin: createVirtualModule(name, content),
+ updateConfig,
+ });
+};
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/utils/add-vite-plugin.ts b/packages/astro-ghostcms/src/utils/add-vite-plugin.ts
new file mode 100644
index 00000000..7571dc0b
--- /dev/null
+++ b/packages/astro-ghostcms/src/utils/add-vite-plugin.ts
@@ -0,0 +1,34 @@
+import type { HookParameters } from "astro";
+import type { PluginOption } from "vite";
+
+/**
+ * Adds a [vite plugin](https://vitejs.dev/guide/using-plugins) to the
+ * Astro config.
+ *
+ * @param {Params} params
+ * @param {import("vite").Plugin} params.plugin
+ * @param {import("astro").HookParameters<"astro:config:setup">["updateConfig"]} params.updateConfig
+ *
+ * @see https://astro-integration-kit.netlify.app/utilities/add-vite-plugin/
+ *
+ * @example
+ * ```ts
+ * addVitePlugin({
+ * plugin,
+ * updateConfig
+ * })
+ * ```
+ */
+export const addVitePlugin = ({
+ plugin,
+ updateConfig,
+}: {
+ plugin: PluginOption;
+ updateConfig: HookParameters<"astro:config:setup">["updateConfig"];
+}) => {
+ updateConfig({
+ vite: {
+ plugins: [plugin],
+ },
+ });
+};
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/virtual/index.ts b/packages/astro-ghostcms/src/virtual/index.ts
deleted file mode 100644
index f7481af7..00000000
--- a/packages/astro-ghostcms/src/virtual/index.ts
+++ /dev/null
@@ -1,41 +0,0 @@
-import type { AstroConfig, ViteUserConfig } from 'astro'
-import { resolve } from 'node:path';
-import { fileURLToPath } from 'node:url';
-import type { UserConfig } from '../schemas';
-
-function resolveVirtualModuleId(id: T): `\0${T}` {
- return `\0${id}`
-}
-
-export function viteGhostCMS(
- opts: UserConfig,
- { root, }: Pick & {
- build: Pick
- }
-): NonNullable[number] {
- const resolveId = (id: string) =>
- JSON.stringify(id.startsWith('.') ? resolve(fileURLToPath(root), id) : id);
-
- const modules = {
- 'virtual:@matthiesenxyz/astro-ghostcms/config': `export default ${ JSON.stringify(opts) }`
- } satisfies Record
-
- /** Mapping names prefixed with `\0` to their original form. */
- const resolutionMap = Object.fromEntries(
- (Object.keys(modules) as (keyof typeof modules)[]).map((key) => [
- resolveVirtualModuleId(key),
- key,
- ])
- )
-
- return {
- name: 'vite-plugin-matthiesenxyz-astro-ghostcms-user-config',
- resolveId(id): string | undefined {
- if (id in modules) return resolveVirtualModuleId(id)
- },
- load(id): string | undefined {
- const resolution = resolutionMap[id]
- if (resolution) return modules[resolution]
- },
- }
-}
\ No newline at end of file
diff --git a/packages/astro-ghostcms/types.ts b/packages/astro-ghostcms/types.ts
index 9154f8c0..fa8c9574 100644
--- a/packages/astro-ghostcms/types.ts
+++ b/packages/astro-ghostcms/types.ts
@@ -6,4 +6,5 @@ export type {
Settings, Tag, TagsIncludeSchema, Tier, TiersIncludeSchema
} from './src/api';
+
export type { ContentAPICredentials, APIVersions } from "@ts-ghost/core-api";
\ No newline at end of file
diff --git a/packages/astro-ghostcms/src/virtual/virtual.d.ts b/packages/astro-ghostcms/virtual.d.ts
similarity index 57%
rename from packages/astro-ghostcms/src/virtual/virtual.d.ts
rename to packages/astro-ghostcms/virtual.d.ts
index 9cfe74a2..0f7bbcd5 100644
--- a/packages/astro-ghostcms/src/virtual/virtual.d.ts
+++ b/packages/astro-ghostcms/virtual.d.ts
@@ -1,4 +1,4 @@
declare module 'virtual:@matthiesenxyz/astro-ghostcms/config' {
- const Config: import('../schemas').UserConfig;
+ const Config: import('./src/schemas/index').GhostUserConfig;
export default Config;
}
\ No newline at end of file
diff --git a/playground/astro.config.mjs b/playground/astro.config.mjs
index a0eb4cbc..8890e5d8 100644
--- a/playground/astro.config.mjs
+++ b/playground/astro.config.mjs
@@ -4,5 +4,7 @@ import ghostcms from "@matthiesenxyz/astro-ghostcms";
// https://astro.build/config
export default defineConfig({
site: "https://demo.astro-ghostcms.xyz/",
- integrations: [ghostcms()],
+ integrations: [ ghostcms({
+ ghostURL: "https://ghostdemo.matthiesen.xyz"
+ })],
});
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index 701c781f..678d6d4e 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -24,11 +24,11 @@ importers:
demo:
dependencies:
'@matthiesenxyz/astro-ghostcms':
- specifier: 3.1.3
+ specifier: 3.1.4
version: link:../packages/astro-ghostcms
'@matthiesenxyz/astro-ghostcms-theme-default':
specifier: 0.1.3
- version: link:../packages/astro-ghostcms-theme-default
+ version: 0.1.3(astro@4.2.4)(typescript@5.3.3)
astro:
specifier: ^4.2.4
version: 4.2.4(sass@1.70.0)(typescript@5.3.3)
@@ -120,7 +120,7 @@ importers:
version: link:../astro-ghostcms
astro:
specifier: ^4.2.1
- version: 4.2.3(typescript@5.3.3)
+ version: 4.2.3(sass@1.70.0)(typescript@5.3.3)
astro-font:
specifier: ^0.0.77
version: 0.0.77
@@ -128,6 +128,9 @@ importers:
'@astrojs/check':
specifier: ^0.4.1
version: 0.4.1(prettier-plugin-astro@0.13.0)(prettier@3.2.4)(typescript@5.3.3)
+ sass:
+ specifier: ^1.70.0
+ version: 1.70.0
typescript:
specifier: ^5.3.3
version: 5.3.3
@@ -1405,6 +1408,53 @@ packages:
read-yaml-file: 1.1.0
dev: true
+ /@matthiesenxyz/astro-ghostcms-theme-default@0.1.3(astro@4.2.4)(typescript@5.3.3):
+ resolution: {integrity: sha512-ZWo5L5ZSYTWYcQjauDEQBiyH2nqnmoBs8F/cCttRzE6ms5LrWQ65nMuWQQomp5j/kMBBn2upVIi6bEUgoCxt6w==}
+ peerDependencies:
+ astro: ^4.2.1
+ dependencies:
+ '@matthiesenxyz/astro-ghostcms': 3.1.4(astro@4.2.4)(typescript@5.3.3)
+ astro: 4.2.4(sass@1.70.0)(typescript@5.3.3)
+ astro-font: 0.0.77
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - typescript
+ dev: false
+
+ /@matthiesenxyz/astro-ghostcms@3.1.4(astro@4.2.4)(typescript@5.3.3):
+ resolution: {integrity: sha512-8jXKKG8IhL1M97+p4rjh8gW+6WM0uzQQEA6SARn68HtB3w7rek3rzfnbf/OsXrP9H8LHgYqAUFvZ1AYMWYVnJw==}
+ peerDependencies:
+ astro: ^4.2.3
+ dependencies:
+ '@astrojs/rss': 4.0.3
+ '@astrojs/sitemap': 3.0.5
+ '@matthiesenxyz/astro-ghostcms-theme-default': 0.1.3(astro@4.2.4)(typescript@5.3.3)
+ '@ts-ghost/core-api': 5.1.2
+ astro: 4.2.4(sass@1.70.0)(typescript@5.3.3)
+ astro-robots-txt: 1.0.0
+ vite: 5.0.12(sass@1.70.0)
+ vite-tsconfig-paths: 4.3.1(typescript@5.3.3)(vite@5.0.12)
+ zod: 3.22.4
+ zod-validation-error: 3.0.0(zod@3.22.4)
+ transitivePeerDependencies:
+ - '@types/node'
+ - less
+ - lightningcss
+ - sass
+ - stylus
+ - sugarss
+ - supports-color
+ - terser
+ - typescript
+ dev: false
+
/@mdx-js/mdx@3.0.0:
resolution: {integrity: sha512-Icm0TBKBLYqroYbNW3BPnzMGn+7mwpQOK310aZ7+fkCtiU3aqv2cdcX+nd0Ydo3wI5Rx8bX2Z2QmGb/XcAClCw==}
dependencies:
@@ -2176,7 +2226,7 @@ packages:
zod: 3.22.4
dev: false
- /astro@4.2.3(typescript@5.3.3):
+ /astro@4.2.3(sass@1.70.0)(typescript@5.3.3):
resolution: {integrity: sha512-6bfSogmcwMdaTRAxuhJ7aISGin/T3ovI/69JWPRYOHBkPZxA/EfsNQOI2TiRHFJSF9XtoMnFlgvT+iYapkhOwg==}
engines: {node: '>=18.14.1', npm: '>=6.14.0'}
hasBin: true