@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.
- package/README.md +699 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +16 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/auth/index.d.ts +2 -0
- package/dist/commands/auth/index.js +18 -0
- package/dist/commands/auth/index.js.map +1 -0
- package/dist/commands/auth/login.d.ts +1 -0
- package/dist/commands/auth/login.js +8 -0
- package/dist/commands/auth/login.js.map +1 -0
- package/dist/commands/auth/logout.d.ts +1 -0
- package/dist/commands/auth/logout.js +5 -0
- package/dist/commands/auth/logout.js.map +1 -0
- package/dist/commands/auth/register.d.ts +1 -0
- package/dist/commands/auth/register.js +8 -0
- package/dist/commands/auth/register.js.map +1 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +3 -0
- package/dist/commands/index.js.map +1 -0
- package/dist/commands/journal/add.d.ts +2 -0
- package/dist/commands/journal/add.js +5 -0
- package/dist/commands/journal/add.js.map +1 -0
- package/dist/commands/journal/amend.d.ts +2 -0
- package/dist/commands/journal/amend.js +5 -0
- package/dist/commands/journal/amend.js.map +1 -0
- package/dist/commands/journal/edit.d.ts +6 -0
- package/dist/commands/journal/edit.js +60 -0
- package/dist/commands/journal/edit.js.map +1 -0
- package/dist/commands/journal/index.d.ts +2 -0
- package/dist/commands/journal/index.js +32 -0
- package/dist/commands/journal/index.js.map +1 -0
- package/dist/commands/journal/list.d.ts +1 -0
- package/dist/commands/journal/list.js +20 -0
- package/dist/commands/journal/list.js.map +1 -0
- package/dist/commands/journal/show.d.ts +2 -0
- package/dist/commands/journal/show.js +35 -0
- package/dist/commands/journal/show.js.map +1 -0
- package/dist/commands/journal/sync.d.ts +1 -0
- package/dist/commands/journal/sync.js +9 -0
- package/dist/commands/journal/sync.js.map +1 -0
- package/dist/commands/types.d.ts +9 -0
- package/dist/commands/types.js +2 -0
- package/dist/commands/types.js.map +1 -0
- package/dist/components/Browser.d.ts +29 -0
- package/dist/components/Browser.js +124 -0
- package/dist/components/Browser.js.map +1 -0
- package/dist/components/BrowserFooter.d.ts +6 -0
- package/dist/components/BrowserFooter.js +6 -0
- package/dist/components/BrowserFooter.js.map +1 -0
- package/dist/components/BrowserHeader.d.ts +6 -0
- package/dist/components/BrowserHeader.js +6 -0
- package/dist/components/BrowserHeader.js.map +1 -0
- package/dist/components/ColdStart.d.ts +6 -0
- package/dist/components/ColdStart.js +24 -0
- package/dist/components/ColdStart.js.map +1 -0
- package/dist/components/FormInput.d.ts +10 -0
- package/dist/components/FormInput.js +7 -0
- package/dist/components/FormInput.js.map +1 -0
- package/dist/components/JournalListView.d.ts +10 -0
- package/dist/components/JournalListView.js +40 -0
- package/dist/components/JournalListView.js.map +1 -0
- package/dist/components/JournalViewer.d.ts +32 -0
- package/dist/components/JournalViewer.js +146 -0
- package/dist/components/JournalViewer.js.map +1 -0
- package/dist/components/LoginForm.d.ts +1 -0
- package/dist/components/LoginForm.js +68 -0
- package/dist/components/LoginForm.js.map +1 -0
- package/dist/components/Logo.d.ts +1 -0
- package/dist/components/Logo.js +57 -0
- package/dist/components/Logo.js.map +1 -0
- package/dist/components/RegisterForm.d.ts +1 -0
- package/dist/components/RegisterForm.js +72 -0
- package/dist/components/RegisterForm.js.map +1 -0
- package/dist/components/StatusMessage.d.ts +7 -0
- package/dist/components/StatusMessage.js +19 -0
- package/dist/components/StatusMessage.js.map +1 -0
- package/dist/components/SyncProgress.d.ts +1 -0
- package/dist/components/SyncProgress.js +46 -0
- package/dist/components/SyncProgress.js.map +1 -0
- package/dist/lib/api/api-client.d.ts +23 -0
- package/dist/lib/api/api-client.js +111 -0
- package/dist/lib/api/api-client.js.map +1 -0
- package/dist/lib/api/index.d.ts +3 -0
- package/dist/lib/api/index.js +6 -0
- package/dist/lib/api/index.js.map +1 -0
- package/dist/lib/auth/index.d.ts +1 -0
- package/dist/lib/auth/index.js +2 -0
- package/dist/lib/auth/index.js.map +1 -0
- package/dist/lib/auth/require-auth.d.ts +67 -0
- package/dist/lib/auth/require-auth.js +107 -0
- package/dist/lib/auth/require-auth.js.map +1 -0
- package/dist/lib/storage/base-storage.d.ts +50 -0
- package/dist/lib/storage/base-storage.js +91 -0
- package/dist/lib/storage/base-storage.js.map +1 -0
- package/dist/lib/storage/config-store.d.ts +40 -0
- package/dist/lib/storage/config-store.js +63 -0
- package/dist/lib/storage/config-store.js.map +1 -0
- package/dist/lib/storage/index.d.ts +12 -0
- package/dist/lib/storage/index.js +13 -0
- package/dist/lib/storage/index.js.map +1 -0
- package/dist/lib/storage/journal-storage.d.ts +46 -0
- package/dist/lib/storage/journal-storage.js +78 -0
- package/dist/lib/storage/journal-storage.js.map +1 -0
- package/dist/lib/storage/sync-meta-store.d.ts +37 -0
- package/dist/lib/storage/sync-meta-store.js +50 -0
- package/dist/lib/storage/sync-meta-store.js.map +1 -0
- package/dist/lib/storage/token-store.d.ts +25 -0
- package/dist/lib/storage/token-store.js +40 -0
- package/dist/lib/storage/token-store.js.map +1 -0
- package/dist/lib/sync/sync-engine.d.ts +13 -0
- package/dist/lib/sync/sync-engine.js +96 -0
- package/dist/lib/sync/sync-engine.js.map +1 -0
- package/dist/utils/date.d.ts +58 -0
- package/dist/utils/date.js +117 -0
- package/dist/utils/date.js.map +1 -0
- package/dist/utils/editor.d.ts +2 -0
- package/dist/utils/editor.js +81 -0
- package/dist/utils/editor.js.map +1 -0
- package/dist/utils/template.d.ts +2 -0
- package/dist/utils/template.js +17 -0
- package/dist/utils/template.js.map +1 -0
- package/dist/utils/token.d.ts +20 -0
- package/dist/utils/token.js +64 -0
- package/dist/utils/token.js.map +1 -0
- 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
|
+
}
|