hazo_config 2.4.3 → 2.5.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/CHANGE_LOG.md CHANGED
@@ -1,5 +1,31 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.5.0 — 2026-09-06
4
+
5
+ ### Added
6
+
7
+ Ecosystem-first promotion of taxclientdocs' two-tier (global default +
8
+ scope-level override) config helpers, previously duplicated in
9
+ `lib/config/{two-tier,clone-to-override,override-count}.ts`.
10
+
11
+ - `mergeTwoTier<T>(opts): T[]` (`src/lib/two_tier.ts`, exported from the main
12
+ entry and `hazo_config/lib`) — pure, zero-dep merge of a `globals[]` +
13
+ `overrides[]` row pair (each shaped `{ id, scope_id, enabled, ... }`) into
14
+ the effective list. Override wins by key (via `keyFn`); an `additive` mode
15
+ returns the union of both tiers instead. `TwoTierRow`/`MergeOptions` types
16
+ exported alongside. No database dependency — callers fetch `globals`/
17
+ `overrides` however they like, matching the existing `AppConfig`
18
+ callback-persistence pattern.
19
+ - New `hazo_config/server-data` entry point: `cloneToOverride(table,
20
+ globalRowId, orgScopeId)` / `CloneToOverrideError` and
21
+ `getOverrideCount(table, keyColumn, keyValue)` (`src/lib/clone_to_override.ts`,
22
+ `src/lib/override_count.ts`) — hazo_connect-backed CRUD helpers for cloning
23
+ a global row into a scope-level override and counting existing overrides
24
+ for a key. Kept in a separate entry point (not `/server` or `/lib`) so a
25
+ consumer of the fs-based `HazoConfig` or the pure `mergeTwoTier` is never
26
+ required to install `hazo_connect`. `hazo_connect` added as an **optional**
27
+ peer dependency (`^4.1.0`) accordingly.
28
+
3
29
  ## 2.4.2 — 2026-08-04
4
30
 
5
31
  ### Changed
@@ -0,0 +1,26 @@
1
+ /**
2
+ * Purpose: Clone a global (platform-default) two-tier config row into a
3
+ * scope-level override row.
4
+ *
5
+ * hazo_connect is an optional peer dependency here (see `hazo_config/server-data`,
6
+ * the entry point that re-exports this). It is loaded via dynamic import()
7
+ * with bundler-ignore hints, matching `config_loader.ts`'s optional
8
+ * `hazo_core/errors` integration: `hazo_connect/server` and
9
+ * `hazo_connect/nextjs/setup` are ESM-only subpath exports, and this
10
+ * package's build uses moduleResolution:"node" (predates subpath-exports
11
+ * resolution), so TS can't resolve them statically even though they load
12
+ * fine at runtime.
13
+ */
14
+ export declare class CloneToOverrideError extends Error {
15
+ constructor(message: string);
16
+ }
17
+ /**
18
+ * Clone the global row `globalRowId` from `table` into a new row scoped to
19
+ * `orgScopeId`. Strips `id`/`created_at`/`updated_at` and stamps
20
+ * `cloned_from_at` on the new row.
21
+ *
22
+ * @throws {CloneToOverrideError} when the source row does not exist, is not
23
+ * itself a global row (`scope_id` must be `null`), or the insert returns no row.
24
+ */
25
+ export declare function cloneToOverride(table: string, globalRowId: string, orgScopeId: string): Promise<Record<string, unknown>>;
26
+ //# sourceMappingURL=clone_to_override.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"clone_to_override.d.ts","sourceRoot":"","sources":["../../src/lib/clone_to_override.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AA0BH,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B;AAED;;;;;;;GAOG;AACH,wBAAsB,eAAe,CACnC,KAAK,EAAE,MAAM,EACb,WAAW,EAAE,MAAM,EACnB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAoBlC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Purpose: Clone a global (platform-default) two-tier config row into a
3
+ * scope-level override row.
4
+ *
5
+ * hazo_connect is an optional peer dependency here (see `hazo_config/server-data`,
6
+ * the entry point that re-exports this). It is loaded via dynamic import()
7
+ * with bundler-ignore hints, matching `config_loader.ts`'s optional
8
+ * `hazo_core/errors` integration: `hazo_connect/server` and
9
+ * `hazo_connect/nextjs/setup` are ESM-only subpath exports, and this
10
+ * package's build uses moduleResolution:"node" (predates subpath-exports
11
+ * resolution), so TS can't resolve them statically even though they load
12
+ * fine at runtime.
13
+ */
14
+ async function loadCreateCrudService() {
15
+ // @ts-ignore — hazo_connect/server is a valid subpath export; moduleResolution:"node"
16
+ // predates subpath exports so TS can't resolve it statically, but it loads correctly at runtime.
17
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
18
+ const mod = (await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ 'hazo_connect/server'));
19
+ return mod.createCrudService;
20
+ }
21
+ async function loadGetHazoConnectSingleton() {
22
+ // @ts-ignore — hazo_connect/nextjs/setup is a valid subpath export; see loadCreateCrudService above.
23
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
24
+ const mod = (await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ 'hazo_connect/nextjs/setup'));
25
+ return mod.getHazoConnectSingleton;
26
+ }
27
+ export class CloneToOverrideError extends Error {
28
+ constructor(message) {
29
+ super(message);
30
+ this.name = 'CloneToOverrideError';
31
+ }
32
+ }
33
+ /**
34
+ * Clone the global row `globalRowId` from `table` into a new row scoped to
35
+ * `orgScopeId`. Strips `id`/`created_at`/`updated_at` and stamps
36
+ * `cloned_from_at` on the new row.
37
+ *
38
+ * @throws {CloneToOverrideError} when the source row does not exist, is not
39
+ * itself a global row (`scope_id` must be `null`), or the insert returns no row.
40
+ */
41
+ export async function cloneToOverride(table, globalRowId, orgScopeId) {
42
+ const createCrudService = await loadCreateCrudService();
43
+ const getHazoConnectSingleton = await loadGetHazoConnectSingleton();
44
+ const svc = createCrudService(getHazoConnectSingleton(), table);
45
+ const row = await svc.findById(globalRowId);
46
+ if (!row)
47
+ throw new CloneToOverrideError('Global row not found');
48
+ if (row.scope_id !== null)
49
+ throw new CloneToOverrideError('Source row is not a global (scope_id must be null)');
50
+ // Strip the id and timestamps; set new scope
51
+ const { id: _omit, created_at: _ca, updated_at: _ua, ...rest } = row;
52
+ const inserted = await svc.insert({
53
+ ...rest,
54
+ scope_id: orgScopeId,
55
+ cloned_from_at: new Date().toISOString(),
56
+ });
57
+ if (!inserted[0])
58
+ throw new CloneToOverrideError('Insert returned no row');
59
+ return inserted[0];
60
+ }
@@ -12,4 +12,6 @@ export { MockConfigProvider } from './mock_config_provider.js';
12
12
  export { ConfigErrorCode } from './types.js';
13
13
  export type { ConfigProvider, HazoConfigOptions, Logger, HazoConfigError, LogData } from './types.js';
14
14
  export type { ConfigType, AppConfigItem, AppConfigContext, AppConfigProps, UseAppConfigResult } from './app_config_types.js';
15
+ export { mergeTwoTier } from './two_tier.js';
16
+ export type { TwoTierRow, MergeOptions } from './two_tier.js';
15
17
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,eAAe,EACf,OAAO,EACR,MAAM,YAAY,CAAA;AAGnB,YAAY,EACV,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EACnB,MAAM,uBAAuB,CAAA"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/lib/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAGH,OAAO,EAAE,kBAAkB,EAAE,MAAM,2BAA2B,CAAA;AAC9D,OAAO,EAAE,eAAe,EAAE,MAAM,YAAY,CAAA;AAC5C,YAAY,EACV,cAAc,EACd,iBAAiB,EACjB,MAAM,EACN,eAAe,EACf,OAAO,EACR,MAAM,YAAY,CAAA;AAGnB,YAAY,EACV,UAAU,EACV,aAAa,EACb,gBAAgB,EAChB,cAAc,EACd,kBAAkB,EACnB,MAAM,uBAAuB,CAAA;AAK9B,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA;AAC5C,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,eAAe,CAAA"}
package/dist/lib/index.js CHANGED
@@ -11,3 +11,7 @@
11
11
  // Client-safe exports (no Node.js dependencies)
12
12
  export { MockConfigProvider } from './mock_config_provider.js';
13
13
  export { ConfigErrorCode } from './types.js';
14
+ // Two-tier (global default + scope-level override) merge -- pure, no
15
+ // database dependency. See 'hazo_config/server-data' for the hazo_connect-
16
+ // backed clone/override-count helpers that operate on the same shape.
17
+ export { mergeTwoTier } from './two_tier.js';
@@ -0,0 +1,14 @@
1
+ /**
2
+ * Purpose: Count scope-level override rows for a two-tier config key.
3
+ *
4
+ * hazo_connect is an optional peer dependency here (see `hazo_config/server-data`,
5
+ * the entry point that re-exports this) and is loaded via dynamic import()
6
+ * for the same reason as `clone_to_override.ts` -- see that file's header.
7
+ */
8
+ /**
9
+ * Count how many override (non-global) rows exist in `table` for the given
10
+ * `keyColumn`/`keyValue`. A row counts as an override when its `scope_id`
11
+ * is not `null`.
12
+ */
13
+ export declare function getOverrideCount(table: string, keyColumn: string, keyValue: string): Promise<number>;
14
+ //# sourceMappingURL=override_count.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"override_count.d.ts","sourceRoot":"","sources":["../../src/lib/override_count.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AA8BH;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAOjB"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Purpose: Count scope-level override rows for a two-tier config key.
3
+ *
4
+ * hazo_connect is an optional peer dependency here (see `hazo_config/server-data`,
5
+ * the entry point that re-exports this) and is loaded via dynamic import()
6
+ * for the same reason as `clone_to_override.ts` -- see that file's header.
7
+ */
8
+ async function loadCreateCrudService() {
9
+ // @ts-ignore — hazo_connect/server is a valid subpath export; moduleResolution:"node"
10
+ // predates subpath exports so TS can't resolve it statically, but it loads correctly at runtime.
11
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
12
+ const mod = (await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ 'hazo_connect/server'));
13
+ return mod.createCrudService;
14
+ }
15
+ async function loadGetHazoConnectSingleton() {
16
+ // @ts-ignore — hazo_connect/nextjs/setup is a valid subpath export; see loadCreateCrudService above.
17
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
18
+ const mod = (await import(/* turbopackIgnore: true */ /* webpackIgnore: true */ 'hazo_connect/nextjs/setup'));
19
+ return mod.getHazoConnectSingleton;
20
+ }
21
+ /**
22
+ * Count how many override (non-global) rows exist in `table` for the given
23
+ * `keyColumn`/`keyValue`. A row counts as an override when its `scope_id`
24
+ * is not `null`.
25
+ */
26
+ export async function getOverrideCount(table, keyColumn, keyValue) {
27
+ const createCrudService = await loadCreateCrudService();
28
+ const getHazoConnectSingleton = await loadGetHazoConnectSingleton();
29
+ const svc = createCrudService(getHazoConnectSingleton(), table);
30
+ const rows = (await svc.list((q) => q.where(keyColumn, 'eq', keyValue).select('id,scope_id'))) ?? [];
31
+ return rows.filter((r) => r.scope_id !== null).length;
32
+ }
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Purpose: Two-tier (global default + scope-level override) config merge.
3
+ *
4
+ * Companion to the AppConfig database-backed configuration story (see
5
+ * `app_config_types.ts`): a global row has `scope_id: null`; an override row
6
+ * has the caller's `scope_id` and shadows the global row that shares its key.
7
+ * Pure and framework-agnostic -- the caller fetches `globals`/`overrides`
8
+ * however it likes (hazo_connect, a plain fetch, a mock) and passes both
9
+ * arrays in.
10
+ */
11
+ /**
12
+ * Minimum shape a two-tier row must have. `scope_id: null` marks a global
13
+ * (platform-default) row; any other value marks a scope-level override.
14
+ */
15
+ export interface TwoTierRow {
16
+ id: string;
17
+ scope_id: string | null;
18
+ enabled: boolean;
19
+ [k: string]: unknown;
20
+ }
21
+ /**
22
+ * Options for {@link mergeTwoTier}.
23
+ */
24
+ export interface MergeOptions<T extends TwoTierRow> {
25
+ /** Platform-default rows (`scope_id: null`). */
26
+ globals: T[];
27
+ /** Scope-level override rows. */
28
+ overrides: T[];
29
+ /** Extracts the key two rows are matched on (e.g. a `code` column, or a composite of several columns). */
30
+ keyFn: (row: T) => string;
31
+ /**
32
+ * When true, skip key-based shadowing entirely and return the union of
33
+ * enabled globals and enabled overrides (both tiers additive, not
34
+ * override-wins-by-key).
35
+ */
36
+ additive?: boolean;
37
+ }
38
+ /**
39
+ * Merge a global/override row pair into the effective list.
40
+ *
41
+ * Default (non-additive) mode: for each key, an override row shadows the
42
+ * global row that shares it; a key present only in one tier passes through
43
+ * as-is. A row (global or override) is included only while `enabled` is
44
+ * true -- an override with `enabled: false` hides an enabled global at the
45
+ * same key, and a disabled global stays hidden unless an override
46
+ * re-enables it.
47
+ *
48
+ * Additive mode (`additive: true`) skips key matching and returns every
49
+ * enabled row from both tiers.
50
+ *
51
+ * @example
52
+ * mergeTwoTier({
53
+ * globals: [{ id: 'g1', scope_id: null, code: 'invoice', enabled: true }],
54
+ * overrides: [{ id: 'o1', scope_id: 'org-A', code: 'invoice', enabled: true }],
55
+ * keyFn: (r) => r.code,
56
+ * })
57
+ * // -> [{ id: 'o1', scope_id: 'org-A', code: 'invoice', enabled: true }]
58
+ */
59
+ export declare function mergeTwoTier<T extends TwoTierRow>(opts: MergeOptions<T>): T[];
60
+ //# sourceMappingURL=two_tier.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"two_tier.d.ts","sourceRoot":"","sources":["../../src/lib/two_tier.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH;;;GAGG;AACH,MAAM,WAAW,UAAU;IACzB,EAAE,EAAE,MAAM,CAAA;IACV,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,OAAO,CAAA;IAChB,CAAC,CAAC,EAAE,MAAM,GAAG,OAAO,CAAA;CACrB;AAED;;GAEG;AACH,MAAM,WAAW,YAAY,CAAC,CAAC,SAAS,UAAU;IAChD,gDAAgD;IAChD,OAAO,EAAE,CAAC,EAAE,CAAA;IACZ,iCAAiC;IACjC,SAAS,EAAE,CAAC,EAAE,CAAA;IACd,0GAA0G;IAC1G,KAAK,EAAE,CAAC,GAAG,EAAE,CAAC,KAAK,MAAM,CAAA;IACzB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,YAAY,CAAC,CAAC,SAAS,UAAU,EAAE,IAAI,EAAE,YAAY,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAyB7E"}
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Purpose: Two-tier (global default + scope-level override) config merge.
3
+ *
4
+ * Companion to the AppConfig database-backed configuration story (see
5
+ * `app_config_types.ts`): a global row has `scope_id: null`; an override row
6
+ * has the caller's `scope_id` and shadows the global row that shares its key.
7
+ * Pure and framework-agnostic -- the caller fetches `globals`/`overrides`
8
+ * however it likes (hazo_connect, a plain fetch, a mock) and passes both
9
+ * arrays in.
10
+ */
11
+ /**
12
+ * Merge a global/override row pair into the effective list.
13
+ *
14
+ * Default (non-additive) mode: for each key, an override row shadows the
15
+ * global row that shares it; a key present only in one tier passes through
16
+ * as-is. A row (global or override) is included only while `enabled` is
17
+ * true -- an override with `enabled: false` hides an enabled global at the
18
+ * same key, and a disabled global stays hidden unless an override
19
+ * re-enables it.
20
+ *
21
+ * Additive mode (`additive: true`) skips key matching and returns every
22
+ * enabled row from both tiers.
23
+ *
24
+ * @example
25
+ * mergeTwoTier({
26
+ * globals: [{ id: 'g1', scope_id: null, code: 'invoice', enabled: true }],
27
+ * overrides: [{ id: 'o1', scope_id: 'org-A', code: 'invoice', enabled: true }],
28
+ * keyFn: (r) => r.code,
29
+ * })
30
+ * // -> [{ id: 'o1', scope_id: 'org-A', code: 'invoice', enabled: true }]
31
+ */
32
+ export function mergeTwoTier(opts) {
33
+ const { globals, overrides, keyFn, additive } = opts;
34
+ if (additive) {
35
+ return [...globals, ...overrides].filter((r) => r.enabled);
36
+ }
37
+ const overrideByKey = new Map();
38
+ for (const r of overrides)
39
+ overrideByKey.set(keyFn(r), r);
40
+ const result = [];
41
+ const seenKeys = new Set();
42
+ for (const g of globals) {
43
+ const k = keyFn(g);
44
+ seenKeys.add(k);
45
+ const override = overrideByKey.get(k);
46
+ const effective = override ?? g;
47
+ if (effective.enabled)
48
+ result.push(effective);
49
+ }
50
+ for (const o of overrides) {
51
+ const k = keyFn(o);
52
+ if (!seenKeys.has(k) && o.enabled)
53
+ result.push(o);
54
+ }
55
+ return result;
56
+ }
@@ -0,0 +1,17 @@
1
+ /**
2
+ * hazo_connect-backed data helpers for hazo_config
3
+ *
4
+ * This entry point contains code that depends on `hazo_connect` (an
5
+ * optional peer dependency), separate from `hazo_config/server` (which is
6
+ * Node fs/path-only for the INI-backed `HazoConfig`) and the main/`/lib`
7
+ * entry points (pure, no database dependency). Only import from here if you
8
+ * have `hazo_connect` installed and want the two-tier global/override CRUD
9
+ * helpers -- consumers of `HazoConfig` or `mergeTwoTier` alone are
10
+ * unaffected either way.
11
+ *
12
+ * Usage:
13
+ * import { cloneToOverride, getOverrideCount } from 'hazo_config/server-data'
14
+ */
15
+ export { cloneToOverride, CloneToOverrideError } from '../lib/clone_to_override.js';
16
+ export { getOverrideCount } from '../lib/override_count.js';
17
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/server-data/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAA;AACnF,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAA"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * hazo_connect-backed data helpers for hazo_config
3
+ *
4
+ * This entry point contains code that depends on `hazo_connect` (an
5
+ * optional peer dependency), separate from `hazo_config/server` (which is
6
+ * Node fs/path-only for the INI-backed `HazoConfig`) and the main/`/lib`
7
+ * entry points (pure, no database dependency). Only import from here if you
8
+ * have `hazo_connect` installed and want the two-tier global/override CRUD
9
+ * helpers -- consumers of `HazoConfig` or `mergeTwoTier` alone are
10
+ * unaffected either way.
11
+ *
12
+ * Usage:
13
+ * import { cloneToOverride, getOverrideCount } from 'hazo_config/server-data'
14
+ */
15
+ export { cloneToOverride, CloneToOverrideError } from '../lib/clone_to_override.js';
16
+ export { getOverrideCount } from '../lib/override_count.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hazo_config",
3
- "version": "2.4.3",
3
+ "version": "2.5.0",
4
4
  "description": "Config wrapper with error handling",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -30,6 +30,11 @@
30
30
  "types": "./dist/lib/index.d.ts",
31
31
  "import": "./dist/lib/index.js",
32
32
  "default": "./dist/lib/index.js"
33
+ },
34
+ "./server-data": {
35
+ "types": "./dist/server-data/index.d.ts",
36
+ "import": "./dist/server-data/index.js",
37
+ "default": "./dist/server-data/index.js"
33
38
  }
34
39
  },
35
40
  "scripts": {
@@ -91,7 +96,7 @@
91
96
  "@types/react": "^18.3.3",
92
97
  "@types/react-dom": "^18.3.0",
93
98
  "@vitejs/plugin-react": "^4.2.0",
94
- "hazo_connect": "^4.0.0",
99
+ "hazo_connect": "^4.1.0",
95
100
  "jsdom": "^24.1.3",
96
101
  "postcss": "^8.4.49",
97
102
  "react": "^18.2.0",
@@ -103,14 +108,18 @@
103
108
  "vitest": "^4.0.15"
104
109
  },
105
110
  "peerDependencies": {
106
- "hazo_core": "^2.0.0",
107
- "hazo_theme": "^1.3.0",
108
- "hazo_ui": "^6.8.0",
111
+ "hazo_connect": "^4.1.0",
112
+ "hazo_core": "^2.2.0",
113
+ "hazo_theme": "^1.3.1",
114
+ "hazo_ui": "^6.11.2",
109
115
  "react": "^18.0.0 || ^19.0.0",
110
116
  "react-dom": "^18.0.0 || ^19.0.0",
111
117
  "tailwindcss": "^4.0.0"
112
118
  },
113
119
  "peerDependenciesMeta": {
120
+ "hazo_connect": {
121
+ "optional": true
122
+ },
114
123
  "hazo_core": {
115
124
  "optional": true
116
125
  },