hazo_ihelp 2.0.9 → 2.1.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 (79) hide show
  1. package/SETUP_CHECKLIST.md +131 -0
  2. package/config/hazo_ihelp_config.ini.sample +41 -8
  3. package/db_setup_postgres.sql +52 -0
  4. package/db_setup_sqlite.sql +25 -0
  5. package/dist/api/create_config_handler.d.ts +2 -0
  6. package/dist/api/create_config_handler.d.ts.map +1 -1
  7. package/dist/api/create_config_handler.js +117 -81
  8. package/dist/api/create_config_handler.js.map +1 -1
  9. package/dist/api/create_ihelp_handler.d.ts +4 -12
  10. package/dist/api/create_ihelp_handler.d.ts.map +1 -1
  11. package/dist/api/create_ihelp_handler.js +251 -226
  12. package/dist/api/create_ihelp_handler.js.map +1 -1
  13. package/dist/api/image_upload_handler.d.ts.map +1 -1
  14. package/dist/api/image_upload_handler.js +114 -80
  15. package/dist/api/image_upload_handler.js.map +1 -1
  16. package/dist/components/editor/editor_collapsible_section.js +1 -1
  17. package/dist/components/editor/editor_collapsible_section.js.map +1 -1
  18. package/dist/components/editor/editor_form.js +1 -1
  19. package/dist/components/editor/editor_form.js.map +1 -1
  20. package/dist/components/editor/editor_topic_list_item.js +1 -1
  21. package/dist/components/editor/editor_topic_list_item.js.map +1 -1
  22. package/dist/components/hover_help_icon.d.ts +39 -0
  23. package/dist/components/hover_help_icon.d.ts.map +1 -0
  24. package/dist/components/hover_help_icon.js +29 -0
  25. package/dist/components/hover_help_icon.js.map +1 -0
  26. package/dist/components/ihelp_detail_panel.js +1 -1
  27. package/dist/components/ihelp_detail_panel.js.map +1 -1
  28. package/dist/components/ihelp_editor.js +1 -1
  29. package/dist/components/ihelp_editor.js.map +1 -1
  30. package/dist/components/ihelp_icon.js +1 -1
  31. package/dist/components/ihelp_icon.js.map +1 -1
  32. package/dist/components/ihelp_provider.d.ts.map +1 -1
  33. package/dist/components/ihelp_provider.js +6 -1
  34. package/dist/components/ihelp_provider.js.map +1 -1
  35. package/dist/components/ihelp_rich_editor.js +1 -1
  36. package/dist/components/ihelp_rich_editor.js.map +1 -1
  37. package/dist/components/ihelp_search_dialog.js +1 -1
  38. package/dist/components/ihelp_search_dialog.js.map +1 -1
  39. package/dist/components/index.d.ts +1 -0
  40. package/dist/components/index.d.ts.map +1 -1
  41. package/dist/components/index.js +1 -0
  42. package/dist/components/index.js.map +1 -1
  43. package/dist/components/ui/badge.js +1 -1
  44. package/dist/components/ui/badge.js.map +1 -1
  45. package/dist/components/ui/button.js +1 -1
  46. package/dist/components/ui/button.js.map +1 -1
  47. package/dist/components/ui/dialog.js +1 -1
  48. package/dist/components/ui/dialog.js.map +1 -1
  49. package/dist/components/ui/input.js +1 -1
  50. package/dist/components/ui/input.js.map +1 -1
  51. package/dist/components/ui/label.js +1 -1
  52. package/dist/components/ui/label.js.map +1 -1
  53. package/dist/components/ui/popover.js +1 -1
  54. package/dist/components/ui/popover.js.map +1 -1
  55. package/dist/components/ui/select.js +1 -1
  56. package/dist/components/ui/select.js.map +1 -1
  57. package/dist/components/ui/switch.js +1 -1
  58. package/dist/components/ui/switch.js.map +1 -1
  59. package/dist/components/ui/textarea.js +1 -1
  60. package/dist/components/ui/textarea.js.map +1 -1
  61. package/dist/index.client.d.ts +1 -1
  62. package/dist/index.client.d.ts.map +1 -1
  63. package/dist/index.client.js +1 -1
  64. package/dist/index.client.js.map +1 -1
  65. package/dist/lib/config/hazo_ihelp_config.d.ts +106 -0
  66. package/dist/lib/config/hazo_ihelp_config.d.ts.map +1 -0
  67. package/dist/lib/config/hazo_ihelp_config.js +66 -0
  68. package/dist/lib/config/hazo_ihelp_config.js.map +1 -0
  69. package/dist/utils/logger.d.ts +25 -0
  70. package/dist/utils/logger.d.ts.map +1 -0
  71. package/dist/utils/logger.js +42 -0
  72. package/dist/utils/logger.js.map +1 -0
  73. package/package.json +65 -22
  74. package/config/hazo_ihelp_config.ini +0 -9
  75. package/dist/utils/cn.d.ts +0 -3
  76. package/dist/utils/cn.d.ts.map +0 -1
  77. package/dist/utils/cn.js +0 -6
  78. package/dist/utils/cn.js.map +0 -1
  79. package/migrations/001_create_ihelp_tables.sql +0 -109
@@ -0,0 +1,25 @@
1
+ /**
2
+ * Logger Utility for hazo_ihelp
3
+ *
4
+ * Default behavior: delegates to hazo_core's createLogger('hazo_ihelp'), which
5
+ * auto-injects correlationId, env, and writes structured JSON via hazo_logs.
6
+ * Consumers can still override with set_logger() — useful for browser-only
7
+ * loggers or app-specific instrumentation.
8
+ */
9
+ export interface Logger {
10
+ info: (message: string, data?: Record<string, unknown>) => void;
11
+ debug: (message: string, data?: Record<string, unknown>) => void;
12
+ warn: (message: string, data?: Record<string, unknown>) => void;
13
+ error: (message: string, data?: Record<string, unknown>) => void;
14
+ }
15
+ /**
16
+ * Set the logger instance to use throughout hazo_ihelp.
17
+ * Pass `undefined` to reset to the hazo_core default.
18
+ */
19
+ export declare function set_logger(logger: Logger | undefined): void;
20
+ /**
21
+ * Get the current logger instance — defaults to hazo_core's createLogger
22
+ * on first access if no consumer override has been set.
23
+ */
24
+ export declare function get_logger(): Logger;
25
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,MAAM,WAAW,MAAM;IACrB,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IACjE,IAAI,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;IAChE,KAAK,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,IAAI,CAAC;CAClE;AAmBD;;;GAGG;AACH,wBAAgB,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,CAE3D;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAKnC"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Logger Utility for hazo_ihelp
3
+ *
4
+ * Default behavior: delegates to hazo_core's createLogger('hazo_ihelp'), which
5
+ * auto-injects correlationId, env, and writes structured JSON via hazo_logs.
6
+ * Consumers can still override with set_logger() — useful for browser-only
7
+ * loggers or app-specific instrumentation.
8
+ */
9
+ import { createLogger } from 'hazo_core';
10
+ const console_logger = {
11
+ info: (m, d) => (d ? console.log(`[hazo_ihelp] ${m}`, d) : console.log(`[hazo_ihelp] ${m}`)),
12
+ debug: (m, d) => (d ? console.debug(`[hazo_ihelp] ${m}`, d) : console.debug(`[hazo_ihelp] ${m}`)),
13
+ warn: (m, d) => (d ? console.warn(`[hazo_ihelp] ${m}`, d) : console.warn(`[hazo_ihelp] ${m}`)),
14
+ error: (m, d) => (d ? console.error(`[hazo_ihelp] ${m}`, d) : console.error(`[hazo_ihelp] ${m}`)),
15
+ };
16
+ function build_default_logger() {
17
+ try {
18
+ return createLogger('hazo_ihelp');
19
+ }
20
+ catch {
21
+ return console_logger;
22
+ }
23
+ }
24
+ let current_logger = null;
25
+ /**
26
+ * Set the logger instance to use throughout hazo_ihelp.
27
+ * Pass `undefined` to reset to the hazo_core default.
28
+ */
29
+ export function set_logger(logger) {
30
+ current_logger = logger ?? null;
31
+ }
32
+ /**
33
+ * Get the current logger instance — defaults to hazo_core's createLogger
34
+ * on first access if no consumer override has been set.
35
+ */
36
+ export function get_logger() {
37
+ if (!current_logger) {
38
+ current_logger = build_default_logger();
39
+ }
40
+ return current_logger;
41
+ }
42
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AASzC,MAAM,cAAc,GAAW;IAC7B,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC5F,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IACjG,IAAI,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;IAC9F,KAAK,EAAE,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,gBAAgB,CAAC,EAAE,CAAC,CAAC;CAClG,CAAC;AAEF,SAAS,oBAAoB;IAC3B,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,YAAY,CAAsB,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,cAAc,CAAC;IACxB,CAAC;AACH,CAAC;AAED,IAAI,cAAc,GAAkB,IAAI,CAAC;AAEzC;;;GAGG;AACH,MAAM,UAAU,UAAU,CAAC,MAA0B;IACnD,cAAc,GAAG,MAAM,IAAI,IAAI,CAAC;AAClC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,UAAU;IACxB,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,cAAc,GAAG,oBAAoB,EAAE,CAAC;IAC1C,CAAC;IACD,OAAO,cAAc,CAAC;AACxB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_ihelp",
3
- "version": "2.0.9",
3
+ "version": "2.1.0",
4
4
  "type": "module",
5
5
  "main": "./dist/index.client.js",
6
6
  "module": "./dist/index.client.js",
@@ -29,9 +29,11 @@
29
29
  },
30
30
  "files": [
31
31
  "dist",
32
- "migrations",
33
- "config",
34
- "README.md"
32
+ "config/hazo_ihelp_config.ini.sample",
33
+ "db_setup_postgres.sql",
34
+ "db_setup_sqlite.sql",
35
+ "README.md",
36
+ "SETUP_CHECKLIST.md"
35
37
  ],
36
38
  "scripts": {
37
39
  "build": "tsc -p tsconfig.build.json",
@@ -69,31 +71,61 @@
69
71
  "cmdk": "^1.1.1",
70
72
  "date-fns": "^4.1.0",
71
73
  "fuse.js": "^7.0.0",
72
- "hazo_auth": "^5.1.30",
73
- "hazo_chat": "^5.2.2",
74
- "hazo_config": "^2.1.0",
75
- "hazo_files": "^1.4.4",
76
- "hazo_llm_api": "^1.2.10",
77
- "hazo_logs": "^1.0.10",
78
- "hazo_notes": "^1.1.5",
79
- "lucide-react": "^0.344.0",
74
+ "lucide-react": "^0.553.0",
80
75
  "react-day-picker": "^9.14.0",
81
76
  "react-icons": "^5.6.0",
82
77
  "react-resizable-panels": "^4.7.6",
83
78
  "sonner": "^2.0.7",
84
- "tailwind-merge": "^2.5.4"
79
+ "tailwind-merge": "^3.5.0",
80
+ "zod": "^3.23.8"
85
81
  },
86
82
  "peerDependencies": {
87
- "hazo_connect": "^2.3.1",
88
- "next": ">=14.0.0",
89
- "react": "^18||^19",
90
- "react-dom": "^18||^19",
91
- "tailwindcss": ">=3.0.0"
83
+ "hazo_auth": "^9.0.0",
84
+ "hazo_chat": "^6.0.0",
85
+ "hazo_config": "^2.1.5",
86
+ "hazo_connect": "^3.0.0",
87
+ "hazo_core": "^1.0.0",
88
+ "hazo_files": "^3.0.0",
89
+ "hazo_llm_api": "^2.0.0",
90
+ "hazo_logs": "^2.0.0",
91
+ "hazo_notes": "^2.0.0",
92
+ "hazo_ui": "^3.1.0",
93
+ "next": "^14.0.0 || ^16.0.0",
94
+ "react": "^18.0.0 || ^19.0.0",
95
+ "react-dom": "^18.0.0 || ^19.0.0",
96
+ "tailwindcss": "^4.2.4"
92
97
  },
93
98
  "peerDependenciesMeta": {
99
+ "hazo_auth": {
100
+ "optional": true
101
+ },
102
+ "hazo_chat": {
103
+ "optional": true
104
+ },
105
+ "hazo_config": {
106
+ "optional": true
107
+ },
94
108
  "hazo_connect": {
95
109
  "optional": true
96
110
  },
111
+ "hazo_core": {
112
+ "optional": false
113
+ },
114
+ "hazo_files": {
115
+ "optional": true
116
+ },
117
+ "hazo_llm_api": {
118
+ "optional": true
119
+ },
120
+ "hazo_logs": {
121
+ "optional": true
122
+ },
123
+ "hazo_notes": {
124
+ "optional": true
125
+ },
126
+ "hazo_ui": {
127
+ "optional": false
128
+ },
97
129
  "next": {
98
130
  "optional": true
99
131
  },
@@ -102,10 +134,21 @@
102
134
  }
103
135
  },
104
136
  "devDependencies": {
105
- "@types/node": "^20.10.0",
106
- "@types/react": "^18.2.0",
107
- "@types/react-dom": "^18.2.0",
108
- "typescript": "^5.3.0"
137
+ "@types/node": "^20.14.10",
138
+ "@types/react": "^18.3.3",
139
+ "@types/react-dom": "^18.3.0",
140
+ "hazo_auth": "^9.0.0",
141
+ "hazo_chat": "^6.0.0",
142
+ "hazo_config": "^2.1.6",
143
+ "hazo_connect": "^3.0.0",
144
+ "hazo_core": "^1.0.0",
145
+ "hazo_files": "^3.0.0",
146
+ "hazo_llm_api": "^2.0.0",
147
+ "hazo_logs": "^2.0.1",
148
+ "hazo_notes": "^2.0.0",
149
+ "hazo_ui": "^3.1.0",
150
+ "next": "^16.0.10",
151
+ "typescript": "^5.7.2"
109
152
  },
110
153
  "author": "Pubs Abayasiri",
111
154
  "license": "MIT",
@@ -1,9 +0,0 @@
1
- [image_upload]
2
- max_file_size_mb = 5
3
- allowed_types = image/jpeg, image/png, image/gif, image/webp, image/svg+xml, image/avif
4
- upload_dir = test-app/public/ihelp/images
5
- upload_url_prefix = /ihelp/images
6
- resize_enabled = true
7
- resize_max_width = 1200
8
- resize_max_height = 1200
9
- resize_quality = 80
@@ -1,3 +0,0 @@
1
- import { type ClassValue } from 'clsx';
2
- export declare function cn(...inputs: ClassValue[]): string;
3
- //# sourceMappingURL=cn.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cn.d.ts","sourceRoot":"","sources":["../../src/utils/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,KAAK,UAAU,EAAE,MAAM,MAAM,CAAC;AAG7C,wBAAgB,EAAE,CAAC,GAAG,MAAM,EAAE,UAAU,EAAE,UAEzC"}
package/dist/utils/cn.js DELETED
@@ -1,6 +0,0 @@
1
- import { clsx } from 'clsx';
2
- import { twMerge } from 'tailwind-merge';
3
- export function cn(...inputs) {
4
- return twMerge(clsx(inputs));
5
- }
6
- //# sourceMappingURL=cn.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"cn.js","sourceRoot":"","sources":["../../src/utils/cn.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAmB,MAAM,MAAM,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAEzC,MAAM,UAAU,EAAE,CAAC,GAAG,MAAoB;IACxC,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;AAC/B,CAAC"}
@@ -1,109 +0,0 @@
1
- -- hazo_ihelp database schema
2
- -- Simplified 2-table design: topics with embedded tags/contexts as JSON
3
- --
4
- -- ═══════════════════════════════════════════════════════════════════════════════
5
- -- SQLite Version
6
- -- ═══════════════════════════════════════════════════════════════════════════════
7
- -- SQLite stores UUIDs as TEXT and JSON as TEXT. No native UUID or JSONB type.
8
- --
9
- -- CREATE TABLE IF NOT EXISTS hazo_ihelp_topics (
10
- -- id TEXT PRIMARY KEY, -- UUID as text
11
- -- parent_id TEXT, -- UUID ref → hazo_ihelp_topics(id)
12
- -- scope_id TEXT, -- UUID, NULL = global
13
- -- category TEXT NOT NULL DEFAULT 'General',
14
- -- title TEXT NOT NULL,
15
- -- description TEXT,
16
- -- content TEXT, -- Rich HTML from Tiptap editor
17
- -- icon TEXT, -- Lucide icon name
18
- -- sort_order INTEGER NOT NULL DEFAULT 0,
19
- -- is_published INTEGER NOT NULL DEFAULT 1, -- SQLite boolean (0/1)
20
- -- tags TEXT NOT NULL DEFAULT '[]', -- JSON array: [{label, variant, icon}]
21
- -- contexts TEXT NOT NULL DEFAULT '[]', -- JSON array: [{key, priority}]
22
- -- created_at TEXT NOT NULL DEFAULT (datetime('now')),
23
- -- changed_at TEXT,
24
- -- FOREIGN KEY (parent_id) REFERENCES hazo_ihelp_topics(id) ON DELETE SET NULL
25
- -- );
26
- --
27
- -- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_scope ON hazo_ihelp_topics(scope_id);
28
- -- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_parent ON hazo_ihelp_topics(parent_id);
29
- --
30
- -- CREATE TABLE IF NOT EXISTS hazo_config (
31
- -- id TEXT PRIMARY KEY, -- UUID as text
32
- -- config_key TEXT NOT NULL,
33
- -- config_value TEXT NOT NULL, -- JSON string
34
- -- scope_id TEXT, -- UUID, NULL = global
35
- -- created_at TEXT NOT NULL DEFAULT (datetime('now')),
36
- -- changed_at TEXT,
37
- -- UNIQUE(config_key, scope_id)
38
- -- );
39
- --
40
- -- CREATE INDEX IF NOT EXISTS idx_hazo_config_key ON hazo_config(config_key);
41
- --
42
- -- ═══════════════════════════════════════════════════════════════════════════════
43
- -- PostgreSQL Version
44
- -- ═══════════════════════════════════════════════════════════════════════════════
45
- -- PostgreSQL uses native UUID, JSONB, BOOLEAN, and TIMESTAMPTZ types.
46
- -- Requires: CREATE EXTENSION IF NOT EXISTS "pgcrypto"; (for gen_random_uuid)
47
-
48
- CREATE TABLE IF NOT EXISTS hazo_ihelp_topics (
49
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
50
- parent_id UUID REFERENCES hazo_ihelp_topics(id) ON DELETE SET NULL,
51
- scope_id UUID, -- NULL = global, UUID = org-specific
52
- category TEXT NOT NULL DEFAULT 'General',
53
- title TEXT NOT NULL,
54
- description TEXT, -- Short summary for search cards
55
- content TEXT, -- Rich HTML content from Tiptap editor
56
- icon TEXT, -- Lucide icon name
57
- sort_order INTEGER NOT NULL DEFAULT 0,
58
- is_published BOOLEAN NOT NULL DEFAULT TRUE,
59
- tags JSONB NOT NULL DEFAULT '[]', -- [{label, variant, icon}]
60
- contexts JSONB NOT NULL DEFAULT '[]', -- [{key, priority}]
61
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
62
- changed_at TIMESTAMPTZ
63
- );
64
-
65
- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_scope ON hazo_ihelp_topics(scope_id);
66
- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_parent ON hazo_ihelp_topics(parent_id);
67
- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_tags ON hazo_ihelp_topics USING GIN (tags);
68
- CREATE INDEX IF NOT EXISTS idx_hazo_ihelp_topics_contexts ON hazo_ihelp_topics USING GIN (contexts);
69
-
70
- CREATE TABLE IF NOT EXISTS hazo_config (
71
- id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
72
- config_key TEXT NOT NULL,
73
- config_value TEXT NOT NULL, -- JSON string
74
- scope_id UUID, -- NULL = global, UUID = org-specific
75
- created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
76
- changed_at TIMESTAMPTZ,
77
- UNIQUE(config_key, scope_id)
78
- );
79
-
80
- CREATE INDEX IF NOT EXISTS idx_hazo_config_key ON hazo_config(config_key);
81
-
82
- -- ═══════════════════════════════════════════════════════════════════════════════
83
- -- JSON Column Shapes
84
- -- ═══════════════════════════════════════════════════════════════════════════════
85
- --
86
- -- tags: [
87
- -- { "label": "Receipt Required", "variant": "warning", "icon": "AlertTriangle" },
88
- -- { "label": "Pre-filled", "variant": "success", "icon": "Check" }
89
- -- ]
90
- --
91
- -- contexts: [
92
- -- { "key": "deductions.work_from_home", "priority": 0 },
93
- -- { "key": "onboarding.step3", "priority": 1 }
94
- -- ]
95
- --
96
- -- ═══════════════════════════════════════════════════════════════════════════════
97
- -- PostgreSQL Context Key Query Examples
98
- -- ═══════════════════════════════════════════════════════════════════════════════
99
- --
100
- -- Find topics mapped to a context key:
101
- -- SELECT * FROM hazo_ihelp_topics
102
- -- WHERE contexts @> '[{"key": "deductions.work_from_home"}]'
103
- -- ORDER BY (SELECT MIN((ctx->>'priority')::int)
104
- -- FROM jsonb_array_elements(contexts) ctx
105
- -- WHERE ctx->>'key' = 'deductions.work_from_home');
106
- --
107
- -- Find topics with a specific tag label:
108
- -- SELECT * FROM hazo_ihelp_topics
109
- -- WHERE tags @> '[{"label": "Pre-filled"}]';