@rewrlution/papyrus-cli 0.0.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.
Files changed (125) hide show
  1. package/README.md +699 -0
  2. package/dist/cli.d.ts +2 -0
  3. package/dist/cli.js +16 -0
  4. package/dist/cli.js.map +1 -0
  5. package/dist/commands/auth/index.d.ts +2 -0
  6. package/dist/commands/auth/index.js +18 -0
  7. package/dist/commands/auth/index.js.map +1 -0
  8. package/dist/commands/auth/login.d.ts +1 -0
  9. package/dist/commands/auth/login.js +8 -0
  10. package/dist/commands/auth/login.js.map +1 -0
  11. package/dist/commands/auth/logout.d.ts +1 -0
  12. package/dist/commands/auth/logout.js +5 -0
  13. package/dist/commands/auth/logout.js.map +1 -0
  14. package/dist/commands/auth/register.d.ts +1 -0
  15. package/dist/commands/auth/register.js +8 -0
  16. package/dist/commands/auth/register.js.map +1 -0
  17. package/dist/commands/index.d.ts +2 -0
  18. package/dist/commands/index.js +3 -0
  19. package/dist/commands/index.js.map +1 -0
  20. package/dist/commands/journal/add.d.ts +2 -0
  21. package/dist/commands/journal/add.js +5 -0
  22. package/dist/commands/journal/add.js.map +1 -0
  23. package/dist/commands/journal/amend.d.ts +2 -0
  24. package/dist/commands/journal/amend.js +5 -0
  25. package/dist/commands/journal/amend.js.map +1 -0
  26. package/dist/commands/journal/edit.d.ts +6 -0
  27. package/dist/commands/journal/edit.js +60 -0
  28. package/dist/commands/journal/edit.js.map +1 -0
  29. package/dist/commands/journal/index.d.ts +2 -0
  30. package/dist/commands/journal/index.js +32 -0
  31. package/dist/commands/journal/index.js.map +1 -0
  32. package/dist/commands/journal/list.d.ts +1 -0
  33. package/dist/commands/journal/list.js +20 -0
  34. package/dist/commands/journal/list.js.map +1 -0
  35. package/dist/commands/journal/show.d.ts +2 -0
  36. package/dist/commands/journal/show.js +35 -0
  37. package/dist/commands/journal/show.js.map +1 -0
  38. package/dist/commands/journal/sync.d.ts +1 -0
  39. package/dist/commands/journal/sync.js +9 -0
  40. package/dist/commands/journal/sync.js.map +1 -0
  41. package/dist/commands/types.d.ts +9 -0
  42. package/dist/commands/types.js +2 -0
  43. package/dist/commands/types.js.map +1 -0
  44. package/dist/components/Browser.d.ts +29 -0
  45. package/dist/components/Browser.js +124 -0
  46. package/dist/components/Browser.js.map +1 -0
  47. package/dist/components/BrowserFooter.d.ts +6 -0
  48. package/dist/components/BrowserFooter.js +6 -0
  49. package/dist/components/BrowserFooter.js.map +1 -0
  50. package/dist/components/BrowserHeader.d.ts +6 -0
  51. package/dist/components/BrowserHeader.js +6 -0
  52. package/dist/components/BrowserHeader.js.map +1 -0
  53. package/dist/components/ColdStart.d.ts +6 -0
  54. package/dist/components/ColdStart.js +24 -0
  55. package/dist/components/ColdStart.js.map +1 -0
  56. package/dist/components/FormInput.d.ts +10 -0
  57. package/dist/components/FormInput.js +7 -0
  58. package/dist/components/FormInput.js.map +1 -0
  59. package/dist/components/JournalListView.d.ts +10 -0
  60. package/dist/components/JournalListView.js +40 -0
  61. package/dist/components/JournalListView.js.map +1 -0
  62. package/dist/components/JournalViewer.d.ts +32 -0
  63. package/dist/components/JournalViewer.js +146 -0
  64. package/dist/components/JournalViewer.js.map +1 -0
  65. package/dist/components/LoginForm.d.ts +1 -0
  66. package/dist/components/LoginForm.js +68 -0
  67. package/dist/components/LoginForm.js.map +1 -0
  68. package/dist/components/Logo.d.ts +1 -0
  69. package/dist/components/Logo.js +57 -0
  70. package/dist/components/Logo.js.map +1 -0
  71. package/dist/components/RegisterForm.d.ts +1 -0
  72. package/dist/components/RegisterForm.js +72 -0
  73. package/dist/components/RegisterForm.js.map +1 -0
  74. package/dist/components/StatusMessage.d.ts +7 -0
  75. package/dist/components/StatusMessage.js +19 -0
  76. package/dist/components/StatusMessage.js.map +1 -0
  77. package/dist/components/SyncProgress.d.ts +1 -0
  78. package/dist/components/SyncProgress.js +46 -0
  79. package/dist/components/SyncProgress.js.map +1 -0
  80. package/dist/lib/api/api-client.d.ts +23 -0
  81. package/dist/lib/api/api-client.js +111 -0
  82. package/dist/lib/api/api-client.js.map +1 -0
  83. package/dist/lib/api/index.d.ts +3 -0
  84. package/dist/lib/api/index.js +6 -0
  85. package/dist/lib/api/index.js.map +1 -0
  86. package/dist/lib/auth/index.d.ts +1 -0
  87. package/dist/lib/auth/index.js +2 -0
  88. package/dist/lib/auth/index.js.map +1 -0
  89. package/dist/lib/auth/require-auth.d.ts +67 -0
  90. package/dist/lib/auth/require-auth.js +107 -0
  91. package/dist/lib/auth/require-auth.js.map +1 -0
  92. package/dist/lib/storage/base-storage.d.ts +50 -0
  93. package/dist/lib/storage/base-storage.js +91 -0
  94. package/dist/lib/storage/base-storage.js.map +1 -0
  95. package/dist/lib/storage/config-store.d.ts +40 -0
  96. package/dist/lib/storage/config-store.js +63 -0
  97. package/dist/lib/storage/config-store.js.map +1 -0
  98. package/dist/lib/storage/index.d.ts +12 -0
  99. package/dist/lib/storage/index.js +13 -0
  100. package/dist/lib/storage/index.js.map +1 -0
  101. package/dist/lib/storage/journal-storage.d.ts +46 -0
  102. package/dist/lib/storage/journal-storage.js +78 -0
  103. package/dist/lib/storage/journal-storage.js.map +1 -0
  104. package/dist/lib/storage/sync-meta-store.d.ts +37 -0
  105. package/dist/lib/storage/sync-meta-store.js +50 -0
  106. package/dist/lib/storage/sync-meta-store.js.map +1 -0
  107. package/dist/lib/storage/token-store.d.ts +25 -0
  108. package/dist/lib/storage/token-store.js +40 -0
  109. package/dist/lib/storage/token-store.js.map +1 -0
  110. package/dist/lib/sync/sync-engine.d.ts +13 -0
  111. package/dist/lib/sync/sync-engine.js +96 -0
  112. package/dist/lib/sync/sync-engine.js.map +1 -0
  113. package/dist/utils/date.d.ts +58 -0
  114. package/dist/utils/date.js +117 -0
  115. package/dist/utils/date.js.map +1 -0
  116. package/dist/utils/editor.d.ts +2 -0
  117. package/dist/utils/editor.js +81 -0
  118. package/dist/utils/editor.js.map +1 -0
  119. package/dist/utils/template.d.ts +2 -0
  120. package/dist/utils/template.js +17 -0
  121. package/dist/utils/template.js.map +1 -0
  122. package/dist/utils/token.d.ts +20 -0
  123. package/dist/utils/token.js +64 -0
  124. package/dist/utils/token.js.map +1 -0
  125. package/package.json +53 -0
@@ -0,0 +1,40 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ import { formatDate } from '../utils/date.js';
4
+ export const JournalListView = ({ journals, selectedIndex, todayDate, windowSize = 10, }) => {
5
+ // Virtual scrolling logic - show a window around the selected index
6
+ const getVisibleJournals = () => {
7
+ const total = journals.length;
8
+ if (total <= windowSize)
9
+ return journals;
10
+ const halfWindow = Math.floor(windowSize / 2);
11
+ let start = selectedIndex - halfWindow;
12
+ let end = selectedIndex + halfWindow;
13
+ // Adjust if window goes out of bounds
14
+ if (start < 0) {
15
+ start = 0;
16
+ end = windowSize;
17
+ }
18
+ else if (end > total) {
19
+ end = total;
20
+ start = total - windowSize;
21
+ }
22
+ return journals.slice(start, end);
23
+ };
24
+ const visibleJournals = getVisibleJournals();
25
+ const showMoreAbove = selectedIndex > Math.floor(windowSize / 2);
26
+ const showMoreBelow = selectedIndex < journals.length - Math.floor(windowSize / 2) - 1;
27
+ return (_jsxs(Box, { flexDirection: "column", marginTop: 1, borderStyle: "round", paddingX: 1, paddingY: 1, children: [showMoreAbove && (_jsx(Box, { justifyContent: "center", children: _jsx(Text, { dimColor: true, children: "\u2191 More above" }) })), visibleJournals.map((journal) => {
28
+ // Find actual index in full array
29
+ const actualIndex = journals.findIndex((j) => j.date === journal.date);
30
+ const isSelected = actualIndex === selectedIndex;
31
+ const isToday = journal.date === todayDate;
32
+ return (_jsx(JournalItem, { journal: journal, isSelected: isSelected, isToday: isToday }, journal.date));
33
+ }), showMoreBelow && (_jsx(Box, { justifyContent: "center", children: _jsx(Text, { dimColor: true, children: "\u2193 More below" }) }))] }));
34
+ };
35
+ const JournalItem = ({ journal, isSelected, isToday, }) => {
36
+ // Format date for display
37
+ const formattedDate = formatDate(journal.date);
38
+ return (_jsxs(Box, { children: [_jsx(Text, { color: isSelected ? 'cyan' : 'white', children: isSelected ? '> ' : ' ' }), _jsx(Text, { color: isSelected ? 'cyan' : 'white', children: formattedDate }), _jsxs(Text, { dimColor: true, children: [" (", journal.date, ".md)"] }), isToday && _jsx(Text, { color: "blue", children: " \u25CF" })] }));
39
+ };
40
+ //# sourceMappingURL=JournalListView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JournalListView.js","sourceRoot":"","sources":["../../src/components/JournalListView.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ interface JournalViewerProps {
2
+ date: string;
3
+ content: string;
4
+ onExit?: () => void;
5
+ }
6
+ /**
7
+ * Interactive journal viewer with keyboard navigation and scrolling.
8
+ *
9
+ * Features:
10
+ * - Virtual scrolling (only renders visible lines for performance)
11
+ * - Horizontal panning for long lines (no text wrapping)
12
+ * - Line numbers for easy reference
13
+ * - Sticky header with date and position indicator
14
+ * - Sticky footer with keyboard shortcuts
15
+ * - Multiple navigation methods (arrows, vim keys, page up/down)
16
+ *
17
+ * Architecture:
18
+ * 1. Split content into lines (memoized for performance)
19
+ * 2. Calculate viewport dimensions based on terminal size
20
+ * 3. Track scroll position (vertical and horizontal)
21
+ * 4. Only render visible slice of content (virtual scrolling)
22
+ * 5. Update scroll position on keyboard input
23
+ *
24
+ * Key Design Decisions:
25
+ * - Each content line = 1 display row (no wrapping, use horizontal panning instead)
26
+ * - Line numbers always correspond to content lines (1:1 mapping)
27
+ * - Progress calculated from last visible line (shows 100% when viewing all content)
28
+ * - Auto-reset horizontal position when moving vertically (better UX)
29
+ * - React keys use line numbers (unique, stable identifiers)
30
+ */
31
+ export declare const JournalViewer: ({ date, content, onExit, }: JournalViewerProps) => import("react/jsx-runtime").JSX.Element;
32
+ export {};
@@ -0,0 +1,146 @@
1
+ import { jsxs as _jsxs, jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text, useInput, useApp } from 'ink';
3
+ import { useState, useMemo } from 'react';
4
+ import { formatDateHeader } from '../utils/date.js';
5
+ /**
6
+ * Interactive journal viewer with keyboard navigation and scrolling.
7
+ *
8
+ * Features:
9
+ * - Virtual scrolling (only renders visible lines for performance)
10
+ * - Horizontal panning for long lines (no text wrapping)
11
+ * - Line numbers for easy reference
12
+ * - Sticky header with date and position indicator
13
+ * - Sticky footer with keyboard shortcuts
14
+ * - Multiple navigation methods (arrows, vim keys, page up/down)
15
+ *
16
+ * Architecture:
17
+ * 1. Split content into lines (memoized for performance)
18
+ * 2. Calculate viewport dimensions based on terminal size
19
+ * 3. Track scroll position (vertical and horizontal)
20
+ * 4. Only render visible slice of content (virtual scrolling)
21
+ * 5. Update scroll position on keyboard input
22
+ *
23
+ * Key Design Decisions:
24
+ * - Each content line = 1 display row (no wrapping, use horizontal panning instead)
25
+ * - Line numbers always correspond to content lines (1:1 mapping)
26
+ * - Progress calculated from last visible line (shows 100% when viewing all content)
27
+ * - Auto-reset horizontal position when moving vertically (better UX)
28
+ * - React keys use line numbers (unique, stable identifiers)
29
+ */
30
+ export const JournalViewer = ({ date, content, onExit, }) => {
31
+ const { exit } = useApp();
32
+ // Split content into lines (memoized to avoid re-splitting on every render)
33
+ const contentLines = useMemo(() => content.split('\n'), [content]);
34
+ // Viewport configuration - calculate available space
35
+ const terminalHeight = process.stdout.rows || 24;
36
+ const terminalWidth = process.stdout.columns || 120;
37
+ // Reserve space for UI elements
38
+ // Note: These are estimates. Ink's flexbox will determine actual layout.
39
+ const headerHeight = 3; // Header box takes ~3 lines
40
+ const footerHeight = 2; // Footer box takes ~2 lines
41
+ const reservedHeight = headerHeight + footerHeight;
42
+ // Ensure we have at least 5 visible lines even in small terminals
43
+ const visibleLines = Math.max(5, terminalHeight - reservedHeight);
44
+ // Calculate available width for content (account for borders, padding, line numbers)
45
+ const borderWidth = 2; // Left + right border (1 char each)
46
+ const paddingWidth = 2; // paddingX={1} means 1 space on each side
47
+ const lineNumberWidth = 7; // " 1 │ " format (4 digits + space + │ + space)
48
+ const contentWidth = terminalWidth - borderWidth - paddingWidth - lineNumberWidth;
49
+ // Scroll state
50
+ const [scrollOffset, setScrollOffset] = useState(0); // Vertical scroll (which line is at top)
51
+ const [horizontalOffset, setHorizontalOffset] = useState(0); // Horizontal scroll (which column to start from)
52
+ // Calculate maximum scroll position (can't scroll past end of content)
53
+ const maxScroll = Math.max(0, contentLines.length - visibleLines);
54
+ // Keyboard navigation
55
+ useInput((input, key) => {
56
+ // Quit (q or Escape)
57
+ if (input === 'q' || key.escape) {
58
+ if (onExit) {
59
+ onExit(); // Call callback if provided (for returning to list view)
60
+ }
61
+ else {
62
+ exit(); // Exit app if no callback (standalone viewer)
63
+ }
64
+ return;
65
+ }
66
+ // Vertical navigation
67
+ // Down (↓ or j)
68
+ if (key.downArrow || input === 'j') {
69
+ setScrollOffset((prev) => Math.min(prev + 1, maxScroll));
70
+ setHorizontalOffset(0); // Reset to start of line
71
+ }
72
+ // Up (↑ or k)
73
+ if (key.upArrow || input === 'k') {
74
+ setScrollOffset((prev) => Math.max(prev - 1, 0));
75
+ setHorizontalOffset(0); // Reset to start of line
76
+ }
77
+ // Page down (PgDn or Space)
78
+ if (key.pageDown || input === ' ') {
79
+ setScrollOffset((prev) => Math.min(prev + visibleLines, maxScroll));
80
+ setHorizontalOffset(0); // Reset to start of line
81
+ }
82
+ // Page up (PgUp)
83
+ if (key.pageUp) {
84
+ setScrollOffset((prev) => Math.max(prev - visibleLines, 0));
85
+ setHorizontalOffset(0); // Reset to start of line
86
+ }
87
+ // Jump to top (Home or g)
88
+ if (key.home || input === 'g') {
89
+ setScrollOffset(0);
90
+ setHorizontalOffset(0); // Reset to start of line
91
+ }
92
+ // Jump to bottom (End or G)
93
+ if (key.end || input === 'G') {
94
+ setScrollOffset(maxScroll);
95
+ setHorizontalOffset(0); // Reset to start of line
96
+ }
97
+ // Horizontal navigation
98
+ // Left (← or h)
99
+ if (key.leftArrow || input === 'h') {
100
+ setHorizontalOffset((prev) => Math.max(prev - 10, 0));
101
+ }
102
+ // Right (→ or l)
103
+ if (key.rightArrow || input === 'l') {
104
+ setHorizontalOffset((prev) => prev + 10);
105
+ }
106
+ // Jump to start of line (0)
107
+ if (input === '0') {
108
+ setHorizontalOffset(0);
109
+ }
110
+ });
111
+ // Virtual scrolling: only render visible lines
112
+ // This is critical for performance with large journals (1000+ lines)
113
+ const visibleContent = contentLines.slice(scrollOffset, scrollOffset + visibleLines);
114
+ // Calculate position info based on LAST visible line
115
+ // This ensures progress shows 100% when all content is visible
116
+ // Example: Viewing lines 1-11 of 11 shows "Line 11/11 (100%)"
117
+ const lastVisibleLine = Math.min(scrollOffset + visibleLines, contentLines.length);
118
+ const progress = calculateProgress(lastVisibleLine, contentLines.length);
119
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsxs(Box, { justifyContent: "space-between", children: [_jsxs(Text, { bold: true, color: "cyan", children: ["# ", formatDateHeader(date)] }), _jsxs(Text, { dimColor: true, children: ["Line ", lastVisibleLine, "/", contentLines.length, " (", progress, "%)"] })] }) }), _jsx(Box, { flexDirection: "column", flexGrow: 1, borderStyle: "round", borderColor: "gray", paddingX: 1, children: visibleContent.map((line, idx) => {
120
+ // Calculate actual line number in the full content
121
+ const lineNumber = scrollOffset + idx + 1;
122
+ const lineNumberStr = lineNumber.toString().padStart(4, ' ');
123
+ // Slice line horizontally based on horizontal offset
124
+ // This implements horizontal panning (no text wrapping)
125
+ const visiblePortion = line.substring(horizontalOffset, horizontalOffset + contentWidth);
126
+ // CRITICAL: Use lineNumber as React key (unique, stable identifier)
127
+ // DO NOT use idx or scrollOffset + idx (causes stale content bug)
128
+ // Note: We use a non-breaking space (U+00A0) for empty lines to prevent Ink
129
+ // from collapsing the line entirely. Regular space might get optimized away.
130
+ const displayContent = visiblePortion || '\u00A0'; // Non-breaking space
131
+ return (_jsxs(Box, { flexDirection: "row", minHeight: 1, children: [_jsxs(Text, { dimColor: true, children: [lineNumberStr, " \u2502 "] }), _jsx(Text, { children: displayContent })] }, lineNumber));
132
+ }) }), _jsx(Box, { flexDirection: "column", borderStyle: "round", borderColor: "cyan", paddingX: 1, children: _jsxs(Text, { dimColor: true, children: ["\u2191\u2193/jk Scroll \u2022 \u2190\u2192/hl Pan \u2022 0 Home \u2022 PgUp/PgDn Page \u2022 g/G Top/Bot \u2022 q Quit", horizontalOffset > 0 && ` â€ĸ Col ${horizontalOffset + 1}+`] }) })] }));
133
+ };
134
+ /**
135
+ * Calculate percentage through content.
136
+ *
137
+ * @param currentLine - Current line number (1-indexed)
138
+ * @param totalLines - Total number of lines
139
+ * @returns Percentage (0-100)
140
+ */
141
+ function calculateProgress(currentLine, totalLines) {
142
+ if (totalLines === 0)
143
+ return 0;
144
+ return Math.round((currentLine / totalLines) * 100);
145
+ }
146
+ //# sourceMappingURL=JournalViewer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"JournalViewer.js","sourceRoot":"","sources":["../../src/components/JournalViewer.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function LoginForm(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,68 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { Box, Text, Newline, useApp, useInput } from 'ink';
4
+ import { useState } from 'react';
5
+ import { SigninSchema } from '@rewrlution/papyrus-shared';
6
+ import { api } from '../lib/api/index.js';
7
+ import { ColdStartAwareSpinner } from './ColdStart.js';
8
+ import { FormInput } from './FormInput.js';
9
+ import { Logo } from './Logo.js';
10
+ import { StatusMessage } from './StatusMessage.js';
11
+ export function LoginForm() {
12
+ const { exit } = useApp();
13
+ // Form state
14
+ const [step, setStep] = useState('email');
15
+ const [email, setEmail] = useState('');
16
+ const [password, setPassword] = useState('');
17
+ const [errorMessage, setErrorMessage] = useState('');
18
+ const [userName, setUserName] = useState('');
19
+ useInput((input, key) => {
20
+ if (key.return) {
21
+ if (step === 'email' && email.trim()) {
22
+ setStep('password');
23
+ }
24
+ else if (step === 'password' && password.trim()) {
25
+ handleLogin();
26
+ }
27
+ }
28
+ });
29
+ const handleLogin = async () => {
30
+ if (!password.trim())
31
+ return; // Don't proceed if empty
32
+ // 1. Validate inputs with Zod BEFORE making api call
33
+ setStep('validating');
34
+ const result = SigninSchema.safeParse({ email, password });
35
+ if (!result.success) {
36
+ // Show all validation errors
37
+ const errors = result.error.issues
38
+ .map((issue) => `${issue.path}: ${issue.message}`)
39
+ .join('\n');
40
+ setErrorMessage(errors);
41
+ setStep('error');
42
+ // Go back to appropriate step after showing error
43
+ setTimeout(() => {
44
+ setStep('email');
45
+ setPassword('');
46
+ setErrorMessage('');
47
+ }, 2000);
48
+ return; // Stop execution here - don't proceed to API call
49
+ }
50
+ // 2. Make api call - vliadation already passed
51
+ setStep('submitting');
52
+ try {
53
+ const response = await api.login(result.data);
54
+ setUserName(response.email);
55
+ setStep('success');
56
+ }
57
+ catch (error) {
58
+ setErrorMessage(error.message || 'Login failed');
59
+ setStep('error');
60
+ }
61
+ // Exit after successful login or showing error
62
+ setTimeout(() => {
63
+ exit(); // Exit with code 0 - error message already displayed
64
+ }, 1000);
65
+ };
66
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 2, children: [_jsx(Logo, {}), _jsx(Newline, {}), _jsx(Text, { color: "gray", dimColor: true, children: "Login to your account" }), _jsx(Text, { color: "gray", dimColor: true, children: "Press Ctrl+C to cancel" }), _jsx(Newline, {}), step === 'email' && (_jsx(FormInput, { label: "Email", value: email, onChange: setEmail, placeholder: "user@example.com", focus: true })), step === 'password' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Email:" }), _jsxs(Box, { marginLeft: 2, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: '> ' }), _jsx(Text, { children: email })] }), _jsx(FormInput, { label: "Password", value: password, onChange: setPassword, mask: "*", focus: true })] })), step === 'validating' && (_jsx(StatusMessage, { type: "loading", message: "Validating..." })), step === 'submitting' && (_jsx(ColdStartAwareSpinner, { message: "Logging in..." })), step === 'success' && (_jsx(StatusMessage, { type: "success", message: `Welcome back, ${userName}!` })), step === 'error' && (_jsx(StatusMessage, { type: "error", message: errorMessage }))] }));
67
+ }
68
+ //# sourceMappingURL=LoginForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"LoginForm.js","sourceRoot":"","sources":["../../src/components/LoginForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function Logo(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,57 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import chalk from 'chalk';
3
+ import { Text, Box } from 'ink';
4
+ export function Logo() {
5
+ const logo = [
6
+ chalk.cyan('██████╗ ') +
7
+ chalk.blue(' █████╗ ') +
8
+ chalk.green('██████╗ ') +
9
+ chalk.yellow('██╗ ██╗') +
10
+ chalk.rgb(255, 165, 0)('██████╗ ') +
11
+ chalk.magenta('██╗ ██╗') +
12
+ chalk.red('███████╗'),
13
+ chalk.cyan('██╔══██╗') +
14
+ chalk.blue('██╔══██╗') +
15
+ chalk.green('██╔══██╗') +
16
+ chalk.yellow('╚██╗ ██╔╝') +
17
+ chalk.rgb(255, 165, 0)('██╔══██╗') +
18
+ chalk.magenta('██║ ██║') +
19
+ chalk.red('██╔════╝'),
20
+ chalk.cyan('██████╔╝') +
21
+ chalk.blue('███████║') +
22
+ chalk.green('██████╔╝') +
23
+ chalk.yellow(' ╚████╔╝ ') +
24
+ chalk.rgb(255, 165, 0)('██████╔╝') +
25
+ chalk.magenta('██║ ██║') +
26
+ chalk.red('███████╗'),
27
+ chalk.cyan('██╔═══╝ ') +
28
+ chalk.blue('██╔══██║') +
29
+ chalk.green('██╔═══╝ ') +
30
+ chalk.yellow(' ╚██╔╝ ') +
31
+ chalk.rgb(255, 165, 0)('██╔══██╗') +
32
+ chalk.magenta('██║ ██║') +
33
+ chalk.red('╚════██║'),
34
+ chalk.cyan('██║ ') +
35
+ chalk.blue('██║ ██║') +
36
+ chalk.green('██║ ') +
37
+ chalk.yellow(' ██║ ') +
38
+ chalk.rgb(255, 165, 0)('██║ ██║') +
39
+ chalk.magenta('╚██████╔╝') +
40
+ chalk.red('███████║'),
41
+ chalk.cyan('╚═╝ ') +
42
+ chalk.blue('╚═╝ ╚═╝') +
43
+ chalk.green('╚═╝ ') +
44
+ chalk.yellow(' ╚═╝ ') +
45
+ chalk.rgb(255, 165, 0)('╚═╝ ╚═╝') +
46
+ chalk.magenta(' ╚═════╝ ') +
47
+ chalk.red('╚══════╝'),
48
+ ];
49
+ // Tagline suggestions:
50
+ // "From papyrus to terminal: AI-powered developer journaling"
51
+ // "Timeless journaling, powered by tomorrow"
52
+ // "Where ancient scolls meet modern AI"
53
+ // "Jurnal on digital papyrus, empowered by AI wisdom"
54
+ const tagline = chalk.magenta('Write like the ancients, think with AI');
55
+ return (_jsx(Box, { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: "green", children: _jsxs(Box, { flexDirection: "column", justifyContent: "center", alignItems: "center", marginBottom: 1, children: [logo.map((line, index) => (_jsx(Text, { children: line }, index))), _jsx(Text, { children: tagline })] }) }));
56
+ }
57
+ //# sourceMappingURL=Logo.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logo.js","sourceRoot":"","sources":["../../src/components/Logo.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export declare function RegisterForm(): import("react/jsx-runtime").JSX.Element;
@@ -0,0 +1,72 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ /* eslint-disable @typescript-eslint/no-explicit-any */
3
+ import { Box, Text, Newline, useApp, useInput } from 'ink';
4
+ import { useState } from 'react';
5
+ import { SignupSchema } from '@rewrlution/papyrus-shared';
6
+ import { api } from '../lib/api/index.js';
7
+ import { ColdStartAwareSpinner } from './ColdStart.js';
8
+ import { FormInput } from './FormInput.js';
9
+ import { Logo } from './Logo.js';
10
+ import { StatusMessage } from './StatusMessage.js';
11
+ export function RegisterForm() {
12
+ const { exit } = useApp();
13
+ // Form state
14
+ const [step, setStep] = useState('email');
15
+ const [email, setEmail] = useState('');
16
+ const [password, setPassword] = useState('');
17
+ const [confirmPassword, setConfirmPassword] = useState('');
18
+ const [errorMessage, setErrorMessage] = useState('');
19
+ const [userName, setUserName] = useState('');
20
+ // Handle Enter key to move between fields
21
+ useInput((input, key) => {
22
+ if (key.return) {
23
+ if (step === 'email' && email.trim()) {
24
+ setStep('password');
25
+ }
26
+ else if (step === 'password' && password.trim()) {
27
+ setStep('confirmPassword');
28
+ }
29
+ else if (step === 'confirmPassword' && confirmPassword.trim()) {
30
+ handleRegister();
31
+ }
32
+ }
33
+ });
34
+ const handleRegister = async () => {
35
+ // 1. Validate inputs with Zod BEFORE making API call
36
+ setStep('validating');
37
+ const result = SignupSchema.safeParse({ email, password, confirmPassword });
38
+ if (!result.success) {
39
+ // Show all validation errors
40
+ const errors = result.error.issues
41
+ .map((issue) => `${issue.path}: ${issue.message}`)
42
+ .join('\n');
43
+ setErrorMessage(errors);
44
+ setStep('error');
45
+ // Go back to appropriate step after showing error
46
+ setTimeout(() => {
47
+ setStep('email');
48
+ setPassword('');
49
+ setConfirmPassword('');
50
+ setErrorMessage('');
51
+ }, 2000);
52
+ return; // Stop execution here - don't proceed to API call
53
+ }
54
+ // 2. Make API call - validation already passed
55
+ setStep('submitting');
56
+ try {
57
+ const response = await api.register(result.data);
58
+ setUserName(response.email);
59
+ setStep('success');
60
+ }
61
+ catch (error) {
62
+ setErrorMessage(error.message || 'Registration failed');
63
+ setStep('error');
64
+ }
65
+ // Exit after successful login or showing error
66
+ setTimeout(() => {
67
+ exit(); // Exit with code 0 - error message already displayed
68
+ }, 1000);
69
+ };
70
+ return (_jsxs(Box, { flexDirection: "column", paddingX: 2, paddingY: 2, children: [_jsx(Logo, {}), _jsx(Newline, {}), _jsx(Text, { color: "gray", dimColor: true, children: "Create your Papyrus account" }), _jsx(Text, { color: "gray", dimColor: true, children: "Press Ctrl+C to cancel" }), _jsx(Newline, {}), step === 'email' && (_jsx(FormInput, { label: "Email", value: email, onChange: setEmail, placeholder: "user@example.com", focus: true })), step === 'password' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Email:" }), _jsxs(Box, { marginLeft: 2, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: '> ' }), _jsx(Text, { children: email })] }), _jsx(FormInput, { label: "Password (8+ chars, uppercase, lowercase, number, special char)", value: password, onChange: setPassword, mask: "*", focus: true })] })), step === 'confirmPassword' && (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "cyan", bold: true, children: "Email:" }), _jsxs(Box, { marginLeft: 2, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: '> ' }), _jsx(Text, { children: email })] }), _jsx(Text, { color: "cyan", bold: true, children: "Password:" }), _jsxs(Box, { marginLeft: 2, marginBottom: 1, children: [_jsx(Text, { color: "gray", children: '> ' }), _jsx(Text, { children: '*'.repeat(password.length) })] }), _jsx(FormInput, { label: "Confirm Password", value: confirmPassword, onChange: setConfirmPassword, mask: "*", focus: true })] })), step === 'validating' && (_jsx(StatusMessage, { type: "loading", message: "Validating..." })), step === 'submitting' && (_jsx(ColdStartAwareSpinner, { message: "Creating account..." })), step === 'success' && (_jsx(StatusMessage, { type: "success", message: `Registration successful!\nPlease check ${userName} to verify your account. If you don't receive the verification email, contact: rewrlution@gmail.com` })), step === 'error' && (_jsx(StatusMessage, { type: "error", message: errorMessage }))] }));
71
+ }
72
+ //# sourceMappingURL=RegisterForm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RegisterForm.js","sourceRoot":"","sources":["../../src/components/RegisterForm.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ type MessageType = 'success' | 'error' | 'info' | 'loading';
2
+ interface StatusMessageProps {
3
+ type: MessageType;
4
+ message: string;
5
+ }
6
+ export declare function StatusMessage({ type, message }: StatusMessageProps): import("react/jsx-runtime").JSX.Element;
7
+ export {};
@@ -0,0 +1,19 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box, Text } from 'ink';
3
+ const icons = {
4
+ success: '✅',
5
+ error: '❌',
6
+ info: 'â„šī¸',
7
+ loading: 'đŸ”„ī¸',
8
+ };
9
+ const colors = {
10
+ success: 'green',
11
+ error: 'red',
12
+ info: 'blue',
13
+ loading: 'cyan',
14
+ };
15
+ export function StatusMessage({ type, message }) {
16
+ const lines = message.split('\n');
17
+ return (_jsx(Box, { marginTop: 1, flexDirection: "column", children: lines.map((line, index) => (_jsx(Text, { color: colors[type], children: index === 0 ? `${icons[type]} ${line}` : ` ${line}` }, index))) }));
18
+ }
19
+ //# sourceMappingURL=StatusMessage.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"StatusMessage.js","sourceRoot":"","sources":["../../src/components/StatusMessage.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAUhC,MAAM,KAAK,GAAG;IACZ,OAAO,EAAE,GAAG;IACZ,KAAK,EAAE,GAAG;IACV,IAAI,EAAE,IAAI;IACV,OAAO,EAAE,KAAK;CACf,CAAC;AAEF,MAAM,MAAM,GAAG;IACb,OAAO,EAAE,OAAO;IAChB,KAAK,EAAE,KAAK;IACZ,IAAI,EAAE,MAAM;IACZ,OAAO,EAAE,MAAM;CAChB,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,EAAE,IAAI,EAAE,OAAO,EAAsB;IACjE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAElC,OAAO,CACL,KAAC,GAAG,IAAC,SAAS,EAAE,CAAC,EAAE,aAAa,EAAC,QAAQ,YACtC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE,CAAC,CAC1B,KAAC,IAAI,IAAa,KAAK,EAAE,MAAM,CAAC,IAAI,CAAC,YAClC,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,IAD7C,KAAK,CAET,CACR,CAAC,GACE,CACP,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ export declare const SyncProgress: () => import("react/jsx-runtime").JSX.Element | null;
@@ -0,0 +1,46 @@
1
+ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
+ import { Box, Text, useApp } from 'ink';
3
+ import { useState, useEffect } from 'react';
4
+ import { performSync } from '../lib/sync/sync-engine.js';
5
+ import { ColdStartAwareSpinner } from './ColdStart.js';
6
+ export const SyncProgress = () => {
7
+ const { exit } = useApp();
8
+ const [status, setStatus] = useState('syncing');
9
+ const [result, setResult] = useState(null);
10
+ const [error, setError] = useState('');
11
+ const [progressMessages, setProgressMessages] = useState([]);
12
+ useEffect(() => {
13
+ performSync((message) => {
14
+ // Show progress messages in real-time
15
+ setProgressMessages((prev) => [...prev, message]);
16
+ })
17
+ .then((syncResult) => {
18
+ setResult(syncResult);
19
+ setStatus('done');
20
+ setTimeout(() => exit(), 1000);
21
+ })
22
+ .catch((err) => {
23
+ setError(err.message || 'Sync failed');
24
+ setStatus('error');
25
+ setTimeout(() => exit(err), 2000);
26
+ });
27
+ }, [exit]);
28
+ if (status === 'syncing') {
29
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(ColdStartAwareSpinner, { message: "Syncing journals..." }), progressMessages.length > 0 && (_jsx(Box, { flexDirection: "column", marginTop: 1, children: progressMessages.slice(-5).map((msg, idx) => (_jsx(Text, { dimColor: true, children: msg }, idx))) }))] }));
30
+ }
31
+ if (status === 'error') {
32
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "red", children: "\u2717 Sync failed" }), _jsx(Text, { color: "red", children: error })] }));
33
+ }
34
+ if (status === 'done' && result) {
35
+ const { uploaded, downloaded, conflicts } = result;
36
+ const total = uploaded + downloaded + conflicts;
37
+ // Nothing to sync
38
+ if (total === 0) {
39
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "green", children: "\u2713 Everything is in sync" }), _jsx(Text, { dimColor: true, children: "No changes to upload or download" })] }));
40
+ }
41
+ // Show detailed results
42
+ return (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: "green", children: "\u2713 Sync complete" }), _jsxs(Box, { flexDirection: "column", marginTop: 1, children: [uploaded > 0 && (_jsxs(Text, { children: ["\u2191 ", _jsx(Text, { color: "cyan", children: uploaded }), " uploaded"] })), downloaded > 0 && (_jsxs(Text, { children: ["\u2193 ", _jsx(Text, { color: "cyan", children: downloaded }), " downloaded"] })), conflicts > 0 && (_jsxs(Text, { children: ["\u26A0\uFE0F ", _jsx(Text, { color: "yellow", children: conflicts }), " conflict", conflicts > 1 ? 's' : '', " resolved"] }))] })] }));
43
+ }
44
+ return null;
45
+ };
46
+ //# sourceMappingURL=SyncProgress.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SyncProgress.js","sourceRoot":"","sources":["../../src/components/SyncProgress.tsx"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { SigninInput, SigninResponse, SignupInput, SignupResponse, JournalData, JournalMetaData } from '@rewrlution/papyrus-shared';
2
+ /**
3
+ * API Client for Papyrus server
4
+ * Uses shared types and storage layer for tokens
5
+ *
6
+ * Error handling strategy:
7
+ * - Validation errors: Caught by Zod client-side (before API call)
8
+ * - API errors: Descriptive messages from ApiErrorResponse
9
+ * - Network errors: Wrapped with descriptive message
10
+ */
11
+ export declare class ApiClient {
12
+ private http;
13
+ constructor(baseUrl: string);
14
+ register(credentials: SignupInput): Promise<SignupResponse['data']>;
15
+ login(credentials: SigninInput): Promise<SigninResponse['data']>;
16
+ logout(): void;
17
+ isAuthenticated(): boolean;
18
+ listJournalsMetadata(): Promise<JournalMetaData[]>;
19
+ getJournal(date: string): Promise<JournalData>;
20
+ createJournal(date: string, content: string): Promise<JournalData>;
21
+ updateJournal(date: string, content: string): Promise<JournalData>;
22
+ private handleError;
23
+ }