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
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
"clean": "rm -rf packages/*/build packages/*/.turbo node_modules/.cache",
"test": "vitest --run",
"coverage": "vitest --run --coverage",
"lint": "eslint \"**/*.{ts,tsx}\" --fix --ignore-path .gitignore --cache",
"lint": "ESLINT_USE_FLAT_CONFIG=false eslint \"**/*.{ts,tsx}\" --fix --ignore-path .gitignore --cache",
"format": "prettier \"**/*.{js,json,md,css,js,ts,tsx}\" --write --ignore-path .gitignore",
"prerelease": "standard-version -a -t '' --skip.changelog --prerelease",
"release": "standard-version -a -t '' --release-as",
Expand Down
7 changes: 6 additions & 1 deletion packages/cli/src/notion/export.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,9 @@ export class NotionExportCommand extends Command {
wait = Option.Counter('-w,--wait', {
description: 'Wait couter for missed collection view'
})
push = Option.Boolean('--push', {
description: 'Push exported data to remote repositories'
})

async execute() {
const exporter = new NotionExporter({
Expand All @@ -64,9 +67,11 @@ export class NotionExportCommand extends Command {
load: this.load,
raw: this.raw,
dataset: this.dataset,
token: this.token
token: this.token,
push: this.push
})
await exporter.execute()
if (this.push) await exporter.pushRepos()

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

Expand Down
31 changes: 31 additions & 0 deletions packages/cli/src/notion/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import { mkdir, readFile } from 'fs/promises'
import JSONStream from 'JSONStream'
import fs from 'graceful-fs'
import { promisify } from 'util'
import { execSync } from 'child_process'
import stream from 'stream'
import { format } from 'prettier'
import { isCollection, isSpace } from '@texonom/ntypes'
Expand Down Expand Up @@ -51,6 +52,7 @@ export class NotionExporter {
load: boolean = false
raw: boolean = false
dataset: boolean = false
push: boolean = false
debug: boolean = false
wait: number = 5
token: string | undefined
Expand All @@ -68,6 +70,7 @@ export class NotionExporter {
raw?: boolean
dataset?: boolean
token?: string
push?: boolean
}) {
this.page = parsePageId(options.page)
this.folder = options.folder ?? this.folder
Expand All @@ -81,6 +84,7 @@ export class NotionExporter {
this.raw = options.raw ?? this.raw
this.dataset = options.dataset ?? this.dataset
this.token = options.token
this.push = options.push ?? this.push

this.notion = new NotionAPI({ authToken: this.token })
if (this.validation) writeFile = async () => {}
Expand Down Expand Up @@ -713,6 +717,33 @@ export class NotionExporter {
}
return space
}

pushRepos() {
const run = (cmd: string, cwd: string) => {
try {
execSync(cmd, { cwd, stdio: 'ignore' })
} catch {
// Ignore errors - some commands may fail (e.g., remote already exists)
}
}
const message = new Date().toString()

// push raw
run('git init', this.folder)
run('git add .', this.folder)
run(`git commit -m "${message}"`, this.folder)
run('git branch -M main', this.folder)
run('git remote add origin https://github.com/texonom/texonom-raw.git', this.folder)
run('git push -u origin main --force', this.folder)

// push md
run('git init', this.md)
run('git add .', this.md)
run(`git commit -m "${message}"`, this.md)
run('git branch -M main', this.md)
run('git remote add origin https://github.com/texonom/texonom-md.git', this.md)
run('git push -u origin main --force', this.md)
Comment on lines +721 to +745
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists
fd "index.ts" packages/cli/src/notion/

# Get line count to verify the file size
wc -l packages/cli/src/notion/index.ts

Repository: texonom/notion-node

Length of output: 132


🏁 Script executed:

# Read the specific lines mentioned in the review (721-745)
sed -n '721,745p' packages/cli/src/notion/index.ts

Repository: texonom/notion-node

Length of output: 958


🏁 Script executed:

# Get broader context around the pushRepos function
sed -n '710,760p' packages/cli/src/notion/index.ts

Repository: texonom/notion-node

Length of output: 2190


🏁 Script executed:

# Search for where pushRepos is called
rg "pushRepos" packages/cli/src/notion/index.ts

Repository: texonom/notion-node

Length of output: 78


🏁 Script executed:

# Get more context - find the class definition
sed -n '650,730p' packages/cli/src/notion/index.ts | head -100

Repository: texonom/notion-node

Length of output: 3421


🏁 Script executed:

# Check imports at the top of the file
head -50 packages/cli/src/notion/index.ts

Repository: texonom/notion-node

Length of output: 1455


🏁 Script executed:

# Search for pushRepos usage in the entire codebase
rg "pushRepos" --type ts

Repository: texonom/notion-node

Length of output: 191


Avoid silent failures and hard force-pushes in pushRepos.

Swallowing all exec errors makes failed pushes look successful, and --force can overwrite remote history. The current catch block suppresses all errors, not just the "remote already exists" case mentioned in the comment. Prefer surfacing failures via stdio: 'inherit' and using --force-with-lease to reduce risk of silent data loss.

🔧 Safer push flow
-    const run = (cmd: string, cwd: string) => {
+    const run = (cmd: string, cwd: string, allowFailure = false) => {
       try {
-        execSync(cmd, { cwd, stdio: 'ignore' })
-      } catch {
-        // Ignore errors - some commands may fail (e.g., remote already exists)
+        execSync(cmd, { cwd, stdio: 'inherit' })
+      } catch (err) {
+        if (allowFailure) {
+          console.warn(`[push] ${cmd} failed in ${cwd}`, err)
+          return
+        }
+        throw err
       }
     }
@@
-    run('git remote add origin https://github.com/texonom/texonom-raw.git', this.folder)
-    run('git push -u origin main --force', this.folder)
+    run('git remote add origin https://github.com/texonom/texonom-raw.git', this.folder, true)
+    run('git push -u origin main --force-with-lease', this.folder)
@@
-    run('git remote add origin https://github.com/texonom/texonom-md.git', this.md)
-    run('git push -u origin main --force', this.md)
+    run('git remote add origin https://github.com/texonom/texonom-md.git', this.md, true)
+    run('git push -u origin main --force-with-lease', this.md)
🤖 Prompt for AI Agents
In `@packages/cli/src/notion/index.ts` around lines 721 - 745, The pushRepos
method currently swallows all execSync errors in the local run helper and uses
--force when pushing, so update pushRepos/run to surface real failures and avoid
blind force-pushes: change the run helper (used by pushRepos) to remove the
broad empty catch (or rethrow after handling), execute execSync with stdio:
'inherit' so command errors are visible, only catch the specific "remote already
exists" error when running git remote add (or check for existing remote before
adding), and replace git push --force with git push --force-with-lease for both
this.folder and this.md pushes to reduce risk of overwriting remote history.

}
}

export async function loadRaw(
Expand Down