Skip to content

Switch nutils to vite build #226

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
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 README.md
Original file line number Diff line number Diff line change
@@ -19,7 +19,7 @@ Refactored with [Turboplate](https://github.com/seonglae/turboplate). Search API

```zsh
pnpm i
pnpm build # TSUp
pnpm build # Vite
pnpm test # Vitest
```

@@ -58,7 +58,7 @@ pnpm turbo pu
[Turboplate](https://github.com/seonglae/turboplate) stacks

- `Turborepo` monorepo
- `TSup` build
- `Vite` build
- `Vitest` test
- `ESLint` lint
- `Prettier` format
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -39,11 +39,11 @@
"husky": "^9.1.7",
"prettier": "^3.5.3",
"standard-version": "^9.5.0",
"tsup": "^8.5.0",
"tsx": "^4.19.4",
"turbo": "^2.5.4",
"typescript": "^5.8.3",
"vite": "^6.3.5",
"vite-plugin-dts": "^3.8.1",
"vitest": "^3.2.2"
},
"standard-version": {
4 changes: 2 additions & 2 deletions packages/cli/package.json
Original file line number Diff line number Diff line change
@@ -21,8 +21,8 @@
"notion": "./build/src/main.js"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"test": "vitest --run",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
2 changes: 2 additions & 0 deletions packages/cli/src/main.ts
Original file line number Diff line number Diff line change
@@ -18,3 +18,5 @@ export * from './notion/export'
export * from './notion/index'
export * from './treemap'
export * from './stats'
export * from './treemap'
export * from './stats'
Comment on lines +21 to +22
Copy link
Preview

Copilot AI Jun 7, 2025

Choose a reason for hiding this comment

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

The duplicate export statement for './treemap' (and similarly for './stats') can cause redundancy and potential conflicts. Remove the extra export lines to keep the module exports clear.

Suggested change
export * from './treemap'
export * from './stats'

Copilot uses AI. Check for mistakes.

18 changes: 18 additions & 0 deletions packages/cli/src/notion/export.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
import { Option, Command } from 'clipanion'
import { NotionExporter } from './index'
import { generateTreemaps, PageNode } from '../treemap'
import { computeStats, writeStats } from '../stats'
treemap = Option.Boolean('--treemap', {
description: 'Generate HTML treemap after export'
})
stats = Option.Boolean('--stats', {
description: 'Generate statistics JSON after export'
})

if (this.treemap || this.stats) if (!exporter.pageTree) await exporter.loadRaw()

const tree = exporter.pageTree as unknown as PageNode
if (this.treemap && tree) await generateTreemaps(this.folder, tree)

if (this.stats && tree) {
const stats = computeStats(tree)
await writeStats(`${this.folder}/stats.json`, stats)
}
import { generateTreemaps, PageNode } from '../treemap'
Copy link
Preview

Copilot AI Jun 7, 2025

Choose a reason for hiding this comment

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

A duplicate import of 'generateTreemaps' and 'PageNode' was introduced, which can lead to confusion and potential maintenance issues. Removing the redundant import should resolve this.

Suggested change
import { generateTreemaps, PageNode } from '../treemap'

Copilot uses AI. Check for mistakes.

import { computeStats, writeStats } from '../stats'

export class NotionExportCommand extends Command {
7 changes: 0 additions & 7 deletions packages/cli/src/treemap.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,21 @@
import fs from 'fs'
import { promisify } from 'util'

export interface PageNode {
id: string
blocks: number
pages: number
title: string
children?: PageNode[]
}

const writeFile = promisify(fs.writeFile)

export async function generateTreemaps(folder: string, pageTree: PageNode) {
const treemapDataPages = computeMetrics(pageTree, 'pages')
const titlePages = 'Texonom PageTree'
const outputPathPages = `${folder}/pagetree.html`
await generateTreemapHTML(treemapDataPages, titlePages, outputPathPages)

const treemapDataBlocks = computeMetrics(pageTree, 'blocks')
const titleBlocks = 'Texonom BlockMap'
const outputPathBlocks = `${folder}/blocktree.html`
await generateTreemapHTML(treemapDataBlocks, titleBlocks, outputPathBlocks)
}

interface TreemapNode {
id: string
name: string
14 changes: 0 additions & 14 deletions packages/cli/tsup.config.ts

This file was deleted.

30 changes: 30 additions & 0 deletions packages/cli/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' assert { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/main.ts',
formats: ['es'],
fileName: () => 'main.js'
},
outDir: 'build/src',
target: 'node16',
sourcemap: true,
minify: true,
rollupOptions: {
external: [
...Object.keys(pkg.dependencies || {}),
...Object.keys(pkg.peerDependencies || {}),
'fs',
'fs/promises',
'path',
'stream',
'util'
]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build/src' })]
})

4 changes: 2 additions & 2 deletions packages/nclient/package.json
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@
"node": ">=22.16.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"test": "vitest --run",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
13 changes: 13 additions & 0 deletions packages/nclient/readme.md
Original file line number Diff line number Diff line change
@@ -42,6 +42,19 @@ const backlinks = await api.getBacklinks({
const pageBacklinks = await api.getPageBacklinks('page-id')
```

### Fetch backlinks

Backlinks require an auth token.

```ts
const backlinks = await api.getBacklinks({
block: { id: 'page-id', spaceId: 'space-id' }
})

// or simply pass the page id
const pageBacklinks = await api.getPageBacklinks('page-id')
```

### Fetch a database's content

You can pass a database ID to the `getPage` method. The response is an object which contains several important properties:
6 changes: 6 additions & 0 deletions packages/nclient/src/notion-api.test.ts
Original file line number Diff line number Diff line change
@@ -65,6 +65,12 @@ test(`Page Backlink`, { timeout: 10000, concurrent: true }, async () => {
expect(backlinks.backlinks.length > 0)
})

test(`Page Backlink`, { timeout: 10000, concurrent: true }, async () => {
const api = new NotionAPI({ authToken: process.env.NOTION_TOKEN })
const backlinks = await api.getPageBacklinks('441d5ce2-b781-46d0-9354-54042b4f06d9')
expect(backlinks.backlinks.length > 0)
})

test(`Get block`, { timeout: 10000, concurrent: true }, async () => {
const id = '3f9e0d86-c643-4672-aa0c-78d63fa80598'
const api = new NotionAPI()
17 changes: 17 additions & 0 deletions packages/nclient/src/notion-api.ts
Original file line number Diff line number Diff line change
@@ -591,6 +591,23 @@ export class NotionAPI {
return this.getBacklinks({ block: { id, spaceId } }, fetchOption)
}

/**
* Fetch backlinks for a page by automatically resolving its space id.
* Requires an authToken since backlinks are a private API.
*
* @param pageId page id or url
* @param fetchOption additional fetch options
*/
public async getPageBacklinks(pageId: string, fetchOption?: FetchOption) {
const id = parsePageId(pageId)
const res = await this.getBlocks([id], fetchOption)
const block = res.recordMap.block[id]?.value
if (!block) throw new Error(`Block not found "${uuidToId(id)}"`)
const spaceId = block.space_id

return this.getBacklinks({ block: { id, spaceId } }, fetchOption)
}

public async fetch<T>({
endpoint,
body,
14 changes: 0 additions & 14 deletions packages/nclient/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/nclient/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' assert { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
4 changes: 2 additions & 2 deletions packages/ncompat/package.json
Original file line number Diff line number Diff line change
@@ -17,8 +17,8 @@
"node": ">=22.16.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
13 changes: 0 additions & 13 deletions packages/ncompat/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/ncompat/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' assert { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
4 changes: 2 additions & 2 deletions packages/nreact/package.json
Original file line number Diff line number Diff line change
@@ -18,8 +18,8 @@
"node": ">=22.16.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
12 changes: 10 additions & 2 deletions packages/nreact/src/components/search-dialog.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import React from 'react'
import { getBlockParentPage, getBlockTitle } from '@texonom/nutils'

import { NotionContextConsumer, NotionContextProvider } from '../context'
import { ClearIcon } from '../icons/clear-icon'
import { LoadingIcon } from '../icons/loading-icon'
@@ -19,6 +17,16 @@ const debounce = (func: (...args: any[]) => void, wait: number) => {
}
}

// debounce search calls so the expensive query only runs after typing stops
this._search = debounce(this._searchImpl.bind(this), 500)
onInput={this._onChangeQuery}
Copy link
Preview

Copilot AI Jun 7, 2025

Choose a reason for hiding this comment

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

The 'onInput={this._onChangeQuery}' attribute appears to be misplaced within the debounce function block. Consider moving it to the appropriate component JSX element to avoid unintended behavior.

Copilot uses AI. Check for mistakes.

let timeout: ReturnType<typeof setTimeout> | undefined
return (...args: any[]) => {
if (timeout) clearTimeout(timeout)
timeout = setTimeout(() => func(...args), wait)
}
}

export class SearchDialog extends React.Component<{
isOpen: boolean
rootBlockId: string
7 changes: 6 additions & 1 deletion packages/nreact/src/context.tsx
Original file line number Diff line number Diff line change
@@ -185,10 +185,15 @@ export const NotionContextProvider: React.FC<PartialNotionContext> = ({
if (components.nextLink) {
const nextLink = wrapNextLink(components.nextLink)
components.nextLink = nextLink

if (!components.PageLink) components.PageLink = nextLink
if (!components.Link) components.Link = nextLink
}
// ensure the user can't override default components with falsy values
// since it would result in very difficult-to-debug react errors
for (const key of Object.keys(components)) if (!components[key]) delete components[key]

return components
}, [themeComponents])

// ensure the user can't override default components with falsy values
// since it would result in very difficult-to-debug react errors
34 changes: 0 additions & 34 deletions packages/nreact/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/nreact/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' assert { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.tsx',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
5 changes: 3 additions & 2 deletions packages/ntypes/package.json
Original file line number Diff line number Diff line change
@@ -14,10 +14,11 @@
"build"
],
"scripts": {
"build": "tsc && tsup",
"build": "tsc && vite build",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
"pu": "pnpm publish",
"watch": "vite build --watch --mode development"
},
"engines": {
"node": ">=22.16.0"
14 changes: 0 additions & 14 deletions packages/ntypes/tsup.config.ts

This file was deleted.

21 changes: 21 additions & 0 deletions packages/ntypes/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'
import pkg from './package.json' assert { type: 'json' }

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: [...Object.keys(pkg.dependencies || {}), ...Object.keys(pkg.peerDependencies || {})]
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
7 changes: 5 additions & 2 deletions packages/nutils/package.json
Original file line number Diff line number Diff line change
@@ -23,13 +23,16 @@
"node": ">=22.16.0"
},
"scripts": {
"build": "tsc && tsup",
"watch": "tsup --watch --silent --onSuccess 'echo build successful'",
"build": "tsc && vite build",
"watch": "vite build --watch --mode development",
"test": "vitest --run",
"prerelease": "standard-version --skip.changelog --prerelease",
"release": "standard-version --release-as",
"pu": "pnpm publish"
},
"devDependencies": {
"vite-plugin-dts": "^3.8.1"
},
"dependencies": {
"is-url-superb": "^6.1.0",
"mem": "^10.0.0",
14 changes: 0 additions & 14 deletions packages/nutils/tsup.config.ts

This file was deleted.

20 changes: 20 additions & 0 deletions packages/nutils/vite.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import { defineConfig } from 'vite'
import dts from 'vite-plugin-dts'

export default defineConfig({
build: {
lib: {
entry: 'src/index.ts',
formats: ['es'],
fileName: () => 'index.js'
},
outDir: 'build',
target: 'es2015',
sourcemap: true,
minify: true,
rollupOptions: {
external: ['is-url-superb', 'mem', 'normalize-url', '@texonom/ntypes', 'p-queue']
}
},
plugins: [dts({ tsconfigPath: 'tsconfig.json', outDir: 'build' })]
})
980 changes: 591 additions & 389 deletions pnpm-lock.yaml

Large diffs are not rendered by default.