Skip to content

Commit

Permalink
Add storage.pathPrefix option (#649)
Browse files Browse the repository at this point in the history
  • Loading branch information
emmatown authored Sep 25, 2023
1 parent f5a3901 commit e36b026
Show file tree
Hide file tree
Showing 13 changed files with 203 additions and 117 deletions.
5 changes: 5 additions & 0 deletions .changeset/brave-dingos-pay.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@keystatic/core': patch
---

Add `storage.pathPrefix` option
22 changes: 9 additions & 13 deletions docs/keystatic.config.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,11 @@ const markdocConfig: Config = {
};

const shouldUseCloudStorage = process.env.NODE_ENV === 'production';
const pathPrefix = shouldUseCloudStorage ? 'docs/' : '';
export const readerPath = shouldUseCloudStorage
? process.cwd().replace(/\/docs/, '')
: process.cwd();

export default config({
storage: {
kind: shouldUseCloudStorage ? 'cloud' : 'local',
},
storage: shouldUseCloudStorage
? { kind: 'cloud', pathPrefix: 'docs' }
: { kind: 'local' },
cloud: {
project: 'thinkmill-labs/keystatic-site',
},
Expand All @@ -91,7 +87,7 @@ export default config({
slugField: 'title',
entryLayout: 'content',
format: { contentField: 'content' },
path: `${pathPrefix}src/content/pages/**`,
path: 'src/content/pages/**',
schema: {
title: fields.slug({ name: { label: 'Title' } }),
summary: fields.text({
Expand All @@ -116,7 +112,7 @@ export default config({
blog: collection({
label: 'Blog posts',
slugField: 'title',
path: `${pathPrefix}src/content/blog/**`,
path: 'src/content/blog/**',
entryLayout: 'content',
format: {
contentField: 'content',
Expand Down Expand Up @@ -178,7 +174,7 @@ export default config({
authors: collection({
label: 'Authors',
slugField: 'name',
path: `${pathPrefix}src/content/authors/**`,
path: 'src/content/authors/**',
schema: {
name: fields.slug({
name: {
Expand All @@ -205,7 +201,7 @@ export default config({
projects: collection({
label: 'Projects (Showcase)',
slugField: 'title',
path: `${pathPrefix}src/content/projects/*`,
path: 'src/content/projects/*',
format: { contentField: 'content' },
entryLayout: 'content',
schema: {
Expand Down Expand Up @@ -254,7 +250,7 @@ export default config({
label: 'Pages with new editor',
slugField: 'title',
format: { contentField: 'content' },
path: `${pathPrefix}src/content/pages/**`,
path: 'src/content/pages/**',
schema: {
title: fields.slug({ name: { label: 'Title' } }),
summary: fields.text({
Expand All @@ -275,7 +271,7 @@ export default config({
// ------------------------------
navigation: singleton({
label: 'Navigation',
path: `${pathPrefix}src/content/navigation`,
path: 'src/content/navigation',
schema: {
navGroups: fields.array(
fields.object({
Expand Down
26 changes: 26 additions & 0 deletions docs/src/content/pages/content-organisation.mdoc
Original file line number Diff line number Diff line change
Expand Up @@ -151,3 +151,29 @@ coverImage: fields.image({
```

Regardless of where the `posts` entries are created, the `coverImage` image will be generated in `public/images/posts/{post-slug}`.

---

## Path prefix

If you're in a monorepo, you can use the `storage.pathPrefix` option to scope Keystatic to a specific directory instead of adding a prefix to every `path` option.

For example, this config will look for posts in `somewhere/my-site/content/posts`:

```js
export default config({
storage: {
kind: 'github',
repo: 'my-org/my-repo',
pathPrefix: 'somewhere/my-site'
},
collections: {
posts: collection({
label: 'Posts',
path: 'content/posts/*/',
// ...
})
},
})
```

4 changes: 2 additions & 2 deletions docs/src/utils/reader.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { createReader } from '@keystatic/core/reader';
import keystaticConfig, { readerPath } from '../../keystatic.config';
import keystaticConfig from '../../keystatic.config';

export const reader = createReader(readerPath, keystaticConfig);
export const reader = createReader(process.cwd(), keystaticConfig);

export async function getNavigationMap() {
const navigation = await reader.singletons.navigation.read();
Expand Down
33 changes: 8 additions & 25 deletions packages/keystatic/src/app/ItemPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -44,17 +44,10 @@ import l10nMessages from './l10n/index.json';
import { getDataFileExtension, getSlugGlobForCollection } from './path-utils';
import { useRouter } from './router';
import { PageBody, PageHeader, PageRoot } from './shell/page';
import {
useBaseCommit,
useTree,
useRepositoryId,
useBranchInfo,
} from './shell/data';
import { TreeNode } from './trees';
import { useBaseCommit, useRepositoryId, useBranchInfo } from './shell/data';
import { useDeleteItem, useUpsertItem } from './updating';
import { useItemData } from './useItemData';
import { useHasChanged } from './useHasChanged';
import { mergeDataStates } from './useData';
import { useSlugsInCollection } from './useSlugsInCollection';
import {
getCollectionFormat,
Expand All @@ -73,7 +66,6 @@ type ItemPageProps = {
initialState: Record<string, unknown>;
itemSlug: string;
localTreeKey: string;
currentTree: Map<string, TreeNode>;
basePath: string;
slugInfo: SlugFieldInfo;
};
Expand All @@ -86,7 +78,6 @@ function ItemPage(props: ItemPageProps) {
initialFiles,
initialState,
localTreeKey,
currentTree,
} = props;
const router = useRouter();
const [forceValidation, setForceValidation] = useState(false);
Expand Down Expand Up @@ -140,15 +131,13 @@ function ItemPage(props: ItemPageProps) {
basePath: futureBasePath,
format: formatInfo,
currentLocalTreeKey: localTreeKey,
currentTree,
slug: { field: collectionConfig.slugField, value: slug },
});
const update = useEventCallback(_update);
const [deleteResult, deleteItem, resetDeleteItem] = useDeleteItem({
initialFiles,
storage: config.storage,
basePath: currentBasePath,
currentTree,
});

const onReset = () => {
Expand Down Expand Up @@ -631,22 +620,17 @@ function ItemPageWrapper(props: {
format,
slug: slugInfo,
});
const { current: tree } = useTree();
const combined = useMemo(
() => mergeDataStates({ item: itemData, tree }),
[itemData, tree]
);

if (combined.kind === 'error') {
if (itemData.kind === 'error') {
return (
<ItemPageShell {...props}>
<PageBody>
<Notice tone="critical">{combined.error.message}</Notice>
<Notice tone="critical">{itemData.error.message}</Notice>
</PageBody>
</ItemPageShell>
);
}
if (combined.kind === 'loading') {
if (itemData.kind === 'loading') {
return (
<ItemPageShell {...props}>
<Flex
Expand All @@ -664,7 +648,7 @@ function ItemPageWrapper(props: {
);
}

if (combined.data.item === 'not-found') {
if (itemData.data === 'not-found') {
return (
<ItemPageShell {...props}>
<PageBody>
Expand All @@ -679,10 +663,9 @@ function ItemPageWrapper(props: {
basePath={props.basePath}
config={props.config}
itemSlug={props.itemSlug}
initialState={combined.data.item.initialState}
initialFiles={combined.data.item.initialFiles}
localTreeKey={combined.data.item.localTreeKey}
currentTree={combined.data.tree.tree}
initialState={itemData.data.initialState}
initialFiles={itemData.data.initialFiles}
localTreeKey={itemData.data.localTreeKey}
slugInfo={slugInfo}
/>
);
Expand Down
31 changes: 7 additions & 24 deletions packages/keystatic/src/app/SingletonPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ import { getSingletonFormat, getSingletonPath, isGitHubConfig } from './utils';

import { CreateBranchDuringUpdateDialog } from './ItemPage';
import { PageBody, PageHeader, PageRoot } from './shell/page';
import { useBaseCommit, useTree } from './shell/data';
import { TreeNode } from './trees';
import { mergeDataStates } from './useData';
import { useBaseCommit } from './shell/data';
import { useHasChanged } from './useHasChanged';
import { useItemData } from './useItemData';
import { useUpsertItem } from './updating';
Expand All @@ -37,7 +35,6 @@ type SingletonPageProps = {
initialState: Record<string, unknown> | null;
initialFiles: string[];
localTreeKey: string | undefined;
currentTree: Map<string, TreeNode>;
};

function SingletonPage({
Expand All @@ -46,7 +43,6 @@ function SingletonPage({
initialState,
localTreeKey,
config,
currentTree,
}: SingletonPageProps) {
const [forceValidation, setForceValidation] = useState(false);
const singletonConfig = config.singletons![singleton]!;
Expand Down Expand Up @@ -103,7 +99,6 @@ function SingletonPage({
basePath: singletonPath,
format: formatInfo,
currentLocalTreeKey: localTreeKey,
currentTree,
slug: undefined,
});
const update = useEventCallback(_update);
Expand Down Expand Up @@ -251,25 +246,20 @@ function SingletonPageWrapper(props: { singleton: string; config: Config }) {
format,
slug: undefined,
});
const { current: tree } = useTree();
const combined = useMemo(
() => mergeDataStates({ tree, item: itemData }),
[itemData, tree]
);
if (combined.kind === 'error') {
if (itemData.kind === 'error') {
return (
<PageRoot>
{header}
<PageBody>
<Notice margin="xxlarge" tone="critical">
{combined.error.message}
{itemData.error.message}
</Notice>
</PageBody>
</PageRoot>
);
}

if (combined.kind === 'loading') {
if (itemData.kind === 'loading') {
return (
<PageRoot>
{header}
Expand All @@ -295,21 +285,14 @@ function SingletonPageWrapper(props: { singleton: string; config: Config }) {
singleton={props.singleton}
config={props.config}
initialState={
combined.data.item === 'not-found'
? null
: combined.data.item.initialState
itemData.data === 'not-found' ? null : itemData.data.initialState
}
initialFiles={
combined.data.item === 'not-found'
? []
: combined.data.item.initialFiles
itemData.data === 'not-found' ? [] : itemData.data.initialFiles
}
localTreeKey={
combined.data.item === 'not-found'
? undefined
: combined.data.item.localTreeKey
itemData.data === 'not-found' ? undefined : itemData.data.localTreeKey
}
currentTree={combined.data.tree.tree}
/>
);
}
Expand Down
9 changes: 1 addition & 8 deletions packages/keystatic/src/app/create-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -27,17 +27,14 @@ import { CreateBranchDuringUpdateDialog } from './ItemPage';
import l10nMessages from './l10n/index.json';
import { useRouter } from './router';
import { PageRoot, PageHeader, PageBody } from './shell/page';
import { useBaseCommit, useTree } from './shell/data';
import { TreeNode } from './trees';
import { useBaseCommit } from './shell/data';
import { useSlugsInCollection } from './useSlugsInCollection';
import { ForkRepoDialog } from './fork-repo';
import { useUpsertItem } from './updating';
import { FormForEntry, containerWidthForEntryLayout } from './entry-form';
import { notFound } from './not-found';
import { useItemData } from './useItemData';

const emptyMap = new Map<string, TreeNode>();

function CreateItemWrapper(props: {
collection: string;
config: Config;
Expand Down Expand Up @@ -190,8 +187,6 @@ function CreateItem(props: {

const baseCommit = useBaseCommit();

const tree = useTree();

const slug = getSlugFromState(collectionConfig, state);

const formatInfo = getCollectionFormat(props.config, props.collection);
Expand All @@ -203,8 +198,6 @@ function CreateItem(props: {
schema: collectionConfig.schema,
format: formatInfo,
currentLocalTreeKey: undefined,
currentTree:
tree.current.kind === 'loaded' ? tree.current.data.tree : emptyMap,
slug: { field: collectionConfig.slugField, value: slug },
});
const createItem = useEventCallback(_createItem);
Expand Down
7 changes: 7 additions & 0 deletions packages/keystatic/src/app/path-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,3 +139,10 @@ export type FormatInfo = {
| undefined;
dataLocation: 'index' | 'outer';
};

export function getPathPrefix(storage: Config['storage']) {
if (storage.kind === 'local' || !storage.pathPrefix) {
return undefined;
}
return fixPath(storage.pathPrefix) + '/';
}
Loading

2 comments on commit e36b026

@vercel
Copy link

@vercel vercel bot commented on e36b026 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

keystatic – ./dev-projects/next-app

keystatic-git-main-thinkmill-labs.vercel.app
keystatic.vercel.app
keystatic-thinkmill-labs.vercel.app

@vercel
Copy link

@vercel vercel bot commented on e36b026 Sep 25, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Successfully deployed to the following URLs:

keystar-ui – ./design-system/docs

keystar-ui.vercel.app
keystar-ui-git-main-thinkmill-labs.vercel.app
voussoir.vercel.app
keystar-ui-thinkmill-labs.vercel.app

Please sign in to comment.