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
4 changes: 2 additions & 2 deletions packages/content-engine/content/createContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ export async function defaultCreateUploadsProcessor(
* ```
*/
export async function createContent<
TData extends Record<string, unknown>,
TData,
TIndexValue,
TKey extends Key,
>(options: CreateContentOptions<TData, TIndexValue, TKey>): Promise<void> {
Expand Down Expand Up @@ -91,7 +91,7 @@ export async function createContent<

// 2. Write to filesystem
await writeContentToFilesystem(
config as ContentTypeConfig,
config as ContentTypeConfig<TData>,
slug,
data,
contentDirectory,
Expand Down
2 changes: 1 addition & 1 deletion packages/content-engine/content/deleteContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import type { ContentTypeConfig, DeleteContentOptions } from "./types";
* ```
*/
export async function deleteContent<
TData extends Record<string, unknown>,
TData,
TIndexValue,
TKey extends Key,
>(options: DeleteContentOptions<TData, TIndexValue, TKey>): Promise<void> {
Expand Down
4 changes: 2 additions & 2 deletions packages/content-engine/content/filesystem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ export function getUploadFilePath(
* Write content data to the filesystem
*/
export async function writeContentToFilesystem<
TData extends Record<string, unknown>,
TData,
>(
config: ContentTypeConfig<TData>,
slug: string,
Expand All @@ -109,7 +109,7 @@ export async function writeContentToFilesystem<
* Read content data from the filesystem
*/
export async function readContentFromFilesystem<
TData extends Record<string, unknown>,
TData,
>(
config: ContentTypeConfig<TData>,
slug: string,
Expand Down
10 changes: 5 additions & 5 deletions packages/content-engine/content/readContentFile.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { Key } from "lmdb";
import { Key } from "lmdb";
import { getContentDirectory } from "../fs/getContentDirectory";
import { readContentFromFilesystem } from "./filesystem";
import type { ContentTypeConfig, ReadContentFileOptions } from "./types";
Expand All @@ -15,16 +15,16 @@ import type { ContentTypeConfig, ReadContentFileOptions } from "./types";
* ```
*/
export async function readContentFile<
TData extends Record<string, unknown>,
TIndexValue,
TKey extends Key,
TData = Record<string, unknown>,
TIndexValue = TData,
TKey extends Key = Key,
>(options: ReadContentFileOptions<TData, TIndexValue, TKey>): Promise<TData> {
const { config, slug, contentDirectory: providedContentDirectory } = options;

const contentDirectory = providedContentDirectory || getContentDirectory();

return readContentFromFilesystem<TData>(
config as ContentTypeConfig,
config as ContentTypeConfig<TData>,
slug,
contentDirectory,
);
Expand Down
11 changes: 4 additions & 7 deletions packages/content-engine/content/readContentIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,8 @@ import type {
* });
* ```
*/
export async function readContentIndex<
TData extends Record<string, unknown>,
TIndexValue,
TKey extends Key,
>(
options: ReadContentIndexOptions<TData, TIndexValue, TKey>,
export async function readContentIndex<TIndexValue, TKey extends Key>(
options: ReadContentIndexOptions<TIndexValue, TKey>,
): Promise<ReadContentIndexResult<TIndexValue, TKey>> {
const {
config,
Expand All @@ -47,7 +43,8 @@ export async function readContentIndex<
offset,
reverse,
});
const entries = await entriesIterator.asArray;
const entriesPromise = entriesIterator.asArray;
const entries = await entriesPromise;
const total = getIndexCount(db);
const more = (offset || 0) + (limit || 0) < total;

Expand Down
4 changes: 2 additions & 2 deletions packages/content-engine/content/rebuildIndex.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import type { ContentTypeConfig, RebuildIndexOptions } from "./types";
* ```
*/
export async function rebuildIndex<
TData extends Record<string, unknown>,
TData,
TIndexValue,
TKey extends Key,
>(options: RebuildIndexOptions<TData, TIndexValue, TKey>): Promise<void> {
Expand All @@ -45,7 +45,7 @@ export async function rebuildIndex<
for (const slug of slugDirectories) {
try {
const data = await readContentFromFilesystem<TData>(
config as ContentTypeConfig,
config as ContentTypeConfig<TData>,
slug,
contentDirectory,
);
Expand Down
18 changes: 9 additions & 9 deletions packages/content-engine/content/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import type { Key, RootDatabase } from "lmdb";
* TKey is flexible to support different index key structures (string, number, array, etc.)
*/
export interface ContentTypeConfig<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down Expand Up @@ -52,7 +52,7 @@ export interface UploadSpec {
* Options for creating content
*/
export interface CreateContentOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down Expand Up @@ -94,7 +94,7 @@ export interface CreateContentOptions<
* Options for updating content
*/
export interface UpdateContentOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down Expand Up @@ -144,7 +144,7 @@ export interface UpdateContentOptions<
* Options for deleting content
*/
export interface DeleteContentOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand All @@ -171,12 +171,12 @@ export interface DeleteContentOptions<
* Options for reading content from the index
*/
export interface ReadContentIndexOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
/** The content type configuration */
config: ContentTypeConfig<TData, TIndexValue, TKey>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
config: ContentTypeConfig<any, TIndexValue, TKey>;

/** Maximum number of entries to return */
limit?: number;
Expand Down Expand Up @@ -210,7 +210,7 @@ export interface ReadContentIndexResult<
* Options for reading a single content file
*/
export interface ReadContentFileOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down Expand Up @@ -240,7 +240,7 @@ export interface FileUploadData {
* Options for processing uploads
*/
export interface ProcessUploadsOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down Expand Up @@ -277,7 +277,7 @@ export type ContentDatabase<
* Options for rebuilding the index
*/
export interface RebuildIndexOptions<
TData extends Record<string, unknown> = Record<string, unknown>,
TData = Record<string, unknown>,
TIndexValue = unknown,
TKey extends Key = Key,
> {
Expand Down
4 changes: 2 additions & 2 deletions packages/content-engine/content/updateContent.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ export async function defaultUpdateUploadsProcessor(
* ```
*/
export async function updateContent<
TData extends Record<string, unknown>,
TData,
TIndexValue,
TKey extends Key,
>(options: UpdateContentOptions<TData, TIndexValue, TKey>): Promise<void> {
Expand Down Expand Up @@ -116,7 +116,7 @@ export async function updateContent<

// 3. Write to filesystem
await writeContentToFilesystem(
config as ContentTypeConfig,
config as ContentTypeConfig<TData>,
slug,
data,
contentDirectory,
Expand Down
32 changes: 32 additions & 0 deletions packages/content-engine/demo/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# dependencies
node_modules

# next.js
.next/
out/

# production
build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# env files
.env*.local

# typescript
*.tsbuildinfo
next-env.d.ts

# test content directory
/test-content

# cypress
cypress/videos
cypress/screenshots
41 changes: 41 additions & 0 deletions packages/content-engine/demo/app/layout.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import type { Metadata } from "next";
import Link from "next/link";

export const metadata: Metadata = {
title: "Content Engine Demo",
description: "Demo application for content-engine package",
};

export default function RootLayout({
children,
}: {
children: React.ReactNode;
}) {
return (
<html lang="en">
<body
style={{
fontFamily: "system-ui, sans-serif",
maxWidth: "800px",
margin: "0 auto",
padding: "20px",
}}
>
<header
style={{
marginBottom: "20px",
borderBottom: "1px solid #ddd",
paddingBottom: "10px",
}}
>
<h1 style={{ margin: 0 }}>
<Link href="/" style={{ textDecoration: "none", color: "inherit" }}>
Content Engine Demo
</Link>
</h1>
</header>
<main>{children}</main>
</body>
</html>
);
}
109 changes: 109 additions & 0 deletions packages/content-engine/demo/app/notes/[slug]/delete/page.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
import { redirect, notFound } from "next/navigation";
import Link from "next/link";
import { readContentFile } from "content-engine/content/readContentFile";
import { deleteContent } from "content-engine/content/deleteContent";
import { getContentDirectory } from "content-engine/fs/getContentDirectory";
import {
noteConfig,
NoteIndexValue,
type Note,
type NoteIndexKey,
} from "@/lib/notes";

export const dynamic = "force-dynamic";

interface Props {
params: Promise<{ slug: string }>;
}

async function performDelete(formData: FormData) {
"use server";

const slug = formData.get("slug") as string;
const date = parseInt(formData.get("date") as string, 10);
const contentDirectory = getContentDirectory();
const indexKey: NoteIndexKey = [date, slug];

await deleteContent({
config: noteConfig,
slug,
indexKey,
contentDirectory,
commitMessage: `Delete note: ${slug}`,
});

redirect("/");
}

export default async function DeleteNotePage({ params }: Props) {
const { slug } = await params;
const contentDirectory = getContentDirectory();

let note: Note;
try {
note = await readContentFile<Note, NoteIndexValue, NoteIndexKey>({
config: noteConfig,
slug,
contentDirectory,
});
} catch {
notFound();
}

return (
<div>
<h2>Delete Note</h2>
<div
style={{
backgroundColor: "#fff3cd",
border: "1px solid #ffc107",
borderRadius: "4px",
padding: "20px",
marginBottom: "20px",
}}
>
<p style={{ margin: "0 0 10px", fontWeight: "500" }}>
Are you sure you want to delete this note?
</p>
<p style={{ margin: 0 }}>
<strong>{note.title}</strong>
</p>
</div>

<form action={performDelete}>
<input type="hidden" name="slug" value={slug} />
<input type="hidden" name="date" value={note.date} />

<div style={{ display: "flex", gap: "10px" }}>
<button
type="submit"
style={{
backgroundColor: "#dc3545",
color: "white",
padding: "10px 20px",
border: "none",
borderRadius: "4px",
fontSize: "16px",
cursor: "pointer",
}}
>
Yes, Delete Note
</button>
<Link
href={`/notes/${slug}`}
style={{
padding: "10px 20px",
border: "1px solid #ddd",
borderRadius: "4px",
textDecoration: "none",
color: "#333",
display: "inline-block",
}}
>
Cancel
</Link>
</div>
</form>
</div>
);
}
Loading