hazo_config 2.4.2 → 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 +26 -0
- package/dist/lib/clone_to_override.d.ts +26 -0
- package/dist/lib/clone_to_override.d.ts.map +1 -0
- package/dist/lib/clone_to_override.js +60 -0
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.d.ts.map +1 -1
- package/dist/lib/index.js +4 -0
- package/dist/lib/override_count.d.ts +14 -0
- package/dist/lib/override_count.d.ts.map +1 -0
- package/dist/lib/override_count.js +32 -0
- package/dist/lib/two_tier.d.ts +60 -0
- package/dist/lib/two_tier.d.ts.map +1 -0
- package/dist/lib/two_tier.js +56 -0
- package/dist/server-data/index.d.ts +17 -0
- package/dist/server-data/index.d.ts.map +1 -0
- package/dist/server-data/index.js +16 -0
- package/package.json +14 -5
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
|
+
}
|
package/dist/lib/index.d.ts
CHANGED
|
@@ -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
|
package/dist/lib/index.d.ts.map
CHANGED
|
@@ -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.
|
|
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": "^
|
|
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
|
-
"
|
|
107
|
-
"
|
|
108
|
-
"
|
|
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
|
},
|