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.
Files changed (97) hide show
  1. package/README.md +661 -0
  2. package/SETUP_CHECKLIST.md +453 -0
  3. package/dist/api/create_files_handler.d.ts +42 -0
  4. package/dist/api/create_files_handler.d.ts.map +1 -0
  5. package/dist/api/create_files_handler.js +213 -0
  6. package/dist/api/create_files_handler.js.map +1 -0
  7. package/dist/api/create_notes_handler.d.ts +50 -0
  8. package/dist/api/create_notes_handler.d.ts.map +1 -0
  9. package/dist/api/create_notes_handler.js +242 -0
  10. package/dist/api/create_notes_handler.js.map +1 -0
  11. package/dist/api/index.d.ts +9 -0
  12. package/dist/api/index.d.ts.map +1 -0
  13. package/dist/api/index.js +8 -0
  14. package/dist/api/index.js.map +1 -0
  15. package/dist/components/hazo_notes_entry.d.ts +6 -0
  16. package/dist/components/hazo_notes_entry.d.ts.map +1 -0
  17. package/dist/components/hazo_notes_entry.js +69 -0
  18. package/dist/components/hazo_notes_entry.js.map +1 -0
  19. package/dist/components/hazo_notes_file_preview.d.ts +16 -0
  20. package/dist/components/hazo_notes_file_preview.d.ts.map +1 -0
  21. package/dist/components/hazo_notes_file_preview.js +77 -0
  22. package/dist/components/hazo_notes_file_preview.js.map +1 -0
  23. package/dist/components/hazo_notes_icon.d.ts +6 -0
  24. package/dist/components/hazo_notes_icon.d.ts.map +1 -0
  25. package/dist/components/hazo_notes_icon.js +208 -0
  26. package/dist/components/hazo_notes_icon.js.map +1 -0
  27. package/dist/components/hazo_notes_panel.d.ts +6 -0
  28. package/dist/components/hazo_notes_panel.d.ts.map +1 -0
  29. package/dist/components/hazo_notes_panel.js +197 -0
  30. package/dist/components/hazo_notes_panel.js.map +1 -0
  31. package/dist/components/index.d.ts +8 -0
  32. package/dist/components/index.d.ts.map +1 -0
  33. package/dist/components/index.js +8 -0
  34. package/dist/components/index.js.map +1 -0
  35. package/dist/hooks/index.d.ts +8 -0
  36. package/dist/hooks/index.d.ts.map +1 -0
  37. package/dist/hooks/index.js +6 -0
  38. package/dist/hooks/index.js.map +1 -0
  39. package/dist/hooks/use_notes.d.ts +46 -0
  40. package/dist/hooks/use_notes.d.ts.map +1 -0
  41. package/dist/hooks/use_notes.js +146 -0
  42. package/dist/hooks/use_notes.js.map +1 -0
  43. package/dist/hooks/use_notes_file_upload.d.ts +52 -0
  44. package/dist/hooks/use_notes_file_upload.d.ts.map +1 -0
  45. package/dist/hooks/use_notes_file_upload.js +125 -0
  46. package/dist/hooks/use_notes_file_upload.js.map +1 -0
  47. package/dist/index.client.d.ts +16 -0
  48. package/dist/index.client.d.ts.map +1 -0
  49. package/dist/index.client.js +18 -0
  50. package/dist/index.client.js.map +1 -0
  51. package/dist/index.d.ts +13 -0
  52. package/dist/index.d.ts.map +1 -0
  53. package/dist/index.js +15 -0
  54. package/dist/index.js.map +1 -0
  55. package/dist/lib/config.d.ts +31 -0
  56. package/dist/lib/config.d.ts.map +1 -0
  57. package/dist/lib/config.js +123 -0
  58. package/dist/lib/config.js.map +1 -0
  59. package/dist/lib/index.d.ts +6 -0
  60. package/dist/lib/index.d.ts.map +1 -0
  61. package/dist/lib/index.js +6 -0
  62. package/dist/lib/index.js.map +1 -0
  63. package/dist/logger/context.d.ts +49 -0
  64. package/dist/logger/context.d.ts.map +1 -0
  65. package/dist/logger/context.js +45 -0
  66. package/dist/logger/context.js.map +1 -0
  67. package/dist/logger/index.d.ts +9 -0
  68. package/dist/logger/index.d.ts.map +1 -0
  69. package/dist/logger/index.js +7 -0
  70. package/dist/logger/index.js.map +1 -0
  71. package/dist/logger/server.d.ts +27 -0
  72. package/dist/logger/server.d.ts.map +1 -0
  73. package/dist/logger/server.js +36 -0
  74. package/dist/logger/server.js.map +1 -0
  75. package/dist/logger/types.d.ts +20 -0
  76. package/dist/logger/types.d.ts.map +1 -0
  77. package/dist/logger/types.js +15 -0
  78. package/dist/logger/types.js.map +1 -0
  79. package/dist/types/index.d.ts +267 -0
  80. package/dist/types/index.d.ts.map +1 -0
  81. package/dist/types/index.js +5 -0
  82. package/dist/types/index.js.map +1 -0
  83. package/dist/utils/cn.d.ts +16 -0
  84. package/dist/utils/cn.d.ts.map +1 -0
  85. package/dist/utils/cn.js +19 -0
  86. package/dist/utils/cn.js.map +1 -0
  87. package/dist/utils/file_utils.d.ts +51 -0
  88. package/dist/utils/file_utils.d.ts.map +1 -0
  89. package/dist/utils/file_utils.js +128 -0
  90. package/dist/utils/file_utils.js.map +1 -0
  91. package/dist/utils/index.d.ts +6 -0
  92. package/dist/utils/index.d.ts.map +1 -0
  93. package/dist/utils/index.js +6 -0
  94. package/dist/utils/index.js.map +1 -0
  95. package/migrations/001_create_hazo_notes_table.sql +77 -0
  96. package/package.json +119 -0
  97. package/templates/config/hazo_notes_config.ini +43 -0
@@ -0,0 +1,128 @@
1
+ /**
2
+ * File utility functions for hazo_notes
3
+ */
4
+ /**
5
+ * Generate a sequential file number (e.g., "0001", "0002")
6
+ */
7
+ export function generate_file_no(existing_files) {
8
+ const max_no = existing_files.reduce((max, file) => {
9
+ const num = parseInt(file.file_no, 10);
10
+ return isNaN(num) ? max : Math.max(max, num);
11
+ }, 0);
12
+ return String(max_no + 1).padStart(4, '0');
13
+ }
14
+ /**
15
+ * Convert File object to base64 string
16
+ */
17
+ export async function file_to_base64(file) {
18
+ return new Promise((resolve, reject) => {
19
+ const reader = new FileReader();
20
+ reader.onload = () => {
21
+ const result = reader.result;
22
+ // Remove data URL prefix (e.g., "data:image/png;base64,")
23
+ const base64 = result.split(',')[1] || result;
24
+ resolve(base64);
25
+ };
26
+ reader.onerror = () => reject(new Error('Failed to read file'));
27
+ reader.readAsDataURL(file);
28
+ });
29
+ }
30
+ /**
31
+ * Get MIME type from filename extension
32
+ */
33
+ export function get_mime_type(filename) {
34
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
35
+ const mime_types = {
36
+ // Images
37
+ png: 'image/png',
38
+ jpg: 'image/jpeg',
39
+ jpeg: 'image/jpeg',
40
+ gif: 'image/gif',
41
+ webp: 'image/webp',
42
+ svg: 'image/svg+xml',
43
+ // Documents
44
+ pdf: 'application/pdf',
45
+ doc: 'application/msword',
46
+ docx: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
47
+ xls: 'application/vnd.ms-excel',
48
+ xlsx: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
49
+ txt: 'text/plain',
50
+ csv: 'text/csv',
51
+ // Archives
52
+ zip: 'application/zip',
53
+ rar: 'application/vnd.rar',
54
+ };
55
+ return mime_types[ext] || 'application/octet-stream';
56
+ }
57
+ /**
58
+ * Check if file type is allowed
59
+ */
60
+ export function is_allowed_file_type(filename, allowed_types) {
61
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
62
+ return allowed_types.map(t => t.toLowerCase()).includes(ext);
63
+ }
64
+ /**
65
+ * Check if file is an image (can be embedded)
66
+ */
67
+ export function is_image_file(filename) {
68
+ const ext = filename.split('.').pop()?.toLowerCase() || '';
69
+ return ['png', 'jpg', 'jpeg', 'gif', 'webp', 'svg'].includes(ext);
70
+ }
71
+ /**
72
+ * Format file size for display
73
+ */
74
+ export function format_file_size(bytes) {
75
+ if (bytes === 0)
76
+ return '0 B';
77
+ const k = 1024;
78
+ const sizes = ['B', 'KB', 'MB', 'GB'];
79
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
80
+ return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
81
+ }
82
+ /**
83
+ * Parse note text and extract file references
84
+ * Returns array of { type: 'embed' | 'attach', file_no: string }
85
+ */
86
+ export function parse_file_references(note_text) {
87
+ const references = [];
88
+ // Match <<embed:0001>> pattern
89
+ const embed_regex = /<<embed:(\d+)>>/g;
90
+ let match;
91
+ while ((match = embed_regex.exec(note_text)) !== null) {
92
+ references.push({ type: 'embed', file_no: match[1] });
93
+ }
94
+ // Match <<attach:0001>> pattern
95
+ const attach_regex = /<<attach:(\d+)>>/g;
96
+ while ((match = attach_regex.exec(note_text)) !== null) {
97
+ references.push({ type: 'attachment', file_no: match[1] });
98
+ }
99
+ return references;
100
+ }
101
+ /**
102
+ * Create file reference syntax for inserting into note text
103
+ */
104
+ export function create_file_reference(file_no, embed_type) {
105
+ return embed_type === 'embed' ? `<<embed:${file_no}>>` : `<<attach:${file_no}>>`;
106
+ }
107
+ /**
108
+ * Validate file before upload
109
+ */
110
+ export function validate_file(file, options) {
111
+ // Check file size
112
+ const max_bytes = options.max_size_mb * 1024 * 1024;
113
+ if (file.size > max_bytes) {
114
+ return {
115
+ valid: false,
116
+ error: `File size (${format_file_size(file.size)}) exceeds maximum allowed (${options.max_size_mb} MB)`,
117
+ };
118
+ }
119
+ // Check file type
120
+ if (!is_allowed_file_type(file.name, options.allowed_types)) {
121
+ return {
122
+ valid: false,
123
+ error: `File type not allowed. Allowed types: ${options.allowed_types.join(', ')}`,
124
+ };
125
+ }
126
+ return { valid: true };
127
+ }
128
+ //# sourceMappingURL=file_utils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"file_utils.js","sourceRoot":"","sources":["../../src/utils/file_utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility functions for hazo_notes
3
+ */
4
+ export { cn } from './cn.js';
5
+ 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 './file_utils.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,GACd,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Utility functions for hazo_notes
3
+ */
4
+ export { cn } from './cn.js';
5
+ 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 './file_utils.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/utils/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,EAAE,EAAE,MAAM,SAAS,CAAC;AAC7B,OAAO,EACL,gBAAgB,EAChB,cAAc,EACd,aAAa,EACb,oBAAoB,EACpB,aAAa,EACb,gBAAgB,EAChB,qBAAqB,EACrB,qBAAqB,EACrB,aAAa,GACd,MAAM,iBAAiB,CAAC"}
@@ -0,0 +1,77 @@
1
+ -- Migration: Create hazo_notes table
2
+ -- Version: 001
3
+ -- Description: Initial table creation for notes system with JSONB storage
4
+ -- Compatible with: PostgreSQL 13+, SQLite 3.38+ (with JSON1 extension)
5
+
6
+ -- ============================================================================
7
+ -- PostgreSQL Version
8
+ -- ============================================================================
9
+
10
+ -- Create the hazo_notes table
11
+ CREATE TABLE IF NOT EXISTS hazo_notes (
12
+ id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
13
+ ref_id UUID NOT NULL,
14
+ note JSONB NOT NULL DEFAULT '[]'::jsonb,
15
+ created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
16
+ changed_at TIMESTAMPTZ,
17
+ note_count INTEGER NOT NULL DEFAULT 0
18
+ );
19
+
20
+ -- Create index on ref_id for efficient lookups
21
+ CREATE INDEX IF NOT EXISTS idx_hazo_notes_ref_id ON hazo_notes(ref_id);
22
+
23
+ -- Add comments for documentation
24
+ COMMENT ON TABLE hazo_notes IS 'Stores notes linked to any entity via ref_id. Notes are stored as JSONB array with user attribution and optional file attachments.';
25
+ COMMENT ON COLUMN hazo_notes.id IS 'Primary key UUID';
26
+ COMMENT ON COLUMN hazo_notes.ref_id IS 'UUID reference to the parent entity (e.g., form field, document, task)';
27
+ COMMENT ON COLUMN hazo_notes.note IS 'JSONB array of note entries: [{userid, created_at, note_text, note_files}]';
28
+ COMMENT ON COLUMN hazo_notes.created_at IS 'Timestamp when the notes row was first created';
29
+ COMMENT ON COLUMN hazo_notes.changed_at IS 'Timestamp of the last modification to the notes';
30
+ COMMENT ON COLUMN hazo_notes.note_count IS 'Denormalized count of notes for quick access without parsing JSONB';
31
+
32
+ -- ============================================================================
33
+ -- SQLite Version (for test-app)
34
+ -- Run this in SQLite instead of the PostgreSQL version above
35
+ -- ============================================================================
36
+
37
+ /*
38
+ -- SQLite version (uncomment to use):
39
+
40
+ CREATE TABLE IF NOT EXISTS hazo_notes (
41
+ id TEXT PRIMARY KEY,
42
+ ref_id TEXT NOT NULL,
43
+ note TEXT NOT NULL DEFAULT '[]',
44
+ created_at TEXT NOT NULL DEFAULT (datetime('now')),
45
+ changed_at TEXT,
46
+ note_count INTEGER NOT NULL DEFAULT 0
47
+ );
48
+
49
+ CREATE INDEX IF NOT EXISTS idx_hazo_notes_ref_id ON hazo_notes(ref_id);
50
+ */
51
+
52
+ -- ============================================================================
53
+ -- Note Entry JSONB Schema Reference
54
+ -- ============================================================================
55
+ /*
56
+ Each element in the `note` JSONB array follows this structure:
57
+
58
+ {
59
+ "userid": "550e8400-e29b-41d4-a716-446655440000",
60
+ "created_at": "2026-01-07T12:30:00.000Z",
61
+ "note_text": "This is the note content. See attachment: <<attach:0001>>",
62
+ "note_files": [
63
+ {
64
+ "file_no": "0001",
65
+ "embed_type": "attachment",
66
+ "filename": "document.pdf",
67
+ "filedata": "base64_encoded_content_or_file_path",
68
+ "mime_type": "application/pdf",
69
+ "file_size": 12345
70
+ }
71
+ ]
72
+ }
73
+
74
+ File references in note_text:
75
+ - <<embed:0001>> - Renders file inline (images displayed directly)
76
+ - <<attach:0001>> - Renders as downloadable link
77
+ */
package/package.json ADDED
@@ -0,0 +1,119 @@
1
+ {
2
+ "name": "hazo_notes",
3
+ "version": "1.0.0",
4
+ "description": "Database-backed notes system with file attachment support for the hazo ecosystem",
5
+ "type": "module",
6
+ "main": "./dist/index.client.js",
7
+ "module": "./dist/index.client.js",
8
+ "types": "./dist/index.client.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "import": "./dist/index.client.js",
12
+ "types": "./dist/index.client.d.ts"
13
+ },
14
+ "./api": {
15
+ "import": "./dist/api/index.js",
16
+ "types": "./dist/api/index.d.ts"
17
+ },
18
+ "./hooks": {
19
+ "import": "./dist/hooks/index.js",
20
+ "types": "./dist/hooks/index.d.ts"
21
+ },
22
+ "./components": {
23
+ "import": "./dist/components/index.js",
24
+ "types": "./dist/components/index.d.ts"
25
+ },
26
+ "./lib": {
27
+ "import": "./dist/lib/index.js",
28
+ "types": "./dist/lib/index.d.ts"
29
+ },
30
+ "./types": {
31
+ "import": "./dist/types/index.js",
32
+ "types": "./dist/types/index.d.ts"
33
+ }
34
+ },
35
+ "files": [
36
+ "dist",
37
+ "templates",
38
+ "migrations",
39
+ "README.md",
40
+ "SETUP_CHECKLIST.md"
41
+ ],
42
+ "workspaces": [
43
+ "test-app"
44
+ ],
45
+ "scripts": {
46
+ "build": "tsc -p tsconfig.build.json",
47
+ "dev:package": "tsc -p tsconfig.build.json --watch",
48
+ "dev:test-app": "npm run build && cd test-app && npm run dev",
49
+ "build:test-app": "npm run build && cd test-app && npm run build",
50
+ "clean": "rm -rf dist",
51
+ "prebuild": "npm run clean",
52
+ "prepublishOnly": "npm run build",
53
+ "test": "echo \"Error: no test specified\" && exit 1"
54
+ },
55
+ "repository": {
56
+ "type": "git",
57
+ "url": "git+https://github.com/pub12/hazo_notes.git"
58
+ },
59
+ "keywords": [
60
+ "notes",
61
+ "hazo",
62
+ "react",
63
+ "typescript",
64
+ "nextjs",
65
+ "file-attachments"
66
+ ],
67
+ "author": "Pubs Abayasiri",
68
+ "license": "MIT",
69
+ "bugs": {
70
+ "url": "https://github.com/pub12/hazo_notes/issues"
71
+ },
72
+ "homepage": "https://github.com/pub12/hazo_notes#readme",
73
+ "dependencies": {
74
+ "clsx": "^2.1.1",
75
+ "hazo_config": "^1.0.0",
76
+ "server-only": "^0.0.1",
77
+ "tailwind-merge": "^2.5.4"
78
+ },
79
+ "devDependencies": {
80
+ "@types/node": "^20.10.0",
81
+ "@types/react": "^18.2.0",
82
+ "@types/react-dom": "^18.2.0",
83
+ "hazo_logs": "^1.0.0",
84
+ "next": "^14.2.33",
85
+ "typescript": "^5.3.0"
86
+ },
87
+ "peerDependencies": {
88
+ "@radix-ui/react-dialog": "^1.0.0",
89
+ "@radix-ui/react-popover": "^1.0.0",
90
+ "hazo_auth": "^5.0.0",
91
+ "hazo_connect": "^2.3.1",
92
+ "hazo_logs": "^1.0.0",
93
+ "next": ">=14.0.0",
94
+ "react": "^18.0.0",
95
+ "react-dom": "^18.0.0",
96
+ "react-icons": "^5.0.0",
97
+ "tailwindcss": ">=3.0.0"
98
+ },
99
+ "peerDependenciesMeta": {
100
+ "hazo_auth": {
101
+ "optional": true
102
+ },
103
+ "hazo_connect": {
104
+ "optional": true
105
+ },
106
+ "hazo_logs": {
107
+ "optional": true
108
+ },
109
+ "@radix-ui/react-popover": {
110
+ "optional": true
111
+ },
112
+ "@radix-ui/react-dialog": {
113
+ "optional": true
114
+ },
115
+ "react-icons": {
116
+ "optional": true
117
+ }
118
+ }
119
+ }
@@ -0,0 +1,43 @@
1
+ # hazo_notes Configuration Template
2
+ # Copy this file to your application's config/ directory
3
+ # Path: config/hazo_notes_config.ini
4
+
5
+ [ui]
6
+ # Background color for notes panel (Tailwind CSS class)
7
+ # Examples: bg-yellow-100, bg-blue-50, bg-gray-100
8
+ background_color = bg-yellow-100
9
+
10
+ # Panel presentation style
11
+ # Options: popover | slide_panel
12
+ panel_style = popover
13
+
14
+ # Save behavior
15
+ # Options:
16
+ # explicit - User clicks Save/Cancel buttons
17
+ # auto - Note saved automatically when panel closes or on blur
18
+ save_mode = explicit
19
+
20
+ [storage]
21
+ # File storage mode
22
+ # Options:
23
+ # jsonb - Store files as Base64 in database (simpler, good for small files)
24
+ # filesystem - Store files on server filesystem (better for large files)
25
+ file_storage_mode = jsonb
26
+
27
+ # Path for filesystem storage (only used when file_storage_mode = filesystem)
28
+ # Must be an absolute path or relative to your application root
29
+ file_storage_path = /uploads/notes
30
+
31
+ [files]
32
+ # Maximum file size in MB
33
+ max_file_size_mb = 10
34
+
35
+ # Allowed file types (comma-separated extensions, no dots)
36
+ allowed_file_types = pdf,png,jpg,jpeg,gif,doc,docx
37
+
38
+ # Maximum files per single note entry
39
+ max_files_per_note = 5
40
+
41
+ [logging]
42
+ # Log file path (relative to application root)
43
+ logfile = logs/hazo_notes.log