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,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Files API Handler Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates handlers for file upload and download operations.
|
|
5
|
+
* Used for filesystem storage mode.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_notes/files/upload/route.ts
|
|
10
|
+
* import { createFilesHandler } from 'hazo_notes/api';
|
|
11
|
+
*
|
|
12
|
+
* export const dynamic = 'force-dynamic';
|
|
13
|
+
*
|
|
14
|
+
* const { POST } = createFilesHandler({
|
|
15
|
+
* getHazoConnect: () => getHazoConnectSingleton(),
|
|
16
|
+
* getUserIdFromRequest: async (req) => userId,
|
|
17
|
+
* file_storage_mode: 'filesystem',
|
|
18
|
+
* file_storage_path: '/uploads/notes',
|
|
19
|
+
* max_file_size_mb: 10,
|
|
20
|
+
* allowed_file_types: ['pdf', 'png', 'jpg', 'jpeg', 'gif'],
|
|
21
|
+
* });
|
|
22
|
+
*
|
|
23
|
+
* export { POST };
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
import { NextResponse } from 'next/server';
|
|
27
|
+
import { get_mime_type, is_allowed_file_type, generate_file_no, } from '../utils/file_utils.js';
|
|
28
|
+
// ============================================================================
|
|
29
|
+
// Constants
|
|
30
|
+
// ============================================================================
|
|
31
|
+
const DEFAULT_MAX_FILE_SIZE_MB = 10;
|
|
32
|
+
const DEFAULT_ALLOWED_TYPES = ['pdf', 'png', 'jpg', 'jpeg', 'gif', 'doc', 'docx'];
|
|
33
|
+
// ============================================================================
|
|
34
|
+
// Helper Functions
|
|
35
|
+
// ============================================================================
|
|
36
|
+
/** No-op logger */
|
|
37
|
+
const noopLogger = {
|
|
38
|
+
error: () => { },
|
|
39
|
+
warn: () => { },
|
|
40
|
+
info: () => { },
|
|
41
|
+
debug: () => { },
|
|
42
|
+
};
|
|
43
|
+
/** Create error response */
|
|
44
|
+
function createErrorResponse(error, status) {
|
|
45
|
+
return NextResponse.json({ success: false, error }, { status });
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Creates file upload and download handlers
|
|
49
|
+
*
|
|
50
|
+
* @param options - Configuration options
|
|
51
|
+
* @returns Object with POST (upload) and GET (download) handlers
|
|
52
|
+
*/
|
|
53
|
+
export function createFilesHandler(options) {
|
|
54
|
+
const { getHazoConnect, getLogger, getUserIdFromRequest, file_storage_mode = 'jsonb', file_storage_path = '/uploads/notes', max_file_size_mb = DEFAULT_MAX_FILE_SIZE_MB, allowed_file_types = DEFAULT_ALLOWED_TYPES, } = options;
|
|
55
|
+
const logger = getLogger?.() || noopLogger;
|
|
56
|
+
const max_bytes = max_file_size_mb * 1024 * 1024;
|
|
57
|
+
/**
|
|
58
|
+
* POST handler - Upload a file
|
|
59
|
+
*
|
|
60
|
+
* Accepts multipart/form-data with:
|
|
61
|
+
* - file: The file to upload
|
|
62
|
+
* - ref_id: Reference ID for the notes
|
|
63
|
+
* - embed_type: 'embed' or 'attachment'
|
|
64
|
+
*/
|
|
65
|
+
async function POST(request) {
|
|
66
|
+
try {
|
|
67
|
+
// Check authentication
|
|
68
|
+
const userId = getUserIdFromRequest
|
|
69
|
+
? await getUserIdFromRequest(request)
|
|
70
|
+
: null;
|
|
71
|
+
if (!userId) {
|
|
72
|
+
return createErrorResponse('Unauthorized', 401);
|
|
73
|
+
}
|
|
74
|
+
// Parse form data
|
|
75
|
+
const formData = await request.formData();
|
|
76
|
+
const file = formData.get('file');
|
|
77
|
+
const ref_id = formData.get('ref_id');
|
|
78
|
+
const embed_type = formData.get('embed_type') || 'attachment';
|
|
79
|
+
if (!file) {
|
|
80
|
+
return createErrorResponse('No file provided', 400);
|
|
81
|
+
}
|
|
82
|
+
if (!ref_id) {
|
|
83
|
+
return createErrorResponse('ref_id is required', 400);
|
|
84
|
+
}
|
|
85
|
+
// Validate file type
|
|
86
|
+
if (!is_allowed_file_type(file.name, allowed_file_types)) {
|
|
87
|
+
return createErrorResponse(`File type not allowed. Allowed types: ${allowed_file_types.join(', ')}`, 400);
|
|
88
|
+
}
|
|
89
|
+
// Validate file size
|
|
90
|
+
if (file.size > max_bytes) {
|
|
91
|
+
return createErrorResponse(`File size exceeds maximum of ${max_file_size_mb} MB`, 400);
|
|
92
|
+
}
|
|
93
|
+
logger.debug('[hazo_notes/files] Upload request', {
|
|
94
|
+
filename: file.name,
|
|
95
|
+
size: file.size,
|
|
96
|
+
ref_id,
|
|
97
|
+
embed_type,
|
|
98
|
+
storage_mode: file_storage_mode,
|
|
99
|
+
});
|
|
100
|
+
// Generate file number
|
|
101
|
+
const file_no = generate_file_no([]);
|
|
102
|
+
let filedata;
|
|
103
|
+
if (file_storage_mode === 'filesystem') {
|
|
104
|
+
// Filesystem storage - save to disk and store path
|
|
105
|
+
try {
|
|
106
|
+
const fs = await import('fs/promises');
|
|
107
|
+
const path = await import('path');
|
|
108
|
+
// Create directory if it doesn't exist
|
|
109
|
+
const upload_dir = path.join(process.cwd(), file_storage_path, ref_id);
|
|
110
|
+
await fs.mkdir(upload_dir, { recursive: true });
|
|
111
|
+
// Save file
|
|
112
|
+
const safe_filename = `${file_no}_${file.name.replace(/[^a-zA-Z0-9._-]/g, '_')}`;
|
|
113
|
+
const file_path = path.join(upload_dir, safe_filename);
|
|
114
|
+
const buffer = Buffer.from(await file.arrayBuffer());
|
|
115
|
+
await fs.writeFile(file_path, buffer);
|
|
116
|
+
// Store relative path
|
|
117
|
+
filedata = `${file_storage_path}/${ref_id}/${safe_filename}`;
|
|
118
|
+
logger.debug('[hazo_notes/files] File saved to filesystem', { path: filedata });
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
logger.error('[hazo_notes/files] Filesystem write error', {
|
|
122
|
+
error: error instanceof Error ? error.message : String(error),
|
|
123
|
+
});
|
|
124
|
+
return createErrorResponse('Failed to save file', 500);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// JSONB storage - convert to base64
|
|
129
|
+
const buffer = await file.arrayBuffer();
|
|
130
|
+
filedata = Buffer.from(buffer).toString('base64');
|
|
131
|
+
}
|
|
132
|
+
const note_file = {
|
|
133
|
+
file_no,
|
|
134
|
+
embed_type,
|
|
135
|
+
filename: file.name,
|
|
136
|
+
filedata,
|
|
137
|
+
mime_type: get_mime_type(file.name),
|
|
138
|
+
file_size: file.size,
|
|
139
|
+
};
|
|
140
|
+
return NextResponse.json({
|
|
141
|
+
success: true,
|
|
142
|
+
file: note_file,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
catch (error) {
|
|
146
|
+
logger.error('[hazo_notes/files] Upload error', {
|
|
147
|
+
error: error instanceof Error ? error.message : String(error),
|
|
148
|
+
});
|
|
149
|
+
return createErrorResponse('Failed to upload file', 500);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* GET handler - Download a file (for filesystem storage mode)
|
|
154
|
+
*
|
|
155
|
+
* Query params:
|
|
156
|
+
* - ref_id: Reference ID
|
|
157
|
+
* - file_no: File number
|
|
158
|
+
*/
|
|
159
|
+
async function GET(request, context) {
|
|
160
|
+
try {
|
|
161
|
+
if (file_storage_mode !== 'filesystem') {
|
|
162
|
+
return createErrorResponse('File download only available for filesystem storage mode', 400);
|
|
163
|
+
}
|
|
164
|
+
const url = new URL(request.url);
|
|
165
|
+
const ref_id = url.searchParams.get('ref_id');
|
|
166
|
+
const file_no = url.searchParams.get('file_no');
|
|
167
|
+
if (!ref_id || !file_no) {
|
|
168
|
+
return createErrorResponse('ref_id and file_no are required', 400);
|
|
169
|
+
}
|
|
170
|
+
// Get notes to find the file
|
|
171
|
+
const hazoConnect = await getHazoConnect();
|
|
172
|
+
const result = await hazoConnect.rawQuery(`/hazo_notes?ref_id=eq.${ref_id}`);
|
|
173
|
+
if (!result || result.length === 0) {
|
|
174
|
+
return createErrorResponse('Notes not found', 404);
|
|
175
|
+
}
|
|
176
|
+
// Find the file in notes
|
|
177
|
+
const notes = result[0].note || [];
|
|
178
|
+
let file_info = null;
|
|
179
|
+
for (const note of notes) {
|
|
180
|
+
if (note.note_files) {
|
|
181
|
+
const found = note.note_files.find((f) => f.file_no === file_no);
|
|
182
|
+
if (found) {
|
|
183
|
+
file_info = found;
|
|
184
|
+
break;
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (!file_info) {
|
|
189
|
+
return createErrorResponse('File not found', 404);
|
|
190
|
+
}
|
|
191
|
+
// Read file from filesystem
|
|
192
|
+
const fs = await import('fs/promises');
|
|
193
|
+
const path = await import('path');
|
|
194
|
+
const file_path = path.join(process.cwd(), file_info.filedata);
|
|
195
|
+
const buffer = await fs.readFile(file_path);
|
|
196
|
+
return new NextResponse(buffer, {
|
|
197
|
+
headers: {
|
|
198
|
+
'Content-Type': file_info.mime_type || 'application/octet-stream',
|
|
199
|
+
'Content-Disposition': `attachment; filename="${file_info.filename}"`,
|
|
200
|
+
'Content-Length': String(buffer.length),
|
|
201
|
+
},
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
logger.error('[hazo_notes/files] Download error', {
|
|
206
|
+
error: error instanceof Error ? error.message : String(error),
|
|
207
|
+
});
|
|
208
|
+
return createErrorResponse('Failed to download file', 500);
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
return { GET, POST };
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=create_files_handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_files_handler.js","sourceRoot":"","sources":["../../src/api/create_files_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notes API Handler Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates GET and POST handlers for the /api/hazo_notes/[ref_id] endpoint.
|
|
5
|
+
* These handlers should be used in a Next.js API route.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_notes/[ref_id]/route.ts
|
|
10
|
+
* import { createNotesHandler } from 'hazo_notes/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createNotesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton(),
|
|
17
|
+
* getUserIdFromRequest: async (req) => {
|
|
18
|
+
* // Your auth logic here
|
|
19
|
+
* return userId;
|
|
20
|
+
* },
|
|
21
|
+
* getUserProfile: async (userId) => {
|
|
22
|
+
* // Your profile lookup logic here
|
|
23
|
+
* return { id: userId, name: 'User', email: 'user@example.com' };
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* export { GET, POST };
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { NextResponse } from 'next/server';
|
|
31
|
+
import type { CreateNotesHandlerOptions, NotesApiResponse, AddNoteApiResponse } from '../types/index.js';
|
|
32
|
+
/**
|
|
33
|
+
* Creates GET and POST handlers for notes
|
|
34
|
+
*
|
|
35
|
+
* @param options - Configuration options
|
|
36
|
+
* @returns Object with GET and POST handlers
|
|
37
|
+
*/
|
|
38
|
+
export declare function createNotesHandler(options: CreateNotesHandlerOptions): {
|
|
39
|
+
GET: (request: Request, context: {
|
|
40
|
+
params: Promise<{
|
|
41
|
+
ref_id: string;
|
|
42
|
+
}>;
|
|
43
|
+
}) => Promise<NextResponse<NotesApiResponse>>;
|
|
44
|
+
POST: (request: Request, context: {
|
|
45
|
+
params: Promise<{
|
|
46
|
+
ref_id: string;
|
|
47
|
+
}>;
|
|
48
|
+
}) => Promise<NextResponse<AddNoteApiResponse>>;
|
|
49
|
+
};
|
|
50
|
+
//# sourceMappingURL=create_notes_handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_notes_handler.d.ts","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,KAAK,EACV,yBAAyB,EAIzB,gBAAgB,EAChB,kBAAkB,EAEnB,MAAM,mBAAmB,CAAC;AA+C3B;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,yBAAyB;mBAWxD,OAAO,WACP;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC/C,OAAO,CAAC,YAAY,CAAC,gBAAgB,CAAC,CAAC;oBAoE/B,OAAO,WACP;QAAE,MAAM,EAAE,OAAO,CAAC;YAAE,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC,CAAA;KAAE,KAC/C,OAAO,CAAC,YAAY,CAAC,kBAAkB,CAAC,CAAC;EAkJ7C"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Notes API Handler Factory
|
|
3
|
+
*
|
|
4
|
+
* Creates GET and POST handlers for the /api/hazo_notes/[ref_id] endpoint.
|
|
5
|
+
* These handlers should be used in a Next.js API route.
|
|
6
|
+
*
|
|
7
|
+
* @example
|
|
8
|
+
* ```typescript
|
|
9
|
+
* // app/api/hazo_notes/[ref_id]/route.ts
|
|
10
|
+
* import { createNotesHandler } from 'hazo_notes/api';
|
|
11
|
+
* import { getHazoConnectSingleton } from 'hazo_connect/nextjs/setup';
|
|
12
|
+
*
|
|
13
|
+
* export const dynamic = 'force-dynamic';
|
|
14
|
+
*
|
|
15
|
+
* const { GET, POST } = createNotesHandler({
|
|
16
|
+
* getHazoConnect: () => getHazoConnectSingleton(),
|
|
17
|
+
* getUserIdFromRequest: async (req) => {
|
|
18
|
+
* // Your auth logic here
|
|
19
|
+
* return userId;
|
|
20
|
+
* },
|
|
21
|
+
* getUserProfile: async (userId) => {
|
|
22
|
+
* // Your profile lookup logic here
|
|
23
|
+
* return { id: userId, name: 'User', email: 'user@example.com' };
|
|
24
|
+
* }
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* export { GET, POST };
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
import { NextResponse } from 'next/server';
|
|
31
|
+
// ============================================================================
|
|
32
|
+
// Constants
|
|
33
|
+
// ============================================================================
|
|
34
|
+
/** Maximum note text length in characters */
|
|
35
|
+
const MAX_NOTE_TEXT_LENGTH = 10000;
|
|
36
|
+
/** Maximum files per note */
|
|
37
|
+
const DEFAULT_MAX_FILES_PER_NOTE = 5;
|
|
38
|
+
// ============================================================================
|
|
39
|
+
// Helper Functions
|
|
40
|
+
// ============================================================================
|
|
41
|
+
/** Generate a UUID v4 */
|
|
42
|
+
function generateUUID() {
|
|
43
|
+
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) {
|
|
44
|
+
const r = (Math.random() * 16) | 0;
|
|
45
|
+
const v = c === 'x' ? r : (r & 0x3) | 0x8;
|
|
46
|
+
return v.toString(16);
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
/** Create a standardized error response */
|
|
50
|
+
function createErrorResponse(error, status) {
|
|
51
|
+
return NextResponse.json({
|
|
52
|
+
success: false,
|
|
53
|
+
error,
|
|
54
|
+
}, { status });
|
|
55
|
+
}
|
|
56
|
+
/** No-op logger */
|
|
57
|
+
const noopLogger = {
|
|
58
|
+
error: () => { },
|
|
59
|
+
warn: () => { },
|
|
60
|
+
info: () => { },
|
|
61
|
+
debug: () => { },
|
|
62
|
+
};
|
|
63
|
+
/**
|
|
64
|
+
* Creates GET and POST handlers for notes
|
|
65
|
+
*
|
|
66
|
+
* @param options - Configuration options
|
|
67
|
+
* @returns Object with GET and POST handlers
|
|
68
|
+
*/
|
|
69
|
+
export function createNotesHandler(options) {
|
|
70
|
+
const { getHazoConnect, getLogger, getUserIdFromRequest, getUserProfile } = options;
|
|
71
|
+
const logger = getLogger?.() || noopLogger;
|
|
72
|
+
/**
|
|
73
|
+
* GET handler - Fetch notes for a ref_id
|
|
74
|
+
*
|
|
75
|
+
* @param request - The incoming request
|
|
76
|
+
* @param context - Route context with params
|
|
77
|
+
*/
|
|
78
|
+
async function GET(request, context) {
|
|
79
|
+
try {
|
|
80
|
+
const { ref_id } = await context.params;
|
|
81
|
+
if (!ref_id) {
|
|
82
|
+
return createErrorResponse('ref_id is required', 400);
|
|
83
|
+
}
|
|
84
|
+
logger.debug('[hazo_notes] GET request', { ref_id });
|
|
85
|
+
const hazoConnect = await getHazoConnect();
|
|
86
|
+
// Query the hazo_notes table using PostgREST-style query
|
|
87
|
+
const result = await hazoConnect.rawQuery(`/hazo_notes?ref_id=eq.${ref_id}`);
|
|
88
|
+
if (!result || result.length === 0) {
|
|
89
|
+
return NextResponse.json({
|
|
90
|
+
success: true,
|
|
91
|
+
notes: [],
|
|
92
|
+
note_count: 0,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
const row = result[0];
|
|
96
|
+
const notes_db = Array.isArray(row.note) ? row.note : [];
|
|
97
|
+
// Enrich notes with user profiles if getUserProfile is provided
|
|
98
|
+
let notes;
|
|
99
|
+
if (getUserProfile) {
|
|
100
|
+
notes = await Promise.all(notes_db.map(async (note) => {
|
|
101
|
+
const profile = await getUserProfile(note.userid).catch(() => null);
|
|
102
|
+
return {
|
|
103
|
+
...note,
|
|
104
|
+
user_name: profile?.name || 'Unknown User',
|
|
105
|
+
user_email: profile?.email || '',
|
|
106
|
+
user_avatar: profile?.profile_image,
|
|
107
|
+
};
|
|
108
|
+
}));
|
|
109
|
+
}
|
|
110
|
+
else {
|
|
111
|
+
notes = notes_db.map((note) => ({
|
|
112
|
+
...note,
|
|
113
|
+
user_name: 'Unknown User',
|
|
114
|
+
user_email: '',
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
return NextResponse.json({
|
|
118
|
+
success: true,
|
|
119
|
+
notes,
|
|
120
|
+
note_count: row.note_count,
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
catch (error) {
|
|
124
|
+
logger.error('[hazo_notes] GET error', {
|
|
125
|
+
error: error instanceof Error ? error.message : String(error),
|
|
126
|
+
});
|
|
127
|
+
return createErrorResponse('Failed to fetch notes', 500);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* POST handler - Add a new note
|
|
132
|
+
*
|
|
133
|
+
* @param request - The incoming request
|
|
134
|
+
* @param context - Route context with params
|
|
135
|
+
*/
|
|
136
|
+
async function POST(request, context) {
|
|
137
|
+
try {
|
|
138
|
+
const { ref_id } = await context.params;
|
|
139
|
+
if (!ref_id) {
|
|
140
|
+
return NextResponse.json({ success: false, error: 'ref_id is required' }, { status: 400 });
|
|
141
|
+
}
|
|
142
|
+
// Get user ID from request
|
|
143
|
+
const userId = getUserIdFromRequest
|
|
144
|
+
? await getUserIdFromRequest(request)
|
|
145
|
+
: null;
|
|
146
|
+
if (!userId) {
|
|
147
|
+
return NextResponse.json({ success: false, error: 'Unauthorized - user not authenticated' }, { status: 401 });
|
|
148
|
+
}
|
|
149
|
+
// Parse request body
|
|
150
|
+
const body = await request.json();
|
|
151
|
+
const { note_text, note_files } = body;
|
|
152
|
+
// Validate note_text
|
|
153
|
+
if (!note_text || typeof note_text !== 'string') {
|
|
154
|
+
return NextResponse.json({ success: false, error: 'note_text is required' }, { status: 400 });
|
|
155
|
+
}
|
|
156
|
+
if (note_text.length > MAX_NOTE_TEXT_LENGTH) {
|
|
157
|
+
return NextResponse.json({
|
|
158
|
+
success: false,
|
|
159
|
+
error: `note_text exceeds maximum length of ${MAX_NOTE_TEXT_LENGTH} characters`,
|
|
160
|
+
}, { status: 400 });
|
|
161
|
+
}
|
|
162
|
+
// Validate note_files if provided
|
|
163
|
+
if (note_files) {
|
|
164
|
+
if (!Array.isArray(note_files)) {
|
|
165
|
+
return NextResponse.json({ success: false, error: 'note_files must be an array' }, { status: 400 });
|
|
166
|
+
}
|
|
167
|
+
if (note_files.length > DEFAULT_MAX_FILES_PER_NOTE) {
|
|
168
|
+
return NextResponse.json({
|
|
169
|
+
success: false,
|
|
170
|
+
error: `Maximum ${DEFAULT_MAX_FILES_PER_NOTE} files per note allowed`,
|
|
171
|
+
}, { status: 400 });
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
logger.debug('[hazo_notes] POST request', { ref_id, userId });
|
|
175
|
+
const hazoConnect = await getHazoConnect();
|
|
176
|
+
// Create new note entry
|
|
177
|
+
const new_note = {
|
|
178
|
+
userid: userId,
|
|
179
|
+
created_at: new Date().toISOString(),
|
|
180
|
+
note_text: note_text.trim(),
|
|
181
|
+
note_files: note_files || undefined,
|
|
182
|
+
};
|
|
183
|
+
// Check if row exists for this ref_id
|
|
184
|
+
const existing = await hazoConnect.rawQuery(`/hazo_notes?ref_id=eq.${ref_id}`);
|
|
185
|
+
let updated_count;
|
|
186
|
+
if (!existing || existing.length === 0) {
|
|
187
|
+
// Create new row with first note
|
|
188
|
+
const new_id = generateUUID();
|
|
189
|
+
await hazoConnect.rawQuery('/hazo_notes', {
|
|
190
|
+
method: 'POST',
|
|
191
|
+
body: JSON.stringify({
|
|
192
|
+
id: new_id,
|
|
193
|
+
ref_id,
|
|
194
|
+
note: [new_note],
|
|
195
|
+
note_count: 1,
|
|
196
|
+
}),
|
|
197
|
+
headers: { 'Content-Type': 'application/json' },
|
|
198
|
+
});
|
|
199
|
+
updated_count = 1;
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
// Append to existing notes array
|
|
203
|
+
const row = existing[0];
|
|
204
|
+
const existing_notes = Array.isArray(row.note) ? row.note : [];
|
|
205
|
+
const updated_notes = [...existing_notes, new_note];
|
|
206
|
+
updated_count = updated_notes.length;
|
|
207
|
+
await hazoConnect.rawQuery(`/hazo_notes?id=eq.${row.id}`, {
|
|
208
|
+
method: 'PATCH',
|
|
209
|
+
body: JSON.stringify({
|
|
210
|
+
note: updated_notes,
|
|
211
|
+
note_count: updated_count,
|
|
212
|
+
changed_at: new Date().toISOString(),
|
|
213
|
+
}),
|
|
214
|
+
headers: { 'Content-Type': 'application/json' },
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
// Get user profile for response
|
|
218
|
+
const profile = getUserProfile
|
|
219
|
+
? await getUserProfile(userId).catch(() => null)
|
|
220
|
+
: null;
|
|
221
|
+
const enriched_note = {
|
|
222
|
+
...new_note,
|
|
223
|
+
user_name: profile?.name || 'Unknown User',
|
|
224
|
+
user_email: profile?.email || '',
|
|
225
|
+
user_avatar: profile?.profile_image,
|
|
226
|
+
};
|
|
227
|
+
return NextResponse.json({
|
|
228
|
+
success: true,
|
|
229
|
+
note: enriched_note,
|
|
230
|
+
note_count: updated_count,
|
|
231
|
+
});
|
|
232
|
+
}
|
|
233
|
+
catch (error) {
|
|
234
|
+
logger.error('[hazo_notes] POST error', {
|
|
235
|
+
error: error instanceof Error ? error.message : String(error),
|
|
236
|
+
});
|
|
237
|
+
return NextResponse.json({ success: false, error: 'Failed to add note' }, { status: 500 });
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
return { GET, POST };
|
|
241
|
+
}
|
|
242
|
+
//# sourceMappingURL=create_notes_handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create_notes_handler.js","sourceRoot":"","sources":["../../src/api/create_notes_handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API handlers for hazo_notes
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating Next.js API route handlers
|
|
5
|
+
*/
|
|
6
|
+
export { createNotesHandler } from './create_notes_handler.js';
|
|
7
|
+
export { createFilesHandler } from './create_files_handler.js';
|
|
8
|
+
export type { CreateNotesHandlerOptions, CreateFilesHandlerOptions, NotesApiResponse, AddNoteApiResponse, FileUploadApiResponse, } from '../types/index.js';
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAG/D,YAAY,EACV,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,mBAAmB,CAAC"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API handlers for hazo_notes
|
|
3
|
+
*
|
|
4
|
+
* Factory functions for creating Next.js API route handlers
|
|
5
|
+
*/
|
|
6
|
+
export { createNotesHandler } from './create_notes_handler.js';
|
|
7
|
+
export { createFilesHandler } from './create_files_handler.js';
|
|
8
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/api/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC;AAC/D,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { HazoNotesEntryProps } from '../types/index.js';
|
|
2
|
+
/**
|
|
3
|
+
* Single note entry display component
|
|
4
|
+
*/
|
|
5
|
+
export declare function HazoNotesEntry({ note, ProfileStampComponent }: HazoNotesEntryProps): import("react/jsx-runtime").JSX.Element;
|
|
6
|
+
//# sourceMappingURL=hazo_notes_entry.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hazo_notes_entry.d.ts","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"AASA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AA+C7D;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,IAAI,EAAE,qBAAqB,EAAE,EAAE,mBAAmB,2CAmElF"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
'use client';
|
|
2
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
3
|
+
import { render_note_with_files } from './hazo_notes_file_preview.js';
|
|
4
|
+
/**
|
|
5
|
+
* Format timestamp for display
|
|
6
|
+
*/
|
|
7
|
+
function format_timestamp(iso_timestamp) {
|
|
8
|
+
try {
|
|
9
|
+
const date = new Date(iso_timestamp);
|
|
10
|
+
return date.toLocaleString('en-US', {
|
|
11
|
+
month: 'short',
|
|
12
|
+
day: 'numeric',
|
|
13
|
+
hour: '2-digit',
|
|
14
|
+
minute: '2-digit',
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return iso_timestamp;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Get initials from name for avatar
|
|
23
|
+
*/
|
|
24
|
+
function get_initials(name) {
|
|
25
|
+
const parts = name.trim().split(/\s+/);
|
|
26
|
+
if (parts.length >= 2) {
|
|
27
|
+
return (parts[0][0] + parts[parts.length - 1][0]).toUpperCase();
|
|
28
|
+
}
|
|
29
|
+
return name.substring(0, 2).toUpperCase();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Generate consistent hex color from name for avatar background
|
|
33
|
+
*/
|
|
34
|
+
function get_avatar_color(name) {
|
|
35
|
+
const colors = [
|
|
36
|
+
'#ef4444', '#f97316', '#d97706', '#22c55e',
|
|
37
|
+
'#14b8a6', '#3b82f6', '#6366f1', '#a855f7',
|
|
38
|
+
'#ec4899', '#f43f5e',
|
|
39
|
+
];
|
|
40
|
+
let hash = 0;
|
|
41
|
+
for (let i = 0; i < name.length; i++) {
|
|
42
|
+
hash = name.charCodeAt(i) + ((hash << 5) - hash);
|
|
43
|
+
}
|
|
44
|
+
return colors[Math.abs(hash) % colors.length];
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Single note entry display component
|
|
48
|
+
*/
|
|
49
|
+
export function HazoNotesEntry({ note, ProfileStampComponent }) {
|
|
50
|
+
const { user_name, user_avatar, created_at, note_text, note_files } = note;
|
|
51
|
+
// Render avatar
|
|
52
|
+
const render_avatar = () => {
|
|
53
|
+
if (ProfileStampComponent) {
|
|
54
|
+
const custom_fields = [{ label: 'Posted', value: format_timestamp(created_at) }];
|
|
55
|
+
return (_jsx(ProfileStampComponent, { size: "sm", show_name: false, show_email: false, custom_fields: custom_fields }));
|
|
56
|
+
}
|
|
57
|
+
// Fallback to image or initials
|
|
58
|
+
if (user_avatar) {
|
|
59
|
+
return (_jsx("img", { src: user_avatar, alt: user_name, className: "w-7 h-7 rounded-full object-cover flex-shrink-0", title: user_name }));
|
|
60
|
+
}
|
|
61
|
+
// Initials avatar
|
|
62
|
+
return (_jsx("span", { className: "w-7 h-7 rounded-full inline-flex items-center justify-center text-xs font-bold flex-shrink-0", style: {
|
|
63
|
+
backgroundColor: get_avatar_color(user_name),
|
|
64
|
+
color: '#ffffff',
|
|
65
|
+
}, title: user_name, children: get_initials(user_name) }));
|
|
66
|
+
};
|
|
67
|
+
return (_jsxs("div", { className: "cls_hazo_notes_entry p-3", children: [_jsxs("div", { className: "flex items-center gap-2 mb-2", children: [render_avatar(), !ProfileStampComponent && (_jsx("span", { className: "text-xs text-yellow-700 flex-shrink-0", children: format_timestamp(created_at) }))] }), _jsx("div", { className: "cls_hazo_notes_entry_content ml-9 overflow-hidden", children: _jsx("div", { className: "w-full min-h-[40px] rounded-md border border-yellow-400 px-3 py-2 text-sm text-yellow-900 overflow-hidden", style: { backgroundColor: '#d4c896' }, children: render_note_with_files(note_text, note_files) }) })] }));
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=hazo_notes_entry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hazo_notes_entry.js","sourceRoot":"","sources":["../../src/components/hazo_notes_entry.tsx"],"names":[],"mappings":"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"}
|