Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions examples/_test/luxe.config.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
import { defineConfig } from "@luxecms/core";
// import { DocumentModule } from "@luxecms/core/modules";
import { DocumentModule } from "@luxecms/core/modules";

export default defineConfig({
postgresUrl: process.env.POSTGRES_URL ?? "",
astro: {},
modules: [
// DocumentModule({
// schemas: {},
// }),
DocumentModule({
schemas: {},
}),
],
});
2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"description": "The first truly composable headless CMS built for the modular web.",
"type": "module",
"scripts": {
"dev": "luxe-scripts dev --dts --astroPages=./core/src/server/astro/pages",
"dev": "luxe-scripts dev --dts --astroPagesPattern=**/src/**/pages/**",
"build": "luxe-scripts build --dts",
"test": "vitest"
},
Expand Down
21 changes: 11 additions & 10 deletions packages/core/src/core/cmd/dev.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { astroDev } from "../../server/index.js";
import type { LuxeConfig } from "../../types/index.js";
import type { LuxeConfig, LuxeRoute } from "../../types/index.js";
import {
type LuxeLog,
establishLuxeDatabaseConnection,
Expand All @@ -8,6 +8,12 @@ import {
} from "../index.js";

export const dev = async (config: LuxeConfig, logger: LuxeLog) => {
const routes: Array<LuxeRoute> = [];

const injectRoute = (route: LuxeRoute) => {
routes.push(route);
};

// this doesn't establish a usable connection
await initializeLuxeDatabase(config.postgresUrl);
logger.debug("Database initialized successfully");
Expand All @@ -16,14 +22,7 @@ export const dev = async (config: LuxeConfig, logger: LuxeLog) => {
if (module.hooks?.["luxe:server:init"]) {
await module.hooks["luxe:server:init"]({
logger,
// Don't want users to alter the module hooks, so we exclude them
config: {
...config,
modules: config.modules.map((m) => ({
...m,
hooks: undefined,
})),
},
injectRoute,
});
}
}
Expand All @@ -40,7 +39,9 @@ export const dev = async (config: LuxeConfig, logger: LuxeLog) => {

logger.debug("Initialized module `luxe:server:before` hooks successfully");

const devServer = await astroDev(config.astro);
const devServer = await astroDev(config.astro, {
routes,
});

for (const module of config.modules) {
if (module.hooks?.["luxe:server:ready"]) {
Expand Down
2 changes: 1 addition & 1 deletion packages/core/src/core/db/drizzle/model.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { pgTable, type PgTableWithColumns } from "drizzle-orm/pg-core";
import { type PgTableWithColumns, pgTable } from "drizzle-orm/pg-core";
import type { Model } from "../../../types/core/models/index.js";

export const defineModel = (modelName: string, fields: Model["fields"]) => {
Expand Down
9 changes: 0 additions & 9 deletions packages/core/src/modules/document/module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,17 +53,8 @@ export const DocumentModule = ({ schemas }: DocumentModuleProps): Module => {
"luxe:migrate:error": async (ctx) => {
ctx.logger.info("Document module migrate error hook!");
},

"luxe:server:init": async (ctx) => {
ctx.logger.info("Document module started!");
// ctx.routes.push({
// method: "GET",
// path: "/documents",
// handler: async (req, res) => {
// const documents = await ctx.db.query(`SELECT * FROM documents;`);
// res.status(200).json(documents);
// },
// });
},
"luxe:server:before": async (ctx) => {
ctx.logger.info("Document module server before hook!");
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { APIRoute } from "astro";

export const GET: APIRoute = async ({ params }) => {
return new Response("Hello, documents!");
};
26 changes: 15 additions & 11 deletions packages/core/src/server/astro/dev.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
import { dev } from "astro";
import { LuxeError } from "../../core/errors/index.js";
import type { LuxeConfig } from "../../types/index.js";
import { dirname, join } from "node:path";
import { fileURLToPath } from "node:url";
import { dev } from "astro";
import { LuxeError } from "../../core/errors/index.js";
import type { LuxeConfig, LuxeRoute } from "../../types/index.js";

export type LuxeAstroConfig = {
routes: Array<LuxeRoute>;
};

export const astroDev = async (
astroConfig: LuxeConfig["astro"],
luxeAstroConfig: LuxeAstroConfig,
): ReturnType<typeof dev> => {
try {
const currentDir = dirname(fileURLToPath(import.meta.url))
Expand All @@ -21,14 +26,13 @@ export const astroDev = async (
name: "luxe-server",
hooks: {
"astro:config:setup": async (config) => {
config.injectRoute({
pattern: "/admin/[...slug]",
entrypoint: join(currentDir, "pages", "admin.astro"),
});
config.injectRoute({
pattern: "/api/[...slug]",
entrypoint: join(currentDir, "pages", "api.ts"),
});
for (const route of luxeAstroConfig.routes) {
console.log(route);
config.injectRoute({
pattern: `${route.type}/${route.pattern}`,
entrypoint: route.entrypoint,
});
}
},
},
},
Expand Down
Empty file.
5 changes: 5 additions & 0 deletions packages/core/src/server/astro/pages/admin/index.astro
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---

---

<p>Hello, admin!</p>
Empty file.
5 changes: 5 additions & 0 deletions packages/core/src/server/astro/pages/api/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { APIRoute } from "astro";

export const GET: APIRoute = async ({ params }) => {
return new Response("status: 200");
};
5 changes: 5 additions & 0 deletions packages/core/src/server/astro/pages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import type { APIRoute } from "astro";

export const GET: APIRoute = async ({ params }) => {
return new Response("Hello, Luxe!");
};
6 changes: 6 additions & 0 deletions packages/core/src/types/core/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ export type LuxeConfig = {
};

export type LuxeUserConfig = Partial<LuxeConfig>;

export type LuxeRoute = {
type: "api" | "admin";
pattern: string;
entrypoint: string;
};
8 changes: 4 additions & 4 deletions packages/core/src/types/core/module/index.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { IncomingMessage, ServerResponse } from "node:http";
import type { AddressInfo } from "node:net";
import type { PgColumn, PgTableWithColumns } from "drizzle-orm/pg-core";
import type { FSWatcher } from "vite";
import type { LuxeError, LuxeLog, luxeQuery } from "../../../core/index.js";
import type { LuxeConfig } from "../config/index.js";
import type { LuxeConfig, LuxeRoute } from "../config/index.js";
import type { Model } from "../models/index.js";
import type { PgColumn, PgTableWithColumns } from "drizzle-orm/pg-core";

/*
* The reason we have a type for Module and a Zod type is so we can add comments to the types.
Expand Down Expand Up @@ -111,10 +111,10 @@ export type Module = {
*/
"luxe:server:init"?: ({
logger,
config,
injectRoute,
}: {
logger: LuxeLog;
config: LuxeConfig;
injectRoute: (route: LuxeRoute) => void;
}) => void | Promise<void>;

/**
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/zod/core/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import type { AstroUserConfig } from "astro";
import type postgres from "postgres";
import { z } from "zod";
import { LuxeErrors } from "../../../core/index.js";
import { baseModuleSchema, moduleSchema } from "../module/index.js";
import { moduleSchema } from "../module/index.js";

export const baseConfigSchema = z.object({
postgresUrl: z
Expand All @@ -16,7 +16,6 @@ export const baseConfigSchema = z.object({
astro: z
.custom<Omit<AstroUserConfig, "output" | "srcDir" | "root">>()
.optional(),
modules: z.array(baseModuleSchema),
});

export const configSchema = baseConfigSchema.extend({
Expand Down
3 changes: 1 addition & 2 deletions packages/core/src/zod/core/module/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import {
LuxeErrors,
type luxeQuery,
} from "../../../core/index.js";
import { baseConfigSchema } from "../config/index.js";
import { loggerSchema } from "../logger/index.js";

export const baseModuleSchema = z.object({
Expand Down Expand Up @@ -77,7 +76,7 @@ export const lifecycleHooksSchema = z.object({
.args(
z.object({
logger: loggerSchema,
config: baseConfigSchema,
injectRoute: z.function().args(z.any()).returns(z.void()),
}),
)
.returns(z.void().or(z.promise(z.void())))
Expand Down
89 changes: 60 additions & 29 deletions packages/luxe-scripts/cmd/build.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,21 @@
import { default as libPath } from "node:path";
import fs from "node:fs";
import { default as libPath } from "node:path";
import * as esbuild from "esbuild";
import { glob } from "glob";
import kleur from "kleur";
import { x } from "tinyexec";
import fg from "fast-glob";

async function build(...args) {
const isDev = args.includes("--dev");
const isVerbose = args.includes("--verbose");
const dts = args.includes("--dts");
const runServer = args.includes("--server");
const joinedArgs = args.join(" ");
const astroBuild = /--astroPages=[^ ]*/
const astroPattern = /--astroPagesPattern=[^ ]*/
.exec(joinedArgs)?.[0]
.trim()
.replace("--astroPages=", "");
.replace("--astroPagesPattern=", "");
const path = /--path=[^ ]*/
.exec(joinedArgs)?.[0]
.trim()
Expand Down Expand Up @@ -73,21 +74,36 @@ async function build(...args) {
return;
}

if (astroBuild) {
const astroPagesPath = libPath.join(
libPath.dirname(process.cwd()),
astroBuild,
);
if (!fs.existsSync(astroPagesPath)) {
log.error("Astro pages path does not exist");
} else {
const distPath = libPath.join(
libPath.dirname(process.cwd()),
astroBuild.split("/")[1],
"dist",
if (astroPattern) {
const files = await fg.glob([
`${astroPattern}/*.ts`,
`${astroPattern}/*.astro`,
]);
const distPath = libPath.join(process.cwd(), "dist", "pages");
if (!fs.existsSync(distPath)) {
await x("mkdir", ["-p", distPath]);
await x("rm", ["-rf", distPath]);
}

for (const file of files) {
const filePath = file.split("pages")[1];
// If file already exists in destination folder, show a warning
if (fs.existsSync(libPath.join(distPath, filePath))) {
log.warn(
`File ${libPath.join(
distPath,
filePath,
)} already exists in destination folder; overwriting`,
);
}
const distFolder = libPath.join(
distPath,
libPath.dirname(file).split("pages")[1],
);
await x("cp", ["-r", astroPagesPath, distPath]);
await x("mkdir", ["-p", distFolder]);
await x("cp", [file, distFolder]);
}

log.debug("Building Astro");
}

Expand Down Expand Up @@ -140,21 +156,36 @@ async function build(...args) {
...(path ? { entryPoints: [`${path}/**/*.ts`] } : {}),
}),
(async () => {
if (astroBuild) {
const astroPagesPath = libPath.join(
libPath.dirname(process.cwd()),
astroBuild,
);
if (!fs.existsSync(astroPagesPath)) {
log.error("Astro pages path does not exist");
} else {
const distPath = libPath.join(
libPath.dirname(process.cwd()),
astroBuild.split("/")[1],
"dist",
if (astroPattern) {
const files = await fg.glob([
`${astroPattern}/*.ts`,
`${astroPattern}/*.astro`,
]);
const distPath = libPath.join(process.cwd(), "dist", "pages");
if (!fs.existsSync(distPath)) {
await x("mkdir", ["-p", distPath]);
await x("rm", ["-rf", distPath]);
}

for (const file of files) {
const filePath = file.split("pages")[1];
// If file already exists in destination folder, show a warning
if (fs.existsSync(libPath.join(distPath, filePath))) {
log.warn(
`File ${libPath.join(
distPath,
filePath,
)} already exists in destination folder; overwriting`,
);
}
const distFolder = libPath.join(
distPath,
libPath.dirname(file).split("pages")[1],
);
await x("cp", ["-r", astroPagesPath, distPath]);
await x("mkdir", ["-p", distFolder]);
await x("cp", [file, distFolder]);
}

log.debug("Building Astro");
}
if (dts) {
Expand Down
33 changes: 17 additions & 16 deletions packages/luxe-scripts/package.json
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
{
"name": "luxe-scripts",
"version": "0.0.1",
"description": "Internal scripts for LuxeCMS",
"private": true,
"type": "module",
"main": "index.js",
"bin": {
"luxe-scripts": "./index.js"
},
"dependencies": {
"@types/glob": "^8.1.0",
"esbuild": "^0.24.0",
"glob": "^11.0.0",
"kleur": "^4.1.5",
"tinyexec": "^0.3.1"
}
"name": "luxe-scripts",
"version": "0.0.1",
"description": "Internal scripts for LuxeCMS",
"private": true,
"type": "module",
"main": "index.js",
"bin": {
"luxe-scripts": "./index.js"
},
"dependencies": {
"@types/glob": "^8.1.0",
"esbuild": "^0.24.0",
"fast-glob": "^3.3.3",
"glob": "^11.0.0",
"kleur": "^4.1.5",
"tinyexec": "^0.3.1"
}
}
Loading