some progress
This commit is contained in:
parent
ea70d64eb1
commit
f3381eb7ba
|
@ -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);
|
||||
|
|
|
@ -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": {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -3,8 +3,8 @@ import './404.css';
|
|||
import { getSettings, invariant } from '../../api';
|
||||
const settings = await getSettings();
|
||||
invariant(settings, "Settings not found");
|
||||
---
|
||||
|
||||
---
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>404 | {settings.title}</title>
|
||||
|
|
|
@ -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;
|
|
@ -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<typeof UserConfigSchema>
|
||||
export type GhostUserConfig = z.infer<typeof UserConfigSchema>
|
|
@ -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 = <T extends string>(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 }`);
|
||||
});
|
||||
});
|
|
@ -0,0 +1,72 @@
|
|||
import type { HookParameters } from "astro";
|
||||
import type { Plugin } from "vite";
|
||||
import { addVitePlugin } from "./add-vite-plugin.js";
|
||||
|
||||
const resolveVirtualModuleId = <T extends string>(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,
|
||||
});
|
||||
};
|
|
@ -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],
|
||||
},
|
||||
});
|
||||
};
|
|
@ -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<T extends string>(id: T): `\0${T}` {
|
||||
return `\0${id}`
|
||||
}
|
||||
|
||||
export function viteGhostCMS(
|
||||
opts: UserConfig,
|
||||
{ root, }: Pick<AstroConfig, 'root' | 'srcDir' | 'trailingSlash'> & {
|
||||
build: Pick<AstroConfig['build'], 'format'>
|
||||
}
|
||||
): NonNullable<ViteUserConfig['plugins']>[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<string, string>
|
||||
|
||||
/** 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]
|
||||
},
|
||||
}
|
||||
}
|
|
@ -6,4 +6,5 @@ export type {
|
|||
Settings, Tag, TagsIncludeSchema, Tier, TiersIncludeSchema
|
||||
} from './src/api';
|
||||
|
||||
|
||||
export type { ContentAPICredentials, APIVersions } from "@ts-ghost/core-api";
|
|
@ -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;
|
||||
}
|
|
@ -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"
|
||||
})],
|
||||
});
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue