hazo_notes 1.0.0
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 +661 -0
- package/SETUP_CHECKLIST.md +453 -0
- package/dist/api/create_files_handler.d.ts +42 -0
- package/dist/api/create_files_handler.d.ts.map +1 -0
- package/dist/api/create_files_handler.js +213 -0
- package/dist/api/create_files_handler.js.map +1 -0
- package/dist/api/create_notes_handler.d.ts +50 -0
- package/dist/api/create_notes_handler.d.ts.map +1 -0
- package/dist/api/create_notes_handler.js +242 -0
- package/dist/api/create_notes_handler.js.map +1 -0
- package/dist/api/index.d.ts +9 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +8 -0
- package/dist/api/index.js.map +1 -0
- package/dist/components/hazo_notes_entry.d.ts +6 -0
- package/dist/components/hazo_notes_entry.d.ts.map +1 -0
- package/dist/components/hazo_notes_entry.js +69 -0
- package/dist/components/hazo_notes_entry.js.map +1 -0
- package/dist/components/hazo_notes_file_preview.d.ts +16 -0
- package/dist/components/hazo_notes_file_preview.d.ts.map +1 -0
- package/dist/components/hazo_notes_file_preview.js +77 -0
- package/dist/components/hazo_notes_file_preview.js.map +1 -0
- package/dist/components/hazo_notes_icon.d.ts +6 -0
- package/dist/components/hazo_notes_icon.d.ts.map +1 -0
- package/dist/components/hazo_notes_icon.js +208 -0
- package/dist/components/hazo_notes_icon.js.map +1 -0
- package/dist/components/hazo_notes_panel.d.ts +6 -0
- package/dist/components/hazo_notes_panel.d.ts.map +1 -0
- package/dist/components/hazo_notes_panel.js +197 -0
- package/dist/components/hazo_notes_panel.js.map +1 -0
- package/dist/components/index.d.ts +8 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +8 -0
- package/dist/components/index.js.map +1 -0
- package/dist/hooks/index.d.ts +8 -0
- package/dist/hooks/index.d.ts.map +1 -0
- package/dist/hooks/index.js +6 -0
- package/dist/hooks/index.js.map +1 -0
- package/dist/hooks/use_notes.d.ts +46 -0
- package/dist/hooks/use_notes.d.ts.map +1 -0
- package/dist/hooks/use_notes.js +146 -0
- package/dist/hooks/use_notes.js.map +1 -0
- package/dist/hooks/use_notes_file_upload.d.ts +52 -0
- package/dist/hooks/use_notes_file_upload.d.ts.map +1 -0
- package/dist/hooks/use_notes_file_upload.js +125 -0
- package/dist/hooks/use_notes_file_upload.js.map +1 -0
- package/dist/index.client.d.ts +16 -0
- package/dist/index.client.d.ts.map +1 -0
- package/dist/index.client.js +18 -0
- package/dist/index.client.js.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +15 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/config.d.ts +31 -0
- package/dist/lib/config.d.ts.map +1 -0
- package/dist/lib/config.js +123 -0
- package/dist/lib/config.js.map +1 -0
- package/dist/lib/index.d.ts +6 -0
- package/dist/lib/index.d.ts.map +1 -0
- package/dist/lib/index.js +6 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/logger/context.d.ts +49 -0
- package/dist/logger/context.d.ts.map +1 -0
- package/dist/logger/context.js +45 -0
- package/dist/logger/context.js.map +1 -0
- package/dist/logger/index.d.ts +9 -0
- package/dist/logger/index.d.ts.map +1 -0
- package/dist/logger/index.js +7 -0
- package/dist/logger/index.js.map +1 -0
- package/dist/logger/server.d.ts +27 -0
- package/dist/logger/server.d.ts.map +1 -0
- package/dist/logger/server.js +36 -0
- package/dist/logger/server.js.map +1 -0
- package/dist/logger/types.d.ts +20 -0
- package/dist/logger/types.d.ts.map +1 -0
- package/dist/logger/types.js +15 -0
- package/dist/logger/types.js.map +1 -0
- package/dist/types/index.d.ts +267 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +5 -0
- package/dist/types/index.js.map +1 -0
- package/dist/utils/cn.d.ts +16 -0
- package/dist/utils/cn.d.ts.map +1 -0
- package/dist/utils/cn.js +19 -0
- package/dist/utils/cn.js.map +1 -0
- package/dist/utils/file_utils.d.ts +51 -0
- package/dist/utils/file_utils.d.ts.map +1 -0
- package/dist/utils/file_utils.js +128 -0
- package/dist/utils/file_utils.js.map +1 -0
- package/dist/utils/index.d.ts +6 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/migrations/001_create_hazo_notes_table.sql +77 -0
- package/package.json +119 -0
- package/templates/config/hazo_notes_config.ini +43 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAG3C,OAAO,EAAE,qBAAqB,EAAE,MAAM,4BAA4B,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { NoteEntry, NoteFile } from '../types/index.js';
|
|
2
|
+
export interface UseNotesOptions {
|
|
3
|
+
/** Skip initial fetch (for controlled mode) */
|
|
4
|
+
skip?: boolean;
|
|
5
|
+
/** API endpoint base path */
|
|
6
|
+
api_endpoint?: string;
|
|
7
|
+
/** Refresh interval in milliseconds (0 = disabled) */
|
|
8
|
+
refresh_interval?: number;
|
|
9
|
+
}
|
|
10
|
+
export interface UseNotesResult {
|
|
11
|
+
/** Array of notes */
|
|
12
|
+
notes: NoteEntry[];
|
|
13
|
+
/** Total note count */
|
|
14
|
+
note_count: number;
|
|
15
|
+
/** Loading state */
|
|
16
|
+
loading: boolean;
|
|
17
|
+
/** Error message */
|
|
18
|
+
error: string | null;
|
|
19
|
+
/** Add a new note */
|
|
20
|
+
add_note: (note_text: string, note_files?: NoteFile[]) => Promise<boolean>;
|
|
21
|
+
/** Refresh notes from server */
|
|
22
|
+
refresh: () => Promise<void>;
|
|
23
|
+
/** Reset error state */
|
|
24
|
+
clear_error: () => void;
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Hook for fetching and managing notes
|
|
28
|
+
*
|
|
29
|
+
* @param ref_id - Reference ID for the notes
|
|
30
|
+
* @param options - Configuration options
|
|
31
|
+
* @returns Notes state and methods
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* const { notes, loading, add_note } = use_notes('my-ref-id');
|
|
36
|
+
*
|
|
37
|
+
* const handleAddNote = async () => {
|
|
38
|
+
* const success = await add_note('This is my note');
|
|
39
|
+
* if (success) {
|
|
40
|
+
* console.log('Note added!');
|
|
41
|
+
* }
|
|
42
|
+
* };
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function use_notes(ref_id: string, options?: UseNotesOptions): UseNotesResult;
|
|
46
|
+
//# sourceMappingURL=use_notes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_notes.d.ts","sourceRoot":"","sources":["../../src/hooks/use_notes.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAwC,MAAM,mBAAmB,CAAC;AAGnG,MAAM,WAAW,eAAe;IAC9B,+CAA+C;IAC/C,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,6BAA6B;IAC7B,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,sDAAsD;IACtD,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,cAAc;IAC7B,qBAAqB;IACrB,KAAK,EAAE,SAAS,EAAE,CAAC;IACnB,uBAAuB;IACvB,UAAU,EAAE,MAAM,CAAC;IACnB,oBAAoB;IACpB,OAAO,EAAE,OAAO,CAAC;IACjB,oBAAoB;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,qBAAqB;IACrB,QAAQ,EAAE,CAAC,SAAS,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC3E,gCAAgC;IAChC,OAAO,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7B,wBAAwB;IACxB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,cAAc,CAyIvF"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* React hook for managing notes state and API interactions
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useEffect, useCallback, useRef } from 'react';
|
|
6
|
+
import { use_logger } from '../logger/context.js';
|
|
7
|
+
/**
|
|
8
|
+
* Hook for fetching and managing notes
|
|
9
|
+
*
|
|
10
|
+
* @param ref_id - Reference ID for the notes
|
|
11
|
+
* @param options - Configuration options
|
|
12
|
+
* @returns Notes state and methods
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```tsx
|
|
16
|
+
* const { notes, loading, add_note } = use_notes('my-ref-id');
|
|
17
|
+
*
|
|
18
|
+
* const handleAddNote = async () => {
|
|
19
|
+
* const success = await add_note('This is my note');
|
|
20
|
+
* if (success) {
|
|
21
|
+
* console.log('Note added!');
|
|
22
|
+
* }
|
|
23
|
+
* };
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
export function use_notes(ref_id, options = {}) {
|
|
27
|
+
const { skip = false, api_endpoint = '/api/hazo_notes', refresh_interval = 0, } = options;
|
|
28
|
+
const logger = use_logger();
|
|
29
|
+
const [notes, set_notes] = useState([]);
|
|
30
|
+
const [note_count, set_note_count] = useState(0);
|
|
31
|
+
const [loading, set_loading] = useState(!skip);
|
|
32
|
+
const [error, set_error] = useState(null);
|
|
33
|
+
// Use ref to track if component is mounted
|
|
34
|
+
const mounted_ref = useRef(true);
|
|
35
|
+
// Fetch notes from API
|
|
36
|
+
const fetch_notes = useCallback(async () => {
|
|
37
|
+
if (skip || !ref_id) {
|
|
38
|
+
set_loading(false);
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
set_loading(true);
|
|
42
|
+
set_error(null);
|
|
43
|
+
try {
|
|
44
|
+
const response = await fetch(`${api_endpoint}/${ref_id}`, {
|
|
45
|
+
credentials: 'include',
|
|
46
|
+
});
|
|
47
|
+
if (!mounted_ref.current)
|
|
48
|
+
return;
|
|
49
|
+
const data = await response.json();
|
|
50
|
+
if (data.success) {
|
|
51
|
+
set_notes(data.notes || []);
|
|
52
|
+
set_note_count(data.note_count || 0);
|
|
53
|
+
logger.debug('[use_notes] Fetched notes', {
|
|
54
|
+
ref_id,
|
|
55
|
+
count: data.notes?.length || 0,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
set_error(data.error || 'Failed to fetch notes');
|
|
60
|
+
logger.error('[use_notes] Fetch error', { ref_id, error: data.error });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch (err) {
|
|
64
|
+
if (!mounted_ref.current)
|
|
65
|
+
return;
|
|
66
|
+
const message = err instanceof Error ? err.message : 'Failed to fetch notes';
|
|
67
|
+
set_error(message);
|
|
68
|
+
logger.error('[use_notes] Fetch exception', { ref_id, error: message });
|
|
69
|
+
}
|
|
70
|
+
finally {
|
|
71
|
+
if (mounted_ref.current) {
|
|
72
|
+
set_loading(false);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
}, [ref_id, skip, api_endpoint, logger]);
|
|
76
|
+
// Initial fetch
|
|
77
|
+
useEffect(() => {
|
|
78
|
+
mounted_ref.current = true;
|
|
79
|
+
fetch_notes();
|
|
80
|
+
return () => {
|
|
81
|
+
mounted_ref.current = false;
|
|
82
|
+
};
|
|
83
|
+
}, [fetch_notes]);
|
|
84
|
+
// Refresh interval
|
|
85
|
+
useEffect(() => {
|
|
86
|
+
if (refresh_interval <= 0 || skip)
|
|
87
|
+
return;
|
|
88
|
+
const interval = setInterval(fetch_notes, refresh_interval);
|
|
89
|
+
return () => clearInterval(interval);
|
|
90
|
+
}, [refresh_interval, skip, fetch_notes]);
|
|
91
|
+
// Add a new note
|
|
92
|
+
const add_note = useCallback(async (note_text, note_files) => {
|
|
93
|
+
if (!ref_id) {
|
|
94
|
+
set_error('ref_id is required');
|
|
95
|
+
return false;
|
|
96
|
+
}
|
|
97
|
+
if (!note_text.trim()) {
|
|
98
|
+
set_error('Note text cannot be empty');
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
try {
|
|
102
|
+
const response = await fetch(`${api_endpoint}/${ref_id}`, {
|
|
103
|
+
method: 'POST',
|
|
104
|
+
headers: { 'Content-Type': 'application/json' },
|
|
105
|
+
credentials: 'include',
|
|
106
|
+
body: JSON.stringify({
|
|
107
|
+
note_text: note_text.trim(),
|
|
108
|
+
note_files,
|
|
109
|
+
}),
|
|
110
|
+
});
|
|
111
|
+
const data = await response.json();
|
|
112
|
+
if (data.success && data.note) {
|
|
113
|
+
// Optimistic update
|
|
114
|
+
set_notes((prev) => [...prev, data.note]);
|
|
115
|
+
set_note_count(data.note_count || notes.length + 1);
|
|
116
|
+
logger.debug('[use_notes] Added note', { ref_id, note_count: data.note_count });
|
|
117
|
+
return true;
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
set_error(data.error || 'Failed to add note');
|
|
121
|
+
logger.error('[use_notes] Add note error', { ref_id, error: data.error });
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
catch (err) {
|
|
126
|
+
const message = err instanceof Error ? err.message : 'Failed to add note';
|
|
127
|
+
set_error(message);
|
|
128
|
+
logger.error('[use_notes] Add note exception', { ref_id, error: message });
|
|
129
|
+
return false;
|
|
130
|
+
}
|
|
131
|
+
}, [ref_id, api_endpoint, notes.length, logger]);
|
|
132
|
+
// Clear error
|
|
133
|
+
const clear_error = useCallback(() => {
|
|
134
|
+
set_error(null);
|
|
135
|
+
}, []);
|
|
136
|
+
return {
|
|
137
|
+
notes,
|
|
138
|
+
note_count,
|
|
139
|
+
loading,
|
|
140
|
+
error,
|
|
141
|
+
add_note,
|
|
142
|
+
refresh: fetch_notes,
|
|
143
|
+
clear_error,
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
//# sourceMappingURL=use_notes.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_notes.js","sourceRoot":"","sources":["../../src/hooks/use_notes.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { NoteFile } from '../types/index.js';
|
|
2
|
+
export interface UseNotesFileUploadOptions {
|
|
3
|
+
/** Reference ID for the notes */
|
|
4
|
+
ref_id: string;
|
|
5
|
+
/** API endpoint for file uploads */
|
|
6
|
+
api_endpoint?: string;
|
|
7
|
+
/** Maximum file size in MB */
|
|
8
|
+
max_file_size_mb?: number;
|
|
9
|
+
/** Allowed file types */
|
|
10
|
+
allowed_file_types?: string[];
|
|
11
|
+
/** Storage mode: jsonb (client-side encoding) or filesystem (server upload) */
|
|
12
|
+
storage_mode?: 'jsonb' | 'filesystem';
|
|
13
|
+
}
|
|
14
|
+
export interface UseNotesFileUploadResult {
|
|
15
|
+
/** Files pending to be attached to a note */
|
|
16
|
+
pending_files: NoteFile[];
|
|
17
|
+
/** Upload a file */
|
|
18
|
+
upload_file: (file: File, embed_type?: 'embed' | 'attachment') => Promise<NoteFile | null>;
|
|
19
|
+
/** Remove a pending file */
|
|
20
|
+
remove_file: (file_no: string) => void;
|
|
21
|
+
/** Clear all pending files */
|
|
22
|
+
clear_files: () => void;
|
|
23
|
+
/** Loading state */
|
|
24
|
+
uploading: boolean;
|
|
25
|
+
/** Error message */
|
|
26
|
+
error: string | null;
|
|
27
|
+
/** Clear error */
|
|
28
|
+
clear_error: () => void;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Hook for handling file uploads for notes
|
|
32
|
+
*
|
|
33
|
+
* @param options - Configuration options
|
|
34
|
+
* @returns File upload state and methods
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```tsx
|
|
38
|
+
* const { pending_files, upload_file, remove_file } = use_notes_file_upload({
|
|
39
|
+
* ref_id: 'my-ref-id',
|
|
40
|
+
* max_file_size_mb: 5,
|
|
41
|
+
* });
|
|
42
|
+
*
|
|
43
|
+
* const handleFileSelect = async (file: File) => {
|
|
44
|
+
* const uploaded = await upload_file(file, 'attachment');
|
|
45
|
+
* if (uploaded) {
|
|
46
|
+
* console.log('File uploaded:', uploaded.filename);
|
|
47
|
+
* }
|
|
48
|
+
* };
|
|
49
|
+
* ```
|
|
50
|
+
*/
|
|
51
|
+
export declare function use_notes_file_upload(options: UseNotesFileUploadOptions): UseNotesFileUploadResult;
|
|
52
|
+
//# sourceMappingURL=use_notes_file_upload.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_notes_file_upload.d.ts","sourceRoot":"","sources":["../../src/hooks/use_notes_file_upload.ts"],"names":[],"mappings":"AAOA,OAAO,KAAK,EAAE,QAAQ,EAAyB,MAAM,mBAAmB,CAAC;AAUzE,MAAM,WAAW,yBAAyB;IACxC,iCAAiC;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,oCAAoC;IACpC,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,8BAA8B;IAC9B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,yBAAyB;IACzB,kBAAkB,CAAC,EAAE,MAAM,EAAE,CAAC;IAC9B,+EAA+E;IAC/E,YAAY,CAAC,EAAE,OAAO,GAAG,YAAY,CAAC;CACvC;AAED,MAAM,WAAW,wBAAwB;IACvC,6CAA6C;IAC7C,aAAa,EAAE,QAAQ,EAAE,CAAC;IAC1B,oBAAoB;IACpB,WAAW,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,OAAO,GAAG,YAAY,KAAK,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC3F,4BAA4B;IAC5B,WAAW,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,8BAA8B;IAC9B,WAAW,EAAE,MAAM,IAAI,CAAC;IACxB,oBAAoB;IACpB,SAAS,EAAE,OAAO,CAAC;IACnB,oBAAoB;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,kBAAkB;IAClB,WAAW,EAAE,MAAM,IAAI,CAAC;CACzB;AAKD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,yBAAyB,GAAG,wBAAwB,CAuHlG"}
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
/**
|
|
3
|
+
* React hook for handling file uploads for notes
|
|
4
|
+
*/
|
|
5
|
+
import { useState, useCallback } from 'react';
|
|
6
|
+
import { use_logger } from '../logger/context.js';
|
|
7
|
+
import { validate_file, file_to_base64, get_mime_type, generate_file_no, is_image_file, } from '../utils/file_utils.js';
|
|
8
|
+
const DEFAULT_MAX_FILE_SIZE_MB = 10;
|
|
9
|
+
const DEFAULT_ALLOWED_TYPES = ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx'];
|
|
10
|
+
/**
|
|
11
|
+
* Hook for handling file uploads for notes
|
|
12
|
+
*
|
|
13
|
+
* @param options - Configuration options
|
|
14
|
+
* @returns File upload state and methods
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```tsx
|
|
18
|
+
* const { pending_files, upload_file, remove_file } = use_notes_file_upload({
|
|
19
|
+
* ref_id: 'my-ref-id',
|
|
20
|
+
* max_file_size_mb: 5,
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* const handleFileSelect = async (file: File) => {
|
|
24
|
+
* const uploaded = await upload_file(file, 'attachment');
|
|
25
|
+
* if (uploaded) {
|
|
26
|
+
* console.log('File uploaded:', uploaded.filename);
|
|
27
|
+
* }
|
|
28
|
+
* };
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export function use_notes_file_upload(options) {
|
|
32
|
+
const { ref_id, api_endpoint = '/api/hazo_notes/files/upload', max_file_size_mb = DEFAULT_MAX_FILE_SIZE_MB, allowed_file_types = DEFAULT_ALLOWED_TYPES, storage_mode = 'jsonb', } = options;
|
|
33
|
+
const logger = use_logger();
|
|
34
|
+
const [pending_files, set_pending_files] = useState([]);
|
|
35
|
+
const [uploading, set_uploading] = useState(false);
|
|
36
|
+
const [error, set_error] = useState(null);
|
|
37
|
+
// Upload a file
|
|
38
|
+
const upload_file = useCallback(async (file, embed_type) => {
|
|
39
|
+
set_error(null);
|
|
40
|
+
// Validate file
|
|
41
|
+
const validation = validate_file(file, {
|
|
42
|
+
max_size_mb: max_file_size_mb,
|
|
43
|
+
allowed_types: allowed_file_types,
|
|
44
|
+
});
|
|
45
|
+
if (!validation.valid) {
|
|
46
|
+
set_error(validation.error || 'Invalid file');
|
|
47
|
+
return null;
|
|
48
|
+
}
|
|
49
|
+
// Auto-determine embed type based on file type
|
|
50
|
+
const actual_embed_type = embed_type || (is_image_file(file.name) ? 'embed' : 'attachment');
|
|
51
|
+
set_uploading(true);
|
|
52
|
+
try {
|
|
53
|
+
let note_file;
|
|
54
|
+
if (storage_mode === 'filesystem') {
|
|
55
|
+
// Upload to server
|
|
56
|
+
const formData = new FormData();
|
|
57
|
+
formData.append('file', file);
|
|
58
|
+
formData.append('ref_id', ref_id);
|
|
59
|
+
formData.append('embed_type', actual_embed_type);
|
|
60
|
+
const response = await fetch(api_endpoint, {
|
|
61
|
+
method: 'POST',
|
|
62
|
+
credentials: 'include',
|
|
63
|
+
body: formData,
|
|
64
|
+
});
|
|
65
|
+
const data = await response.json();
|
|
66
|
+
if (!data.success || !data.file) {
|
|
67
|
+
throw new Error(data.error || 'Upload failed');
|
|
68
|
+
}
|
|
69
|
+
note_file = data.file;
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
// JSONB mode - encode on client
|
|
73
|
+
const base64_data = await file_to_base64(file);
|
|
74
|
+
const file_no = generate_file_no(pending_files);
|
|
75
|
+
note_file = {
|
|
76
|
+
file_no,
|
|
77
|
+
embed_type: actual_embed_type,
|
|
78
|
+
filename: file.name,
|
|
79
|
+
filedata: base64_data,
|
|
80
|
+
mime_type: get_mime_type(file.name),
|
|
81
|
+
file_size: file.size,
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
// Add to pending files
|
|
85
|
+
set_pending_files((prev) => [...prev, note_file]);
|
|
86
|
+
logger.debug('[use_notes_file_upload] File uploaded', {
|
|
87
|
+
filename: file.name,
|
|
88
|
+
file_no: note_file.file_no,
|
|
89
|
+
embed_type: actual_embed_type,
|
|
90
|
+
});
|
|
91
|
+
return note_file;
|
|
92
|
+
}
|
|
93
|
+
catch (err) {
|
|
94
|
+
const message = err instanceof Error ? err.message : 'Upload failed';
|
|
95
|
+
set_error(message);
|
|
96
|
+
logger.error('[use_notes_file_upload] Upload error', { error: message });
|
|
97
|
+
return null;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
set_uploading(false);
|
|
101
|
+
}
|
|
102
|
+
}, [ref_id, api_endpoint, max_file_size_mb, allowed_file_types, storage_mode, pending_files, logger]);
|
|
103
|
+
// Remove a pending file
|
|
104
|
+
const remove_file = useCallback((file_no) => {
|
|
105
|
+
set_pending_files((prev) => prev.filter((f) => f.file_no !== file_no));
|
|
106
|
+
}, []);
|
|
107
|
+
// Clear all pending files
|
|
108
|
+
const clear_files = useCallback(() => {
|
|
109
|
+
set_pending_files([]);
|
|
110
|
+
}, []);
|
|
111
|
+
// Clear error
|
|
112
|
+
const clear_error = useCallback(() => {
|
|
113
|
+
set_error(null);
|
|
114
|
+
}, []);
|
|
115
|
+
return {
|
|
116
|
+
pending_files,
|
|
117
|
+
upload_file,
|
|
118
|
+
remove_file,
|
|
119
|
+
clear_files,
|
|
120
|
+
uploading,
|
|
121
|
+
error,
|
|
122
|
+
clear_error,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
//# sourceMappingURL=use_notes_file_upload.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use_notes_file_upload.js","sourceRoot":"","sources":["../../src/hooks/use_notes_file_upload.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_notes - Client-safe exports
|
|
3
|
+
*
|
|
4
|
+
* This is the default entry point for 'hazo_notes' imports
|
|
5
|
+
* Contains only client-safe components, hooks, and types
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
export * from './components/index.js';
|
|
10
|
+
export * from './hooks/index.js';
|
|
11
|
+
export type { NoteFile, NoteEntry, NoteEntryDB, NewNoteInput, NoteUserInfo, HazoNotesIconProps, HazoNotesPanelProps, HazoNotesEntryProps, HazoNotesFilePreviewProps, NotesApiResponse, AddNoteApiResponse, } from './types/index.js';
|
|
12
|
+
export { LoggerProvider, use_logger, noop_logger } from './logger/index.js';
|
|
13
|
+
export type { Logger, LoggerProviderProps } from './logger/index.js';
|
|
14
|
+
export { cn } from './utils/cn.js';
|
|
15
|
+
export { generate_file_no, file_to_base64, get_mime_type, is_allowed_file_type, is_image_file, format_file_size, parse_file_references, create_file_reference, validate_file, } from './utils/file_utils.js';
|
|
16
|
+
//# sourceMappingURL=index.client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client.d.ts","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,cAAc,uBAAuB,CAAC;AAGtC,cAAc,kBAAkB,CAAC;AAGjC,YAAY,EACV,QAAQ,EACR,SAAS,EACT,WAAW,EACX,YAAY,EACZ,YAAY,EACZ,kBAAkB,EAClB,mBAAmB,EACnB,mBAAmB,EACnB,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,GACnB,MAAM,kBAAkB,CAAC;AAG1B,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,MAAM,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAGrE,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACnC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,GACd,MAAM,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_notes - Client-safe exports
|
|
3
|
+
*
|
|
4
|
+
* This is the default entry point for 'hazo_notes' imports
|
|
5
|
+
* Contains only client-safe components, hooks, and types
|
|
6
|
+
*
|
|
7
|
+
* @packageDocumentation
|
|
8
|
+
*/
|
|
9
|
+
// Components
|
|
10
|
+
export * from './components/index.js';
|
|
11
|
+
// Hooks
|
|
12
|
+
export * from './hooks/index.js';
|
|
13
|
+
// Logger (client-side)
|
|
14
|
+
export { LoggerProvider, use_logger, noop_logger } from './logger/index.js';
|
|
15
|
+
// Utils (client-safe)
|
|
16
|
+
export { cn } from './utils/cn.js';
|
|
17
|
+
export { generate_file_no, file_to_base64, get_mime_type, is_allowed_file_type, is_image_file, format_file_size, parse_file_references, create_file_reference, validate_file, } from './utils/file_utils.js';
|
|
18
|
+
//# sourceMappingURL=index.client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.client.js","sourceRoot":"","sources":["../src/index.client.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,aAAa;AACb,cAAc,uBAAuB,CAAC;AAEtC,QAAQ;AACR,cAAc,kBAAkB,CAAC;AAiBjC,uBAAuB;AACvB,OAAO,EAAE,cAAc,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAG5E,sBAAsB;AACtB,OAAO,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACnC,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,GACd,MAAM,uBAAuB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_notes - Database-backed notes system with file attachment support
|
|
3
|
+
*
|
|
4
|
+
* Main entry point exports server-side utilities
|
|
5
|
+
* For client components, use 'hazo_notes' (which maps to index.client.ts)
|
|
6
|
+
* For API handlers, use 'hazo_notes/api'
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
export * from './index.client.js';
|
|
11
|
+
export { get_config, get_notes_config, get_config_path, has_config } from './lib/config.js';
|
|
12
|
+
export { set_server_logger, get_server_logger } from './logger/server.js';
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAGH,cAAc,mBAAmB,CAAC;AAGlC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* hazo_notes - Database-backed notes system with file attachment support
|
|
3
|
+
*
|
|
4
|
+
* Main entry point exports server-side utilities
|
|
5
|
+
* For client components, use 'hazo_notes' (which maps to index.client.ts)
|
|
6
|
+
* For API handlers, use 'hazo_notes/api'
|
|
7
|
+
*
|
|
8
|
+
* @packageDocumentation
|
|
9
|
+
*/
|
|
10
|
+
// Re-export everything from client
|
|
11
|
+
export * from './index.client.js';
|
|
12
|
+
// Server-only exports
|
|
13
|
+
export { get_config, get_notes_config, get_config_path, has_config } from './lib/config.js';
|
|
14
|
+
export { set_server_logger, get_server_logger } from './logger/server.js';
|
|
15
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,mCAAmC;AACnC,cAAc,mBAAmB,CAAC;AAElC,sBAAsB;AACtB,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAC5F,OAAO,EAAE,iBAAiB,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management using hazo_config
|
|
3
|
+
* Reads from hazo_notes_config.ini
|
|
4
|
+
*
|
|
5
|
+
* NOTE: This module is server-only and cannot be imported in client components
|
|
6
|
+
*/
|
|
7
|
+
import 'server-only';
|
|
8
|
+
import type { HazoNotesConfig } from '../types/index.js';
|
|
9
|
+
/**
|
|
10
|
+
* Get configuration values from the config file
|
|
11
|
+
* @param section - The section name in the config file
|
|
12
|
+
* @param key - The key within the section
|
|
13
|
+
* @returns The configuration value or undefined if not found or config file missing
|
|
14
|
+
*/
|
|
15
|
+
export declare function get_config(section: string, key: string): string | undefined;
|
|
16
|
+
/**
|
|
17
|
+
* Get the full notes configuration with defaults
|
|
18
|
+
* @returns Complete HazoNotesConfig object
|
|
19
|
+
*/
|
|
20
|
+
export declare function get_notes_config(): HazoNotesConfig;
|
|
21
|
+
/**
|
|
22
|
+
* Get the path to the config file currently in use
|
|
23
|
+
* @returns The config file path or null if no config loaded
|
|
24
|
+
*/
|
|
25
|
+
export declare function get_config_path(): string | null;
|
|
26
|
+
/**
|
|
27
|
+
* Check if a config file has been loaded
|
|
28
|
+
* @returns true if config file exists and was loaded
|
|
29
|
+
*/
|
|
30
|
+
export declare function has_config(): boolean;
|
|
31
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,aAAa,CAAC;AAMrB,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AA2DzD;;;;;GAKG;AACH,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAe3E;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,IAAI,eAAe,CAoBlD;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,GAAG,IAAI,CAE/C;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,OAAO,CAEpC"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration management using hazo_config
|
|
3
|
+
* Reads from hazo_notes_config.ini
|
|
4
|
+
*
|
|
5
|
+
* NOTE: This module is server-only and cannot be imported in client components
|
|
6
|
+
*/
|
|
7
|
+
import 'server-only';
|
|
8
|
+
import { HazoConfig } from 'hazo_config';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import { fileURLToPath } from 'url';
|
|
11
|
+
import { existsSync } from 'fs';
|
|
12
|
+
import { get_server_logger } from '../logger/server.js';
|
|
13
|
+
// Get the directory of the current module
|
|
14
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
15
|
+
const __dirname = path.dirname(__filename);
|
|
16
|
+
// Config file name and subdirectory
|
|
17
|
+
const CONFIG_SUBDIR = 'config';
|
|
18
|
+
const CONFIG_FILE_NAME = 'hazo_notes_config.ini';
|
|
19
|
+
// Create a singleton instance of HazoConfig
|
|
20
|
+
let config_instance = null;
|
|
21
|
+
let config_path_used = null;
|
|
22
|
+
let config_missing_warned = false;
|
|
23
|
+
/**
|
|
24
|
+
* Get the HazoConfig instance, creating it if it doesn't exist
|
|
25
|
+
* Looks for config file in the consuming application's root (process.cwd())
|
|
26
|
+
* Falls back to package root if not found
|
|
27
|
+
* @returns The HazoConfig instance or null if config file not found
|
|
28
|
+
*/
|
|
29
|
+
function get_config_instance() {
|
|
30
|
+
if (config_instance) {
|
|
31
|
+
return config_instance;
|
|
32
|
+
}
|
|
33
|
+
// First try to find config in the consuming app's config subdirectory
|
|
34
|
+
const app_root_config = path.resolve(process.cwd(), CONFIG_SUBDIR, CONFIG_FILE_NAME);
|
|
35
|
+
// Fallback to package config subdirectory (for development/testing)
|
|
36
|
+
const package_root_config = path.resolve(__dirname, '../../', CONFIG_SUBDIR, CONFIG_FILE_NAME);
|
|
37
|
+
let config_path = null;
|
|
38
|
+
if (existsSync(app_root_config)) {
|
|
39
|
+
config_path = app_root_config;
|
|
40
|
+
}
|
|
41
|
+
else if (existsSync(package_root_config)) {
|
|
42
|
+
config_path = package_root_config;
|
|
43
|
+
}
|
|
44
|
+
if (!config_path) {
|
|
45
|
+
// Only warn once to avoid log spam
|
|
46
|
+
if (!config_missing_warned) {
|
|
47
|
+
config_missing_warned = true;
|
|
48
|
+
get_server_logger().warn('[hazo_notes] Config file not found', {
|
|
49
|
+
searched_locations: [app_root_config, package_root_config],
|
|
50
|
+
hint: `Copy template: cp node_modules/hazo_notes/templates/${CONFIG_SUBDIR}/${CONFIG_FILE_NAME} ./${CONFIG_SUBDIR}/`,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
return null;
|
|
54
|
+
}
|
|
55
|
+
config_path_used = config_path;
|
|
56
|
+
config_instance = new HazoConfig({
|
|
57
|
+
filePath: config_path,
|
|
58
|
+
});
|
|
59
|
+
return config_instance;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Get configuration values from the config file
|
|
63
|
+
* @param section - The section name in the config file
|
|
64
|
+
* @param key - The key within the section
|
|
65
|
+
* @returns The configuration value or undefined if not found or config file missing
|
|
66
|
+
*/
|
|
67
|
+
export function get_config(section, key) {
|
|
68
|
+
try {
|
|
69
|
+
const config = get_config_instance();
|
|
70
|
+
if (!config) {
|
|
71
|
+
return undefined;
|
|
72
|
+
}
|
|
73
|
+
return config.get(section, key);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
get_server_logger().error('[hazo_notes] Error reading config', {
|
|
77
|
+
section,
|
|
78
|
+
key,
|
|
79
|
+
error: error instanceof Error ? error.message : String(error),
|
|
80
|
+
});
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Get the full notes configuration with defaults
|
|
86
|
+
* @returns Complete HazoNotesConfig object
|
|
87
|
+
*/
|
|
88
|
+
export function get_notes_config() {
|
|
89
|
+
return {
|
|
90
|
+
ui: {
|
|
91
|
+
background_color: get_config('ui', 'background_color') || 'bg-yellow-100',
|
|
92
|
+
panel_style: get_config('ui', 'panel_style') || 'popover',
|
|
93
|
+
save_mode: get_config('ui', 'save_mode') || 'explicit',
|
|
94
|
+
},
|
|
95
|
+
storage: {
|
|
96
|
+
file_storage_mode: get_config('storage', 'file_storage_mode') || 'jsonb',
|
|
97
|
+
file_storage_path: get_config('storage', 'file_storage_path') || '/uploads/notes',
|
|
98
|
+
},
|
|
99
|
+
files: {
|
|
100
|
+
max_file_size_mb: parseInt(get_config('files', 'max_file_size_mb') || '10', 10),
|
|
101
|
+
allowed_file_types: (get_config('files', 'allowed_file_types') || 'pdf,png,jpg,jpeg,gif,doc,docx').split(',').map(t => t.trim()),
|
|
102
|
+
max_files_per_note: parseInt(get_config('files', 'max_files_per_note') || '5', 10),
|
|
103
|
+
},
|
|
104
|
+
logging: {
|
|
105
|
+
logfile: get_config('logging', 'logfile') || 'logs/hazo_notes.log',
|
|
106
|
+
},
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Get the path to the config file currently in use
|
|
111
|
+
* @returns The config file path or null if no config loaded
|
|
112
|
+
*/
|
|
113
|
+
export function get_config_path() {
|
|
114
|
+
return config_path_used;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Check if a config file has been loaded
|
|
118
|
+
* @returns true if config file exists and was loaded
|
|
119
|
+
*/
|
|
120
|
+
export function has_config() {
|
|
121
|
+
return get_config_instance() !== null;
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/lib/config.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChC,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAGxD,0CAA0C;AAC1C,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,oCAAoC;AACpC,MAAM,aAAa,GAAG,QAAQ,CAAC;AAC/B,MAAM,gBAAgB,GAAG,uBAAuB,CAAC;AAEjD,4CAA4C;AAC5C,IAAI,eAAe,GAAsB,IAAI,CAAC;AAC9C,IAAI,gBAAgB,GAAkB,IAAI,CAAC;AAC3C,IAAI,qBAAqB,GAAG,KAAK,CAAC;AAElC;;;;;GAKG;AACH,SAAS,mBAAmB;IAC1B,IAAI,eAAe,EAAE,CAAC;QACpB,OAAO,eAAe,CAAC;IACzB,CAAC;IAED,sEAAsE;IACtE,MAAM,eAAe,GAAG,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IACrF,oEAAoE;IACpE,MAAM,mBAAmB,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,QAAQ,EAAE,aAAa,EAAE,gBAAgB,CAAC,CAAC;IAE/F,IAAI,WAAW,GAAkB,IAAI,CAAC;IAEtC,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;QAChC,WAAW,GAAG,eAAe,CAAC;IAChC,CAAC;SAAM,IAAI,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC;QAC3C,WAAW,GAAG,mBAAmB,CAAC;IACpC,CAAC;IAED,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,mCAAmC;QACnC,IAAI,CAAC,qBAAqB,EAAE,CAAC;YAC3B,qBAAqB,GAAG,IAAI,CAAC;YAC7B,iBAAiB,EAAE,CAAC,IAAI,CAAC,oCAAoC,EAAE;gBAC7D,kBAAkB,EAAE,CAAC,eAAe,EAAE,mBAAmB,CAAC;gBAC1D,IAAI,EAAE,uDAAuD,aAAa,IAAI,gBAAgB,MAAM,aAAa,GAAG;aACrH,CAAC,CAAC;QACL,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gBAAgB,GAAG,WAAW,CAAC;IAC/B,eAAe,GAAG,IAAI,UAAU,CAAC;QAC/B,QAAQ,EAAE,WAAW;KACtB,CAAC,CAAC;IAEH,OAAO,eAAe,CAAC;AACzB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,UAAU,CAAC,OAAe,EAAE,GAAW;IACrD,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,mBAAmB,EAAE,CAAC;QACrC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,OAAO,SAAS,CAAC;QACnB,CAAC;QACD,OAAO,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAClC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,iBAAiB,EAAE,CAAC,KAAK,CAAC,mCAAmC,EAAE;YAC7D,OAAO;YACP,GAAG;YACH,KAAK,EAAE,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;SAC9D,CAAC,CAAC;QACH,OAAO,SAAS,CAAC;IACnB,CAAC;AACH,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB;IAC9B,OAAO;QACL,EAAE,EAAE;YACF,gBAAgB,EAAE,UAAU,CAAC,IAAI,EAAE,kBAAkB,CAAC,IAAI,eAAe;YACzE,WAAW,EAAG,UAAU,CAAC,IAAI,EAAE,aAAa,CAA+B,IAAI,SAAS;YACxF,SAAS,EAAG,UAAU,CAAC,IAAI,EAAE,WAAW,CAAyB,IAAI,UAAU;SAChF;QACD,OAAO,EAAE;YACP,iBAAiB,EAAG,UAAU,CAAC,SAAS,EAAE,mBAAmB,CAA4B,IAAI,OAAO;YACpG,iBAAiB,EAAE,UAAU,CAAC,SAAS,EAAE,mBAAmB,CAAC,IAAI,gBAAgB;SAClF;QACD,KAAK,EAAE;YACL,gBAAgB,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,kBAAkB,CAAC,IAAI,IAAI,EAAE,EAAE,CAAC;YAC/E,kBAAkB,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,oBAAoB,CAAC,IAAI,+BAA+B,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;YAChI,kBAAkB,EAAE,QAAQ,CAAC,UAAU,CAAC,OAAO,EAAE,oBAAoB,CAAC,IAAI,GAAG,EAAE,EAAE,CAAC;SACnF;QACD,OAAO,EAAE;YACP,OAAO,EAAE,UAAU,CAAC,SAAS,EAAE,SAAS,CAAC,IAAI,qBAAqB;SACnE;KACF,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,eAAe;IAC7B,OAAO,gBAAgB,CAAC;AAC1B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,OAAO,mBAAmB,EAAE,KAAK,IAAI,CAAC;AACxC,CAAC"}
|