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
54 changes: 48 additions & 6 deletions __tests__/__fakes__/fakeDestination.repository.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { type PageElement } from '@/domains/elements';
import {
DestinationRepository,
ObjectType,
Page,
PageLockedStatus,
} from '@/domains/synchronization/destination.repository';
Expand All @@ -10,18 +11,36 @@ import { FakePage } from './fakePage';
export class FakeDestinationRepository<T extends Page>
implements DestinationRepository<T>
{
getPageIdFromPageUrl({ pageUrl }: { pageUrl: string }): string {
return pageUrl.split('/').pop() ?? '';
async getObjectType({ id }: { id: string }): Promise<ObjectType> {
return Promise.resolve('page');
}

getObjectIdFromObjectUrl({ objectUrl }: { objectUrl: string }): string {
const urlObj = new URL(objectUrl);

// Notion IDs are 32-character hexadecimal strings (UUID without dashes)
// They can be embedded in path segments like "MK-Notes-4dd0bd3dc73648a9a55dcf05dd03080f"
const notionIdRegex = /[a-f0-9]{32}/gi;
const matches = urlObj.pathname.match(notionIdRegex);

if (!matches || matches.length === 0) {
throw new Error('Invalid Notion URL: No valid Notion ID found');
}

// Return the last match (closest to the end of the URL path)
return matches[matches.length - 1];
}

// Simulate creating a new page
// eslint-disable-next-line @typescript-eslint/require-await
async createPage({
pageElement,
parentPageId,
parentObjectId,
parentObjectType,
}: {
pageElement: PageElement;
parentPageId: string;
parentObjectId: string;
parentObjectType: ObjectType;
}): Promise<T> {
// Here you would implement the logic to create a new page in the fake destination
const fakePage = new FakePage({
Expand Down Expand Up @@ -55,9 +74,9 @@ export class FakeDestinationRepository<T extends Page>
// Simulate checking if the destination is accessible
// eslint-disable-next-line @typescript-eslint/require-await
async destinationIsAccessible({
parentPageId,
parentObjectId,
}: {
parentPageId: string;
parentObjectId: string;
}): Promise<boolean> {
// Here you would implement the logic to check if the destination is accessible
// For demonstration purposes, let's return a boolean value
Expand Down Expand Up @@ -110,4 +129,27 @@ export class FakeDestinationRepository<T extends Page>
}): Promise<PageLockedStatus> {
return 'unlocked';
}

async getObjectIdInDatabaseByMkNotesInternalId({
dataSourceId,
mkNotesInternalId,
}: {
dataSourceId: string;
mkNotesInternalId: string;
}): Promise<string[]> {
return Promise.resolve([]);
}

async getDataSourceIdFromDatabaseId({
databaseId,
}: {
databaseId: string;
}): Promise<string> {
return Promise.resolve('');
}

async deleteObjectById({ objectId }: { objectId: string }): Promise<void> {
// no-op in fake repository for testing
return Promise.resolve();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,17 +4,17 @@ title: Your first synchronization
description: Tutorial to make your first synchronization with Mk Notes
---

In this tutorial, you will learn how to synchronize your markdown files in a Notion page with Mk Notes.
In this tutorial, you will learn how to synchronize your markdown files to Notion with Mk Notes.

---

## Requirements

- A **Notion Integration** with read-write access on your Notion page
- A **Notion Integration** with read-write access on your Notion page or your Notion Database
<Callout>
Read the official
[Notion guide](https://developers.notion.com/docs/authorization) to create
and setup a Notion Integration on your workspace
Read the official [Notion
guide](https://developers.notion.com/docs/authorization) to create and setup
a Notion Integration on your workspace
</Callout>

## Step-by-step guide 👇
Expand All @@ -41,18 +41,22 @@ Launch the following command:
```bash
mk-notes sync \
--input <path-to-your-markdown-file-or-directory> \
--destination <notion-page-url> \
--destination <notion-page-or-database-url> \
--notion-api-key <your-notion-secret>
```

- `--input` : The path to your markdown file or directory containing markdown files.
- `--destination` : The Notion page URL where you want to synchronize your markdown files.
- `--destination` : The Notion page or Notion Database URL where you want to synchronize your markdown files.
- `--notion-api-key` : Your Notion secret token.

<Callout type="warning">
Please note that you can only synchronize markdown files to **Notion Pages**.
Notion Databases are not supported for now.
<Callout type="info">
Mk Notes supports both **Notion Pages** and **Notion Databases** as
destinations. When syncing to a database, pages are created as database items.

For more information about synchronization into a database, you can read the [Database Synchronization](../guides/database-sync) guide.

</Callout>

</div>
</div>
---
Expand Down
83 changes: 78 additions & 5 deletions docs/content/docs/cli/guides/cli-commands.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -10,25 +10,56 @@ MK Notes provides two main commands to help you manage your markdown to Notion s

## `sync`

The `sync` command synchronizes markdown files to a Notion page. You can sync either a single markdown file or an entire directory of markdown files, creating a matching page hierarchy for directories.
The `sync` command synchronizes markdown files to a Notion page or database. You can sync either a single markdown file or an entire directory of markdown files, creating a matching page hierarchy for directories.

### Usage

```bash
mk-notes sync -i <path> -d <notionPageUrl> -k <notionApiKey>
mk-notes sync -i <path> -d <notionUrl> -k <notionApiKey>
```

### Required Options

- `-i, --input <path>`: Path to a markdown file or directory containing your markdown files
- `-d, --destination <notionPageUrl>`: URL of the parent Notion page where content will be synchronized
- `-d, --destination <notionUrl>`: URL of the parent Notion page or database where content will be synchronized
- `-k, --notion-api-key <notionApiKey>`: Your Notion API key for authentication

### Optional Options

- `-c, --clean`: Clean sync mode - **WARNING: removes ALL existing content** from the destination page before syncing, including any manually added content or blocks not created by mk-notes. This prevents duplicate content when repeatedly syncing to the same destination, but will delete any custom content you've added to the page.
- `-c, --clean`: Clean sync mode - behavior depends on the destination type:

<Callout type="warning" title="For Notion Pages">

Removes <b>ALL existing content</b> from the destination page before
syncing, including any manually added content or blocks not created by
mk-notes.

</Callout>

<Callout type="warning" title="For Notion Databases">

Finds and deletes existing pages with the same `id` (using the `mk-notes-id`
notion database property) before creating new ones. This requires the `id`
property to be set in your markdown frontmatter.

For more information about synchronization into a database, you can read the [Database Synchronization](../database-sync) guide.

</Callout>

- `-l, --lock`: Lock the Notion page after syncing to prevent further editing. This is useful when you want to preserve the synchronized content and prevent accidental modifications.

### Destination Types

Mk Notes supports two types of destinations:

#### Notion Page

When the destination is a Notion page, content is appended directly to the page (or replaces existing content with `--clean`). Child pages are created as sub-pages.

#### Notion Database

When the destination is a Notion database, pages are created as database items. This is useful for managing collections of documents where you want to leverage Notion's database features like filtering, sorting, and views.

### Examples

#### Syncing a Directory
Expand Down Expand Up @@ -112,13 +143,55 @@ mk-notes sync \

This command will:

1. Remove ALL existing content from the destination Notion page (including pages that arelocked)
1. Remove ALL existing content from the destination Notion page (including pages that are locked)
2. Read all markdown files in the `./my-docs` directory
3. Create a matching page hierarchy in Notion
4. Convert and sync the content to your specified Notion page
5. **Lock the Notion page** to prevent further editing
6. Display a success message with the Notion page URL when complete

#### Syncing to a Notion Database

```bash
mk-notes sync \
--input ./my-docs \
--destination https://notion.so/myworkspace/database-123456 \
--notion-api-key secret_abc123...
```

This command will:

1. Read all markdown files in the `./my-docs` directory
2. Create pages as items in the specified Notion database
3. Display a success message when complete

#### Syncing to a Database with Clean Sync

```bash
mk-notes sync \
--input ./my-docs \
--destination https://notion.so/myworkspace/database-123456 \
--notion-api-key secret_abc123... \
--clean
```

For database destinations with clean sync, make sure your markdown files include an `id` in the frontmatter:

```markdown
---
id: my-unique-page-id
title: My Document
---

Content here...
```

This command will:

1. Find existing pages in the database with matching `mk-notes-id` property
2. Delete those existing pages
3. Create new pages as database items with the content from your markdown files

## `preview-sync`

The `preview-sync` command lets you preview how your markdown files will be organized in Notion before actually performing the synchronization. This is useful for verifying the structure before making any changes.
Expand Down
Loading