@hyzhak/apple-notes-export 0.1.4-dev.0 → 0.1.4-dev.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +4 -0
- package/dist/cli.js.map +1 -1
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -497,6 +497,10 @@ async function main(argv) {
|
|
|
497
497
|
if (maybeCommanderError?.code === "commander.executeSubCommandAsync") {
|
|
498
498
|
throw error;
|
|
499
499
|
}
|
|
500
|
+
if (maybeCommanderError?.code === "commander.helpDisplayed" || maybeCommanderError?.code === "commander.version") {
|
|
501
|
+
process.exitCode = 0;
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
500
504
|
process.stderr.write(`Error: ${maybeCommanderError.message}
|
|
501
505
|
`);
|
|
502
506
|
process.exitCode = 1;
|
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/index.ts","../src/lib/export-context.ts","../src/lib/notes-bridge.ts","../src/lib/export-runner.ts","../src/lib/notes/reader.ts","../src/lib/notes/normalize.ts","../src/lib/notes/jxa-helpers.ts","../src/services/file-writer.ts","../src/services/pathing.ts","../src/lib/filter-schema.ts","../src/lib/filtering.ts","../src/lib/progress-reporter.ts","../src/cli/entry.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { z } from 'zod';\nimport { createRequire } from 'node:module';\nimport { createExportContext } from '../lib/export-context';\nimport { ensureMacOS } from '../lib/notes-bridge';\nimport { exportNotes } from '../lib/export-runner';\nimport { parseFolderFilters, parseDateFilters } from '../lib/filter-schema';\n\nconst require = createRequire(import.meta.url);\n// Keep CLI usable from both compiled dist/ and ts-node/src:\n// - dist/cli.js sits beside dist/package.json -> ../package.json\n// - src/cli/index.ts sits under src/ -> ../../package.json\nconst cliPath = new URL('.', import.meta.url).pathname;\nconst pkgUrl = cliPath.includes('/dist/')\n ? new URL('../package.json', import.meta.url)\n : new URL('../../package.json', import.meta.url);\nconst version =\n (require(pkgUrl.pathname) as { version?: string }).version ??\n 'unknown';\n\nconst cliSchema = z.object({\n target: z.string().min(1, 'Target directory is required'),\n force: z.boolean().optional(),\n includeAttachments: z.boolean().optional(),\n includeFolder: z.array(z.string()).optional(),\n excludeFolder: z.array(z.string()).optional(),\n createdAfter: z.string().optional(),\n createdBefore: z.string().optional(),\n modifiedAfter: z.string().optional(),\n modifiedBefore: z.string().optional(),\n quiet: z.boolean().optional(),\n verbose: z.number().int().nonnegative().optional()\n});\n\nexport async function main(argv: string[]): Promise<void> {\n const program = new Command();\n program\n .name('apple-notes-export')\n .description('Apple Notes export CLI (MVP smoke run)')\n .version(version)\n .requiredOption('-t, --target <dir>', 'Absolute path to target directory')\n .option('-f, --force', 'Allow non-empty target directory', false)\n .option('--include-attachments', 'Attachments export is not yet implemented', false)\n .option('--include-folder <paths...>', 'Include only folders (prefix match)', [])\n .option('--exclude-folder <paths...>', 'Exclude folders (prefix match)', [])\n .option('--created-after <iso>', 'Only export notes created on/after this UTC date')\n .option('--created-before <iso>', 'Only export notes created on/before this UTC date')\n .option('--modified-after <iso>', 'Only export notes modified on/after this UTC date')\n .option('--modified-before <iso>', 'Only export notes modified on/before this UTC date')\n .option('-q, --quiet', 'Reduce log noise (progress only)', false)\n .option(\n '-v, --verbose',\n 'Increase verbosity (repeat for more detail)',\n (_value, previous: number) => previous + 1,\n 0\n );\n\n program.exitOverride();\n\n try {\n program.parse(argv);\n const options = program.opts<{\n target: string;\n force?: boolean;\n includeAttachments?: boolean;\n includeFolder?: string[];\n excludeFolder?: string[];\n createdAfter?: string;\n createdBefore?: string;\n modifiedAfter?: string;\n modifiedBefore?: string;\n quiet?: boolean;\n verbose?: number;\n }>();\n const parsed = cliSchema.parse({\n target: options.target,\n force: Boolean(options.force),\n includeAttachments: Boolean(options.includeAttachments),\n includeFolder: options.includeFolder,\n excludeFolder: options.excludeFolder,\n createdAfter: options.createdAfter,\n createdBefore: options.createdBefore,\n modifiedAfter: options.modifiedAfter,\n modifiedBefore: options.modifiedBefore,\n quiet: Boolean(options.quiet),\n verbose: options.verbose\n });\n\n ensureMacOS();\n\n if (parsed.includeAttachments) {\n // Attachments are deferred; keep UX explicit.\n process.stderr.write('Warning: --include-attachments is not implemented yet; continuing without attachments.\\n');\n }\n\n const context = await createExportContext({\n targetDir: parsed.target,\n force: parsed.force,\n includeAttachments: false\n });\n\n const filters = parseFolderFilters({\n includeFolders: parsed.includeFolder,\n excludeFolders: parsed.excludeFolder\n });\n\n const dateFilters = parseDateFilters({\n createdAfter: parsed.createdAfter,\n createdBefore: parsed.createdBefore,\n modifiedAfter: parsed.modifiedAfter,\n modifiedBefore: parsed.modifiedBefore\n });\n\n const logLevel = parsed.quiet ? 0 : Math.min(2, (parsed.verbose ?? 0) + 1);\n\n const result = await exportNotes(\n context,\n {},\n { folders: filters, dates: dateFilters },\n { logLevel }\n );\n\n const summary = {\n status: 'ok',\n indexPath: result.indexPath,\n notesPath: result.notesPath,\n exported: result.exported,\n skipped: result.skipped,\n firstNote: result.firstNote\n };\n\n process.stdout.write(JSON.stringify(summary, null, 2) + '\\n');\n process.exitCode = 0;\n } catch (error) {\n const maybeCommanderError = error as Error & { code?: string };\n if (maybeCommanderError?.code === 'commander.executeSubCommandAsync') {\n throw error;\n }\n process.stderr.write(`Error: ${(maybeCommanderError as Error).message}\\n`);\n process.exitCode = 1;\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nconst INDEX_FILENAME = 'index.json';\n\nexport interface ExportConfig {\n targetDir: string;\n force?: boolean;\n includeAttachments?: boolean;\n}\n\nexport interface ExportContext {\n targetDir: string;\n notesPath: string;\n artifactsPath: string;\n indexPath: string;\n includeAttachments: boolean;\n}\n\nasync function ensureDirectoryExists(targetDir: string): Promise<void> {\n await fs.mkdir(targetDir, { recursive: true });\n}\n\nasync function isDirectoryEmpty(dir: string, allowedNames: string[] = []): Promise<boolean> {\n const entries = await fs.readdir(dir);\n const meaningful = entries.filter((name) => !allowedNames.includes(name));\n return meaningful.length === 0;\n}\n\nexport async function validateTargetDirectory(targetDir: string, force: boolean): Promise<void> {\n const stats = await fs.stat(targetDir).catch(() => undefined);\n if (!stats) {\n return;\n }\n if (!stats.isDirectory()) {\n throw new Error(`Target path must be a directory: ${targetDir}`);\n }\n // Some environments drop a node-compile-cache folder beside the app; allow it when empty otherwise.\n const allowed = ['node-compile-cache'];\n if (!(await isDirectoryEmpty(targetDir, allowed)) && !force) {\n throw new Error('Target directory must be empty unless --force is provided.');\n }\n}\n\nexport async function createExportContext(config: ExportConfig): Promise<ExportContext> {\n if (!path.isAbsolute(config.targetDir)) {\n throw new Error('Target directory must be an absolute path.');\n }\n\n const force = Boolean(config.force);\n const includeAttachments = Boolean(config.includeAttachments);\n\n await ensureDirectoryExists(config.targetDir);\n await validateTargetDirectory(config.targetDir, force);\n\n const notesPath = path.join(config.targetDir, 'notes');\n const artifactsPath = path.join(config.targetDir, 'artifacts');\n const indexPath = path.join(config.targetDir, INDEX_FILENAME);\n\n await fs.mkdir(notesPath, { recursive: true });\n if (includeAttachments) {\n await fs.mkdir(artifactsPath, { recursive: true });\n }\n\n return {\n targetDir: config.targetDir,\n notesPath,\n artifactsPath,\n indexPath,\n includeAttachments\n };\n}\n","export class MacOSUnsupportedError extends Error {\n constructor(message = 'Apple Notes export requires macOS.') {\n super(message);\n this.name = 'MacOSUnsupportedError';\n }\n}\n\nexport class NotesBridgeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotesBridgeError';\n }\n}\n\nexport function ensureMacOS(): void {\n if (process.platform !== 'darwin') {\n throw new MacOSUnsupportedError();\n }\n}\n","import fs from 'node:fs/promises';\nimport type { ExportContext } from './export-context';\nimport { getNoteCount, readNoteByIndex } from './notes/reader';\nimport type { NotesReaderOptions } from './notes/types';\nimport { LogLevel, logProgress, setLogLevel } from './notes/jxa-helpers';\nimport { NotesBridgeError } from './notes-bridge';\nimport { writeNoteHtml } from '../services/file-writer';\nimport type { IndexEntry, Note } from '../models/note';\nimport type { DateFilters, FolderFilters } from './filter-schema';\nimport { filterNote } from './filtering';\nimport { createProgressReporter } from './progress-reporter';\n\nexport interface ExportSummary {\n exported: number;\n skipped: Array<{ index: number; reason: string }>;\n indexPath: string;\n notesPath: string;\n firstNote:\n | {\n id: string;\n name: string;\n folderPath: string;\n htmlPath: string;\n }\n | null;\n}\n\nexport async function exportNotes(\n context: ExportContext,\n readerOptions: NotesReaderOptions = {},\n filters: { folders?: FolderFilters; dates?: DateFilters } = {},\n options: { logLevel?: LogLevel } = {}\n): Promise<ExportSummary> {\n if (options.logLevel !== undefined) {\n setLogLevel(options.logLevel);\n }\n logProgress('export.start', { target: context.targetDir });\n const reporter = createProgressReporter();\n const total = await getNoteCount(readerOptions);\n logProgress('export.count', { total });\n const entries: IndexEntry[] = [];\n let first: ExportSummary['firstNote'] = null;\n const skipped: ExportSummary['skipped'] = [];\n for (let i = 0; i < total; i += 1) {\n let note: Note;\n try {\n note = await readNoteByIndex(i, readerOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (error instanceof NotesBridgeError) {\n logProgress('export.skip', { idx: i + 1, reason: message });\n skipped.push({ index: i, reason: message });\n continue;\n }\n throw error;\n }\n const gate = filterNote(note, filters);\n if (!gate.allowed) {\n logProgress('export.skip', { idx: i + 1, reason: 'filtered', folder: note.folderPath });\n skipped.push({ index: i, reason: gate.reason ?? 'Filtered' });\n continue;\n }\n\n logProgress('export.note', { idx: i + 1, id: note.id });\n const result = await writeNoteHtml(note, context.notesPath);\n const entry = {\n noteId: note.id,\n noteName: note.name,\n artifacts: [],\n folderPath: note.folderPath,\n createdAtUtc: note.createdAtUtc,\n modifiedAtUtc: note.modifiedAtUtc,\n htmlPath: result.relativeHtmlPath\n };\n entries.push(entry);\n if (!first) {\n first = {\n id: entry.noteId,\n name: entry.noteName,\n folderPath: entry.folderPath,\n htmlPath: entry.htmlPath\n };\n }\n if (typeof readerOptions.limit === 'number' && entries.length >= readerOptions.limit) {\n break;\n }\n reporter.emit('export.progress', {\n processed: entries.length + skipped.length,\n exported: entries.length,\n skipped: skipped.length,\n total\n });\n }\n\n logProgress('export.written', { count: entries.length });\n await fs.writeFile(context.indexPath, JSON.stringify(entries, null, 2), 'utf8');\n logProgress('export.index.write', { count: entries.length, path: context.indexPath });\n\n return {\n exported: entries.length,\n skipped,\n indexPath: context.indexPath,\n notesPath: context.notesPath,\n firstNote: first\n };\n}\n","import { run } from '@jxa/run';\nimport { ensureMacOS, NotesBridgeError } from '../notes-bridge';\nimport type { Note } from '../../models/note';\nimport type { NotesReaderOptions, RawNoteResult, NotesApp } from './types';\nimport { normalizeNote } from './normalize';\nimport type { RunJxa } from './jxa-helpers';\nimport { debugLog } from './jxa-helpers';\n\ndeclare function Application(name: string): unknown;\n\nexport async function getNoteCount(options: NotesReaderOptions = {}): Promise<number> {\n ensureMacOS();\n const runner: RunJxa = options.runJxa ?? run;\n try {\n const count = (await runner(() => {\n const Notes = Application('Notes') as NotesApp;\n const raw = typeof Notes.notes === 'function' ? Notes.notes() : [];\n const length = (raw as { length?: number }).length;\n return typeof length === 'number' && length >= 0 ? length : 0;\n })) as number;\n const safeCount = typeof count === 'number' && count >= 0 ? count : 0;\n debugLog('notes.count', { count: safeCount });\n return safeCount;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new NotesBridgeError(`Failed to count notes: ${message}`);\n }\n}\n\nexport async function readNoteByIndex(\n index: number,\n options: NotesReaderOptions = {}\n): Promise<Note> {\n ensureMacOS();\n const runner: RunJxa = options.runJxa ?? run;\n try {\n const raw = (await runner((idx: number) => {\n const Notes = Application('Notes') as NotesApp;\n type JxaNote = {\n id?: () => unknown;\n uuid?: () => unknown;\n name?: () => unknown;\n body?: () => unknown;\n container?: () => unknown;\n creationDate?: () => unknown;\n modificationDate?: () => unknown;\n };\n const notes = (typeof Notes.notes === 'function' ? Notes.notes() : []) as JxaNote[];\n\n const inRange = idx >= 0 && idx < (notes as { length: number }).length;\n if (!inRange) return null;\n\n const note: JxaNote | undefined = notes[idx];\n if (!note) return null;\n\n const callMethod = <T>(target: unknown, method: string): T | null => {\n if (!target || typeof (target as Record<string, unknown>)[method] !== 'function') {\n return null;\n }\n try {\n return (target as { [key: string]: () => T })[method]();\n } catch {\n return null;\n }\n };\n\n const containerPath = (): string => {\n const names: string[] = [];\n let current = callMethod<unknown>(note, 'container');\n while (current) {\n const containerName = callMethod<string>(current, 'name');\n if (typeof containerName === 'string' && containerName.trim().length > 0) {\n names.push(containerName);\n }\n current = callMethod<unknown>(current, 'container');\n }\n return names.length ? names.reverse().join('/') : 'Notes';\n };\n\n return {\n id: callMethod(note, 'id') ?? callMethod(note, 'uuid'),\n name: callMethod(note, 'name'),\n bodyHtml: callMethod(note, 'body'),\n folderPath: containerPath(),\n createdAtUtc: callMethod(note, 'creationDate'),\n modifiedAtUtc: callMethod(note, 'modificationDate')\n } satisfies RawNoteResult;\n }, index)) as RawNoteResult | null;\n\n if (!raw) {\n throw new NotesBridgeError(`Note at index ${index} not found.`);\n }\n\n const normalized = normalizeNote(raw, { folderPath: 'Notes' });\n debugLog('notes.read', { index, id: normalized.id, name: normalized.name });\n return normalized;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new NotesBridgeError(`Failed to read note at index ${index}: ${message}`);\n }\n}\n","import type { Note } from '../../models/note';\nimport { NotesBridgeError } from '../notes-bridge';\nimport type { RawNoteResult } from './types';\n\nexport function coerceString(value: unknown): string | null {\n if (value == null) return null;\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n return null;\n}\n\nfunction toIsoString(value: unknown): string | null {\n if (!value) return null;\n if (typeof value === 'string' || value instanceof Date) {\n const date = value instanceof Date ? value : new Date(value);\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n }\n return null;\n}\n\nexport function normalizeNote(raw: RawNoteResult | null, fallback?: Partial<RawNoteResult>): Note {\n const merged: RawNoteResult = {\n id: raw?.id ?? fallback?.id ?? null,\n name: raw?.name ?? fallback?.name ?? null,\n bodyHtml: raw?.bodyHtml ?? fallback?.bodyHtml ?? '',\n folderPath: raw?.folderPath ?? fallback?.folderPath ?? 'Notes',\n createdAtUtc: raw?.createdAtUtc ?? fallback?.createdAtUtc ?? null,\n modifiedAtUtc: raw?.modifiedAtUtc ?? fallback?.modifiedAtUtc ?? null\n };\n\n const id = coerceString(merged.id);\n if (!id) {\n throw new NotesBridgeError('Apple Notes returned a note without an id.');\n }\n\n const name = coerceString(merged.name) ?? id;\n const folderPath = coerceString(merged.folderPath) ?? 'Notes';\n const createdAtUtc = toIsoString(merged.createdAtUtc) ?? new Date().toISOString();\n const modifiedAtUtc = toIsoString(merged.modifiedAtUtc) ?? createdAtUtc;\n const bodyHtml = coerceString(merged.bodyHtml) ?? '';\n\n return {\n id,\n name,\n bodyHtml,\n folderPath,\n createdAtUtc,\n modifiedAtUtc,\n attachments: []\n };\n}\n","export type RunJxa = (fn: (...args: any[]) => any, ...args: any[]) => Promise<any>;\n\nexport enum LogLevel {\n Quiet = 0,\n Info = 1,\n Debug = 2\n}\n\nlet currentLevel: LogLevel = process.env.NOTES_DEBUG ? LogLevel.Debug : LogLevel.Info;\n\nexport const setLogLevel = (level: LogLevel): void => {\n currentLevel = level;\n};\n\nexport const debugLog = (message: string, data?: unknown): void => {\n if (currentLevel < LogLevel.Debug) return;\n const payload = data === undefined ? '' : ` ${JSON.stringify(data)}`;\n console.error(`[notes-debug] ${message}${payload}`);\n};\n\nexport const logProgress = (message: string, data?: unknown): void => {\n if (currentLevel < LogLevel.Info && message !== 'export.progress' && message !== 'export.count' && message !== 'export.start' && message !== 'export.index.write' && message !== 'export.written') {\n return;\n }\n const payload = data === undefined ? '' : ` ${JSON.stringify(data)}`;\n console.error(`[notes] ${message}${payload}`);\n};\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Note } from '../models/note';\nimport { buildNotePath, type NotePathInfo } from './pathing';\n\nexport type WriteNoteResult = NotePathInfo;\n\nexport async function writeNoteHtml(note: Note, notesRoot: string): Promise<WriteNoteResult> {\n const { absoluteHtmlPath, relativeHtmlPath } = buildNotePath(note, notesRoot);\n await fs.mkdir(path.dirname(absoluteHtmlPath), { recursive: true });\n await fs.writeFile(absoluteHtmlPath, note.bodyHtml, 'utf8');\n\n const created = new Date(note.createdAtUtc);\n const modified = new Date(note.modifiedAtUtc);\n const atime = Number.isNaN(created.getTime()) ? new Date() : created;\n const mtime = Number.isNaN(modified.getTime()) ? atime : modified;\n\n await fs.utimes(absoluteHtmlPath, atime, mtime);\n\n return { absoluteHtmlPath, relativeHtmlPath };\n}\n","import path from 'node:path';\nimport type { Note } from '../models/note';\n\nfunction sanitizeSegment(input: string): string {\n const trimmed = input.trim();\n const safe = trimmed\n .replace(/[\\s]+/g, '-')\n .replace(/[^a-zA-Z0-9-_]/g, '')\n .replace(/-+/g, '-')\n .replace(/^[-_]+|[-_]+$/g, '');\n return safe || 'note';\n}\n\nfunction slugifyNote(note: Pick<Note, 'name' | 'id'>): string {\n const namePart = sanitizeSegment(note.name);\n const idPart = sanitizeSegment(note.id);\n return `${namePart}_${idPart}`;\n}\n\nfunction normalizeFolderPath(folderPath: string): string {\n const parts = folderPath.split('/').filter(Boolean).map(sanitizeSegment);\n return parts.join('/');\n}\n\nexport interface NotePathInfo {\n relativeHtmlPath: string;\n absoluteHtmlPath: string;\n}\n\nexport function buildNotePath(note: Note, notesRoot: string): NotePathInfo {\n const folderRel = normalizeFolderPath(note.folderPath || 'Notes');\n const filename = `${slugifyNote(note)}.html`;\n const relativeHtmlPath = path.posix.join(folderRel, filename);\n const absoluteHtmlPath = path.join(notesRoot, relativeHtmlPath);\n return { relativeHtmlPath, absoluteHtmlPath };\n}\n\nexport function defaultSlug(note: Pick<Note, 'name' | 'id'>): string {\n return slugifyNote(note);\n}\n","export interface FolderFilters {\n include?: string[];\n exclude?: string[];\n}\n\nexport interface DateFilters {\n createdAfter?: Date;\n createdBefore?: Date;\n modifiedAfter?: Date;\n modifiedBefore?: Date;\n}\n\nconst normalize = (value: string): string => value.trim().replace(/^\\/+|\\/+$/g, '').toLowerCase();\n\nfunction cleanList(values?: string[]): string[] | undefined {\n if (!values) return undefined;\n const cleaned = values\n .flatMap((v) => v.split(','))\n .map(normalize)\n .filter((v) => v.length > 0);\n return cleaned.length ? cleaned : undefined;\n}\n\nexport function parseFolderFilters(input: {\n includeFolders?: string[];\n excludeFolders?: string[];\n}): FolderFilters {\n return {\n include: cleanList(input.includeFolders),\n exclude: cleanList(input.excludeFolders)\n };\n}\n\nexport function matchesFolder(folderPath: string, filters: FolderFilters): boolean {\n const normalized = normalize(folderPath);\n\n const matchesAny = (needles?: string[]) =>\n needles?.some((needle) => normalized === needle || normalized.startsWith(`${needle}/`)) ?? false;\n\n if (filters.include && !matchesAny(filters.include)) {\n return false;\n }\n if (filters.exclude && matchesAny(filters.exclude)) {\n return false;\n }\n return true;\n}\n\nfunction parseDate(value?: string): Date | undefined {\n if (!value) return undefined;\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(`Invalid date: ${value}`);\n }\n return parsed;\n}\n\nexport function parseDateFilters(input: {\n createdAfter?: string;\n createdBefore?: string;\n modifiedAfter?: string;\n modifiedBefore?: string;\n}): DateFilters {\n return {\n createdAfter: parseDate(input.createdAfter),\n createdBefore: parseDate(input.createdBefore),\n modifiedAfter: parseDate(input.modifiedAfter),\n modifiedBefore: parseDate(input.modifiedBefore)\n };\n}\n","import type { DateFilters, FolderFilters } from './filter-schema';\nimport { matchesFolder } from './filter-schema';\nimport type { Note } from '../models/note';\n\nexport function shouldExportFolder(folderPath: string, filters: FolderFilters): boolean {\n return matchesFolder(folderPath, filters);\n}\n\nfunction matchesDate(value: string, after?: Date, before?: Date): boolean {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return false;\n if (after && parsed.getTime() < after.getTime()) return false;\n if (before && parsed.getTime() > before.getTime()) return false;\n return true;\n}\n\nexport function filterNote(\n note: Note,\n filters: { folders?: FolderFilters; dates?: DateFilters }\n): { allowed: boolean; reason?: string } {\n const folderFilters = filters.folders ?? {};\n if (!shouldExportFolder(note.folderPath, folderFilters)) {\n return { allowed: false, reason: `Filtered by folder: ${note.folderPath}` };\n }\n\n const dateFilters = filters.dates ?? {};\n const createdOk = matchesDate(note.createdAtUtc, dateFilters.createdAfter, dateFilters.createdBefore);\n const modifiedOk = matchesDate(note.modifiedAtUtc, dateFilters.modifiedAfter, dateFilters.modifiedBefore);\n\n if (!createdOk || !modifiedOk) {\n return { allowed: false, reason: 'Filtered by date' };\n }\n\n return { allowed: true };\n}\n","import { logProgress } from './notes/jxa-helpers';\n\ntype EventName =\n | 'export.progress'\n | 'export.start'\n | 'export.count'\n | 'export.note'\n | 'export.skip'\n | 'export.written'\n | 'export.index.write';\n\ninterface ProgressReporterOptions {\n /**\n * Minimum milliseconds between emissions of repeated progress events.\n */\n rateMs?: number;\n}\n\nexport class ProgressReporter {\n private lastAt = 0;\n private readonly rateMs: number;\n\n constructor(options: ProgressReporterOptions = {}) {\n this.rateMs = options.rateMs ?? 2000;\n }\n\n emit(event: EventName, data?: unknown, force = false): void {\n const now = Date.now();\n if (!force && now - this.lastAt < this.rateMs && event === 'export.progress') {\n return;\n }\n this.lastAt = now;\n logProgress(event, data);\n }\n}\n\nexport const createProgressReporter = (options?: ProgressReporterOptions): ProgressReporter =>\n new ProgressReporter(options);\n","import { main } from './index';\n\nvoid main(process.argv);\n"],"mappings":"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","names":["fs","fs","path","path","fs","path","fs","require"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/index.ts","../src/lib/export-context.ts","../src/lib/notes-bridge.ts","../src/lib/export-runner.ts","../src/lib/notes/reader.ts","../src/lib/notes/normalize.ts","../src/lib/notes/jxa-helpers.ts","../src/services/file-writer.ts","../src/services/pathing.ts","../src/lib/filter-schema.ts","../src/lib/filtering.ts","../src/lib/progress-reporter.ts","../src/cli/entry.ts"],"sourcesContent":["import { Command } from 'commander';\nimport { z } from 'zod';\nimport { createRequire } from 'node:module';\nimport { createExportContext } from '../lib/export-context';\nimport { ensureMacOS } from '../lib/notes-bridge';\nimport { exportNotes } from '../lib/export-runner';\nimport { parseFolderFilters, parseDateFilters } from '../lib/filter-schema';\n\nconst require = createRequire(import.meta.url);\n// Keep CLI usable from both compiled dist/ and ts-node/src:\n// - dist/cli.js sits beside dist/package.json -> ../package.json\n// - src/cli/index.ts sits under src/ -> ../../package.json\nconst cliPath = new URL('.', import.meta.url).pathname;\nconst pkgUrl = cliPath.includes('/dist/')\n ? new URL('../package.json', import.meta.url)\n : new URL('../../package.json', import.meta.url);\nconst version =\n (require(pkgUrl.pathname) as { version?: string }).version ??\n 'unknown';\n\nconst cliSchema = z.object({\n target: z.string().min(1, 'Target directory is required'),\n force: z.boolean().optional(),\n includeAttachments: z.boolean().optional(),\n includeFolder: z.array(z.string()).optional(),\n excludeFolder: z.array(z.string()).optional(),\n createdAfter: z.string().optional(),\n createdBefore: z.string().optional(),\n modifiedAfter: z.string().optional(),\n modifiedBefore: z.string().optional(),\n quiet: z.boolean().optional(),\n verbose: z.number().int().nonnegative().optional()\n});\n\nexport async function main(argv: string[]): Promise<void> {\n const program = new Command();\n program\n .name('apple-notes-export')\n .description('Apple Notes export CLI (MVP smoke run)')\n .version(version)\n .requiredOption('-t, --target <dir>', 'Absolute path to target directory')\n .option('-f, --force', 'Allow non-empty target directory', false)\n .option('--include-attachments', 'Attachments export is not yet implemented', false)\n .option('--include-folder <paths...>', 'Include only folders (prefix match)', [])\n .option('--exclude-folder <paths...>', 'Exclude folders (prefix match)', [])\n .option('--created-after <iso>', 'Only export notes created on/after this UTC date')\n .option('--created-before <iso>', 'Only export notes created on/before this UTC date')\n .option('--modified-after <iso>', 'Only export notes modified on/after this UTC date')\n .option('--modified-before <iso>', 'Only export notes modified on/before this UTC date')\n .option('-q, --quiet', 'Reduce log noise (progress only)', false)\n .option(\n '-v, --verbose',\n 'Increase verbosity (repeat for more detail)',\n (_value, previous: number) => previous + 1,\n 0\n );\n\n program.exitOverride();\n\n try {\n program.parse(argv);\n const options = program.opts<{\n target: string;\n force?: boolean;\n includeAttachments?: boolean;\n includeFolder?: string[];\n excludeFolder?: string[];\n createdAfter?: string;\n createdBefore?: string;\n modifiedAfter?: string;\n modifiedBefore?: string;\n quiet?: boolean;\n verbose?: number;\n }>();\n const parsed = cliSchema.parse({\n target: options.target,\n force: Boolean(options.force),\n includeAttachments: Boolean(options.includeAttachments),\n includeFolder: options.includeFolder,\n excludeFolder: options.excludeFolder,\n createdAfter: options.createdAfter,\n createdBefore: options.createdBefore,\n modifiedAfter: options.modifiedAfter,\n modifiedBefore: options.modifiedBefore,\n quiet: Boolean(options.quiet),\n verbose: options.verbose\n });\n\n ensureMacOS();\n\n if (parsed.includeAttachments) {\n // Attachments are deferred; keep UX explicit.\n process.stderr.write('Warning: --include-attachments is not implemented yet; continuing without attachments.\\n');\n }\n\n const context = await createExportContext({\n targetDir: parsed.target,\n force: parsed.force,\n includeAttachments: false\n });\n\n const filters = parseFolderFilters({\n includeFolders: parsed.includeFolder,\n excludeFolders: parsed.excludeFolder\n });\n\n const dateFilters = parseDateFilters({\n createdAfter: parsed.createdAfter,\n createdBefore: parsed.createdBefore,\n modifiedAfter: parsed.modifiedAfter,\n modifiedBefore: parsed.modifiedBefore\n });\n\n const logLevel = parsed.quiet ? 0 : Math.min(2, (parsed.verbose ?? 0) + 1);\n\n const result = await exportNotes(\n context,\n {},\n { folders: filters, dates: dateFilters },\n { logLevel }\n );\n\n const summary = {\n status: 'ok',\n indexPath: result.indexPath,\n notesPath: result.notesPath,\n exported: result.exported,\n skipped: result.skipped,\n firstNote: result.firstNote\n };\n\n process.stdout.write(JSON.stringify(summary, null, 2) + '\\n');\n process.exitCode = 0;\n } catch (error) {\n const maybeCommanderError = error as Error & { code?: string };\n if (maybeCommanderError?.code === 'commander.executeSubCommandAsync') {\n throw error;\n }\n if (\n maybeCommanderError?.code === 'commander.helpDisplayed' ||\n maybeCommanderError?.code === 'commander.version'\n ) {\n process.exitCode = 0;\n return;\n }\n process.stderr.write(`Error: ${(maybeCommanderError as Error).message}\\n`);\n process.exitCode = 1;\n }\n}\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nconst INDEX_FILENAME = 'index.json';\n\nexport interface ExportConfig {\n targetDir: string;\n force?: boolean;\n includeAttachments?: boolean;\n}\n\nexport interface ExportContext {\n targetDir: string;\n notesPath: string;\n artifactsPath: string;\n indexPath: string;\n includeAttachments: boolean;\n}\n\nasync function ensureDirectoryExists(targetDir: string): Promise<void> {\n await fs.mkdir(targetDir, { recursive: true });\n}\n\nasync function isDirectoryEmpty(dir: string, allowedNames: string[] = []): Promise<boolean> {\n const entries = await fs.readdir(dir);\n const meaningful = entries.filter((name) => !allowedNames.includes(name));\n return meaningful.length === 0;\n}\n\nexport async function validateTargetDirectory(targetDir: string, force: boolean): Promise<void> {\n const stats = await fs.stat(targetDir).catch(() => undefined);\n if (!stats) {\n return;\n }\n if (!stats.isDirectory()) {\n throw new Error(`Target path must be a directory: ${targetDir}`);\n }\n // Some environments drop a node-compile-cache folder beside the app; allow it when empty otherwise.\n const allowed = ['node-compile-cache'];\n if (!(await isDirectoryEmpty(targetDir, allowed)) && !force) {\n throw new Error('Target directory must be empty unless --force is provided.');\n }\n}\n\nexport async function createExportContext(config: ExportConfig): Promise<ExportContext> {\n if (!path.isAbsolute(config.targetDir)) {\n throw new Error('Target directory must be an absolute path.');\n }\n\n const force = Boolean(config.force);\n const includeAttachments = Boolean(config.includeAttachments);\n\n await ensureDirectoryExists(config.targetDir);\n await validateTargetDirectory(config.targetDir, force);\n\n const notesPath = path.join(config.targetDir, 'notes');\n const artifactsPath = path.join(config.targetDir, 'artifacts');\n const indexPath = path.join(config.targetDir, INDEX_FILENAME);\n\n await fs.mkdir(notesPath, { recursive: true });\n if (includeAttachments) {\n await fs.mkdir(artifactsPath, { recursive: true });\n }\n\n return {\n targetDir: config.targetDir,\n notesPath,\n artifactsPath,\n indexPath,\n includeAttachments\n };\n}\n","export class MacOSUnsupportedError extends Error {\n constructor(message = 'Apple Notes export requires macOS.') {\n super(message);\n this.name = 'MacOSUnsupportedError';\n }\n}\n\nexport class NotesBridgeError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'NotesBridgeError';\n }\n}\n\nexport function ensureMacOS(): void {\n if (process.platform !== 'darwin') {\n throw new MacOSUnsupportedError();\n }\n}\n","import fs from 'node:fs/promises';\nimport type { ExportContext } from './export-context';\nimport { getNoteCount, readNoteByIndex } from './notes/reader';\nimport type { NotesReaderOptions } from './notes/types';\nimport { LogLevel, logProgress, setLogLevel } from './notes/jxa-helpers';\nimport { NotesBridgeError } from './notes-bridge';\nimport { writeNoteHtml } from '../services/file-writer';\nimport type { IndexEntry, Note } from '../models/note';\nimport type { DateFilters, FolderFilters } from './filter-schema';\nimport { filterNote } from './filtering';\nimport { createProgressReporter } from './progress-reporter';\n\nexport interface ExportSummary {\n exported: number;\n skipped: Array<{ index: number; reason: string }>;\n indexPath: string;\n notesPath: string;\n firstNote:\n | {\n id: string;\n name: string;\n folderPath: string;\n htmlPath: string;\n }\n | null;\n}\n\nexport async function exportNotes(\n context: ExportContext,\n readerOptions: NotesReaderOptions = {},\n filters: { folders?: FolderFilters; dates?: DateFilters } = {},\n options: { logLevel?: LogLevel } = {}\n): Promise<ExportSummary> {\n if (options.logLevel !== undefined) {\n setLogLevel(options.logLevel);\n }\n logProgress('export.start', { target: context.targetDir });\n const reporter = createProgressReporter();\n const total = await getNoteCount(readerOptions);\n logProgress('export.count', { total });\n const entries: IndexEntry[] = [];\n let first: ExportSummary['firstNote'] = null;\n const skipped: ExportSummary['skipped'] = [];\n for (let i = 0; i < total; i += 1) {\n let note: Note;\n try {\n note = await readNoteByIndex(i, readerOptions);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (error instanceof NotesBridgeError) {\n logProgress('export.skip', { idx: i + 1, reason: message });\n skipped.push({ index: i, reason: message });\n continue;\n }\n throw error;\n }\n const gate = filterNote(note, filters);\n if (!gate.allowed) {\n logProgress('export.skip', { idx: i + 1, reason: 'filtered', folder: note.folderPath });\n skipped.push({ index: i, reason: gate.reason ?? 'Filtered' });\n continue;\n }\n\n logProgress('export.note', { idx: i + 1, id: note.id });\n const result = await writeNoteHtml(note, context.notesPath);\n const entry = {\n noteId: note.id,\n noteName: note.name,\n artifacts: [],\n folderPath: note.folderPath,\n createdAtUtc: note.createdAtUtc,\n modifiedAtUtc: note.modifiedAtUtc,\n htmlPath: result.relativeHtmlPath\n };\n entries.push(entry);\n if (!first) {\n first = {\n id: entry.noteId,\n name: entry.noteName,\n folderPath: entry.folderPath,\n htmlPath: entry.htmlPath\n };\n }\n if (typeof readerOptions.limit === 'number' && entries.length >= readerOptions.limit) {\n break;\n }\n reporter.emit('export.progress', {\n processed: entries.length + skipped.length,\n exported: entries.length,\n skipped: skipped.length,\n total\n });\n }\n\n logProgress('export.written', { count: entries.length });\n await fs.writeFile(context.indexPath, JSON.stringify(entries, null, 2), 'utf8');\n logProgress('export.index.write', { count: entries.length, path: context.indexPath });\n\n return {\n exported: entries.length,\n skipped,\n indexPath: context.indexPath,\n notesPath: context.notesPath,\n firstNote: first\n };\n}\n","import { run } from '@jxa/run';\nimport { ensureMacOS, NotesBridgeError } from '../notes-bridge';\nimport type { Note } from '../../models/note';\nimport type { NotesReaderOptions, RawNoteResult, NotesApp } from './types';\nimport { normalizeNote } from './normalize';\nimport type { RunJxa } from './jxa-helpers';\nimport { debugLog } from './jxa-helpers';\n\ndeclare function Application(name: string): unknown;\n\nexport async function getNoteCount(options: NotesReaderOptions = {}): Promise<number> {\n ensureMacOS();\n const runner: RunJxa = options.runJxa ?? run;\n try {\n const count = (await runner(() => {\n const Notes = Application('Notes') as NotesApp;\n const raw = typeof Notes.notes === 'function' ? Notes.notes() : [];\n const length = (raw as { length?: number }).length;\n return typeof length === 'number' && length >= 0 ? length : 0;\n })) as number;\n const safeCount = typeof count === 'number' && count >= 0 ? count : 0;\n debugLog('notes.count', { count: safeCount });\n return safeCount;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new NotesBridgeError(`Failed to count notes: ${message}`);\n }\n}\n\nexport async function readNoteByIndex(\n index: number,\n options: NotesReaderOptions = {}\n): Promise<Note> {\n ensureMacOS();\n const runner: RunJxa = options.runJxa ?? run;\n try {\n const raw = (await runner((idx: number) => {\n const Notes = Application('Notes') as NotesApp;\n type JxaNote = {\n id?: () => unknown;\n uuid?: () => unknown;\n name?: () => unknown;\n body?: () => unknown;\n container?: () => unknown;\n creationDate?: () => unknown;\n modificationDate?: () => unknown;\n };\n const notes = (typeof Notes.notes === 'function' ? Notes.notes() : []) as JxaNote[];\n\n const inRange = idx >= 0 && idx < (notes as { length: number }).length;\n if (!inRange) return null;\n\n const note: JxaNote | undefined = notes[idx];\n if (!note) return null;\n\n const callMethod = <T>(target: unknown, method: string): T | null => {\n if (!target || typeof (target as Record<string, unknown>)[method] !== 'function') {\n return null;\n }\n try {\n return (target as { [key: string]: () => T })[method]();\n } catch {\n return null;\n }\n };\n\n const containerPath = (): string => {\n const names: string[] = [];\n let current = callMethod<unknown>(note, 'container');\n while (current) {\n const containerName = callMethod<string>(current, 'name');\n if (typeof containerName === 'string' && containerName.trim().length > 0) {\n names.push(containerName);\n }\n current = callMethod<unknown>(current, 'container');\n }\n return names.length ? names.reverse().join('/') : 'Notes';\n };\n\n return {\n id: callMethod(note, 'id') ?? callMethod(note, 'uuid'),\n name: callMethod(note, 'name'),\n bodyHtml: callMethod(note, 'body'),\n folderPath: containerPath(),\n createdAtUtc: callMethod(note, 'creationDate'),\n modifiedAtUtc: callMethod(note, 'modificationDate')\n } satisfies RawNoteResult;\n }, index)) as RawNoteResult | null;\n\n if (!raw) {\n throw new NotesBridgeError(`Note at index ${index} not found.`);\n }\n\n const normalized = normalizeNote(raw, { folderPath: 'Notes' });\n debugLog('notes.read', { index, id: normalized.id, name: normalized.name });\n return normalized;\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n throw new NotesBridgeError(`Failed to read note at index ${index}: ${message}`);\n }\n}\n","import type { Note } from '../../models/note';\nimport { NotesBridgeError } from '../notes-bridge';\nimport type { RawNoteResult } from './types';\n\nexport function coerceString(value: unknown): string | null {\n if (value == null) return null;\n if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n return null;\n}\n\nfunction toIsoString(value: unknown): string | null {\n if (!value) return null;\n if (typeof value === 'string' || value instanceof Date) {\n const date = value instanceof Date ? value : new Date(value);\n return Number.isNaN(date.getTime()) ? null : date.toISOString();\n }\n return null;\n}\n\nexport function normalizeNote(raw: RawNoteResult | null, fallback?: Partial<RawNoteResult>): Note {\n const merged: RawNoteResult = {\n id: raw?.id ?? fallback?.id ?? null,\n name: raw?.name ?? fallback?.name ?? null,\n bodyHtml: raw?.bodyHtml ?? fallback?.bodyHtml ?? '',\n folderPath: raw?.folderPath ?? fallback?.folderPath ?? 'Notes',\n createdAtUtc: raw?.createdAtUtc ?? fallback?.createdAtUtc ?? null,\n modifiedAtUtc: raw?.modifiedAtUtc ?? fallback?.modifiedAtUtc ?? null\n };\n\n const id = coerceString(merged.id);\n if (!id) {\n throw new NotesBridgeError('Apple Notes returned a note without an id.');\n }\n\n const name = coerceString(merged.name) ?? id;\n const folderPath = coerceString(merged.folderPath) ?? 'Notes';\n const createdAtUtc = toIsoString(merged.createdAtUtc) ?? new Date().toISOString();\n const modifiedAtUtc = toIsoString(merged.modifiedAtUtc) ?? createdAtUtc;\n const bodyHtml = coerceString(merged.bodyHtml) ?? '';\n\n return {\n id,\n name,\n bodyHtml,\n folderPath,\n createdAtUtc,\n modifiedAtUtc,\n attachments: []\n };\n}\n","export type RunJxa = (fn: (...args: any[]) => any, ...args: any[]) => Promise<any>;\n\nexport enum LogLevel {\n Quiet = 0,\n Info = 1,\n Debug = 2\n}\n\nlet currentLevel: LogLevel = process.env.NOTES_DEBUG ? LogLevel.Debug : LogLevel.Info;\n\nexport const setLogLevel = (level: LogLevel): void => {\n currentLevel = level;\n};\n\nexport const debugLog = (message: string, data?: unknown): void => {\n if (currentLevel < LogLevel.Debug) return;\n const payload = data === undefined ? '' : ` ${JSON.stringify(data)}`;\n console.error(`[notes-debug] ${message}${payload}`);\n};\n\nexport const logProgress = (message: string, data?: unknown): void => {\n if (currentLevel < LogLevel.Info && message !== 'export.progress' && message !== 'export.count' && message !== 'export.start' && message !== 'export.index.write' && message !== 'export.written') {\n return;\n }\n const payload = data === undefined ? '' : ` ${JSON.stringify(data)}`;\n console.error(`[notes] ${message}${payload}`);\n};\n","import fs from 'node:fs/promises';\nimport path from 'node:path';\nimport type { Note } from '../models/note';\nimport { buildNotePath, type NotePathInfo } from './pathing';\n\nexport type WriteNoteResult = NotePathInfo;\n\nexport async function writeNoteHtml(note: Note, notesRoot: string): Promise<WriteNoteResult> {\n const { absoluteHtmlPath, relativeHtmlPath } = buildNotePath(note, notesRoot);\n await fs.mkdir(path.dirname(absoluteHtmlPath), { recursive: true });\n await fs.writeFile(absoluteHtmlPath, note.bodyHtml, 'utf8');\n\n const created = new Date(note.createdAtUtc);\n const modified = new Date(note.modifiedAtUtc);\n const atime = Number.isNaN(created.getTime()) ? new Date() : created;\n const mtime = Number.isNaN(modified.getTime()) ? atime : modified;\n\n await fs.utimes(absoluteHtmlPath, atime, mtime);\n\n return { absoluteHtmlPath, relativeHtmlPath };\n}\n","import path from 'node:path';\nimport type { Note } from '../models/note';\n\nfunction sanitizeSegment(input: string): string {\n const trimmed = input.trim();\n const safe = trimmed\n .replace(/[\\s]+/g, '-')\n .replace(/[^a-zA-Z0-9-_]/g, '')\n .replace(/-+/g, '-')\n .replace(/^[-_]+|[-_]+$/g, '');\n return safe || 'note';\n}\n\nfunction slugifyNote(note: Pick<Note, 'name' | 'id'>): string {\n const namePart = sanitizeSegment(note.name);\n const idPart = sanitizeSegment(note.id);\n return `${namePart}_${idPart}`;\n}\n\nfunction normalizeFolderPath(folderPath: string): string {\n const parts = folderPath.split('/').filter(Boolean).map(sanitizeSegment);\n return parts.join('/');\n}\n\nexport interface NotePathInfo {\n relativeHtmlPath: string;\n absoluteHtmlPath: string;\n}\n\nexport function buildNotePath(note: Note, notesRoot: string): NotePathInfo {\n const folderRel = normalizeFolderPath(note.folderPath || 'Notes');\n const filename = `${slugifyNote(note)}.html`;\n const relativeHtmlPath = path.posix.join(folderRel, filename);\n const absoluteHtmlPath = path.join(notesRoot, relativeHtmlPath);\n return { relativeHtmlPath, absoluteHtmlPath };\n}\n\nexport function defaultSlug(note: Pick<Note, 'name' | 'id'>): string {\n return slugifyNote(note);\n}\n","export interface FolderFilters {\n include?: string[];\n exclude?: string[];\n}\n\nexport interface DateFilters {\n createdAfter?: Date;\n createdBefore?: Date;\n modifiedAfter?: Date;\n modifiedBefore?: Date;\n}\n\nconst normalize = (value: string): string => value.trim().replace(/^\\/+|\\/+$/g, '').toLowerCase();\n\nfunction cleanList(values?: string[]): string[] | undefined {\n if (!values) return undefined;\n const cleaned = values\n .flatMap((v) => v.split(','))\n .map(normalize)\n .filter((v) => v.length > 0);\n return cleaned.length ? cleaned : undefined;\n}\n\nexport function parseFolderFilters(input: {\n includeFolders?: string[];\n excludeFolders?: string[];\n}): FolderFilters {\n return {\n include: cleanList(input.includeFolders),\n exclude: cleanList(input.excludeFolders)\n };\n}\n\nexport function matchesFolder(folderPath: string, filters: FolderFilters): boolean {\n const normalized = normalize(folderPath);\n\n const matchesAny = (needles?: string[]) =>\n needles?.some((needle) => normalized === needle || normalized.startsWith(`${needle}/`)) ?? false;\n\n if (filters.include && !matchesAny(filters.include)) {\n return false;\n }\n if (filters.exclude && matchesAny(filters.exclude)) {\n return false;\n }\n return true;\n}\n\nfunction parseDate(value?: string): Date | undefined {\n if (!value) return undefined;\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) {\n throw new Error(`Invalid date: ${value}`);\n }\n return parsed;\n}\n\nexport function parseDateFilters(input: {\n createdAfter?: string;\n createdBefore?: string;\n modifiedAfter?: string;\n modifiedBefore?: string;\n}): DateFilters {\n return {\n createdAfter: parseDate(input.createdAfter),\n createdBefore: parseDate(input.createdBefore),\n modifiedAfter: parseDate(input.modifiedAfter),\n modifiedBefore: parseDate(input.modifiedBefore)\n };\n}\n","import type { DateFilters, FolderFilters } from './filter-schema';\nimport { matchesFolder } from './filter-schema';\nimport type { Note } from '../models/note';\n\nexport function shouldExportFolder(folderPath: string, filters: FolderFilters): boolean {\n return matchesFolder(folderPath, filters);\n}\n\nfunction matchesDate(value: string, after?: Date, before?: Date): boolean {\n const parsed = new Date(value);\n if (Number.isNaN(parsed.getTime())) return false;\n if (after && parsed.getTime() < after.getTime()) return false;\n if (before && parsed.getTime() > before.getTime()) return false;\n return true;\n}\n\nexport function filterNote(\n note: Note,\n filters: { folders?: FolderFilters; dates?: DateFilters }\n): { allowed: boolean; reason?: string } {\n const folderFilters = filters.folders ?? {};\n if (!shouldExportFolder(note.folderPath, folderFilters)) {\n return { allowed: false, reason: `Filtered by folder: ${note.folderPath}` };\n }\n\n const dateFilters = filters.dates ?? {};\n const createdOk = matchesDate(note.createdAtUtc, dateFilters.createdAfter, dateFilters.createdBefore);\n const modifiedOk = matchesDate(note.modifiedAtUtc, dateFilters.modifiedAfter, dateFilters.modifiedBefore);\n\n if (!createdOk || !modifiedOk) {\n return { allowed: false, reason: 'Filtered by date' };\n }\n\n return { allowed: true };\n}\n","import { logProgress } from './notes/jxa-helpers';\n\ntype EventName =\n | 'export.progress'\n | 'export.start'\n | 'export.count'\n | 'export.note'\n | 'export.skip'\n | 'export.written'\n | 'export.index.write';\n\ninterface ProgressReporterOptions {\n /**\n * Minimum milliseconds between emissions of repeated progress events.\n */\n rateMs?: number;\n}\n\nexport class ProgressReporter {\n private lastAt = 0;\n private readonly rateMs: number;\n\n constructor(options: ProgressReporterOptions = {}) {\n this.rateMs = options.rateMs ?? 2000;\n }\n\n emit(event: EventName, data?: unknown, force = false): void {\n const now = Date.now();\n if (!force && now - this.lastAt < this.rateMs && event === 'export.progress') {\n return;\n }\n this.lastAt = now;\n logProgress(event, data);\n }\n}\n\nexport const createProgressReporter = (options?: ProgressReporterOptions): ProgressReporter =>\n new ProgressReporter(options);\n","import { main } from './index';\n\nvoid main(process.argv);\n"],"mappings":"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","names":["fs","fs","path","path","fs","path","fs","require"]}
|