@cldmv/slothlet 3.2.3 → 3.3.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 +20 -5
- package/dist/lib/builders/api_builder.mjs +233 -3
- package/dist/lib/handlers/api-manager.mjs +23 -0
- package/dist/lib/handlers/context-async.mjs +4 -0
- package/dist/lib/handlers/context-live.mjs +5 -0
- package/dist/lib/handlers/hook-manager.mjs +5 -111
- package/dist/lib/handlers/permission-manager.mjs +408 -0
- package/dist/lib/handlers/unified-wrapper.mjs +90 -22
- package/dist/lib/helpers/config.mjs +91 -7
- package/dist/lib/helpers/pattern-matcher.mjs +141 -0
- package/dist/lib/i18n/languages/de-de.json +21 -1
- package/dist/lib/i18n/languages/en-gb.json +21 -1
- package/dist/lib/i18n/languages/en-us.json +21 -1
- package/dist/lib/i18n/languages/es-mx.json +21 -1
- package/dist/lib/i18n/languages/fr-fr.json +21 -1
- package/dist/lib/i18n/languages/hi-in.json +21 -1
- package/dist/lib/i18n/languages/ja-jp.json +21 -1
- package/dist/lib/i18n/languages/ko-kr.json +21 -1
- package/dist/lib/i18n/languages/pt-br.json +21 -1
- package/dist/lib/i18n/languages/ru-ru.json +21 -1
- package/dist/lib/i18n/languages/zh-cn.json +21 -1
- package/dist/slothlet.mjs +11 -2
- package/package.json +4 -1
- package/types/dist/lib/builders/api_builder.d.mts.map +1 -1
- package/types/dist/lib/handlers/api-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-async.d.mts.map +1 -1
- package/types/dist/lib/handlers/context-live.d.mts.map +1 -1
- package/types/dist/lib/handlers/hook-manager.d.mts.map +1 -1
- package/types/dist/lib/handlers/permission-manager.d.mts +151 -0
- package/types/dist/lib/handlers/permission-manager.d.mts.map +1 -0
- package/types/dist/lib/handlers/unified-wrapper.d.mts.map +1 -1
- package/types/dist/lib/helpers/config.d.mts +16 -0
- package/types/dist/lib/helpers/config.d.mts.map +1 -1
- package/types/dist/lib/helpers/pattern-matcher.d.mts +44 -0
- package/types/dist/lib/helpers/pattern-matcher.d.mts.map +1 -0
- package/types/dist/slothlet.d.mts.map +1 -1
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manages access control rules for API path invocations.
|
|
3
|
+
* Rules are glob-pattern-based (same syntax as hooks: *, **, ?, {a,b}, !negation).
|
|
4
|
+
* Self-calls (same moduleID) always bypass the permission system.
|
|
5
|
+
*
|
|
6
|
+
* @class PermissionManager
|
|
7
|
+
* @extends ComponentBase
|
|
8
|
+
*/
|
|
9
|
+
export class PermissionManager extends ComponentBase {
|
|
10
|
+
/**
|
|
11
|
+
* Property name for auto-discovery by _initializeComponents.
|
|
12
|
+
* @type {string}
|
|
13
|
+
* @static
|
|
14
|
+
*/
|
|
15
|
+
static slothletProperty: string;
|
|
16
|
+
/**
|
|
17
|
+
* Add a permission rule.
|
|
18
|
+
*
|
|
19
|
+
* @param {object} rule - The rule definition.
|
|
20
|
+
* @param {string} rule.caller - Glob pattern matching caller API paths.
|
|
21
|
+
* @param {string} rule.target - Glob pattern matching target API paths.
|
|
22
|
+
* @param {string} rule.effect - "allow" or "deny".
|
|
23
|
+
* @param {string|null} [ownerModuleID=null] - Module ID that owns this rule.
|
|
24
|
+
* @param {string|null} [ruleId=null] - Optional rule ID to reuse (for replay).
|
|
25
|
+
* @returns {string} The rule ID (generated or reused).
|
|
26
|
+
* @throws {SlothletError} INVALID_PERMISSION_RULE if rule is malformed.
|
|
27
|
+
* @example
|
|
28
|
+
* pm.addRule({ caller: "payments.**", target: "db.write", effect: "allow" }, "mod_abc123");
|
|
29
|
+
*/
|
|
30
|
+
addRule(rule: {
|
|
31
|
+
caller: string;
|
|
32
|
+
target: string;
|
|
33
|
+
effect: string;
|
|
34
|
+
}, ownerModuleID?: string | null, ruleId?: string | null): string;
|
|
35
|
+
/**
|
|
36
|
+
* Remove a permission rule by ID.
|
|
37
|
+
* A module cannot remove rules it owns (immutability).
|
|
38
|
+
*
|
|
39
|
+
* @param {string} ruleId - The rule ID to remove.
|
|
40
|
+
* @param {string|null} [callerModuleID=null] - Module ID of the caller attempting removal.
|
|
41
|
+
* @returns {boolean} True if the rule was removed.
|
|
42
|
+
* @throws {SlothletError} PERMISSION_SELF_MODIFY if caller owns the rule.
|
|
43
|
+
* @example
|
|
44
|
+
* pm.removeRule("perm-3", "mod_other");
|
|
45
|
+
*/
|
|
46
|
+
removeRule(ruleId: string, callerModuleID?: string | null): boolean;
|
|
47
|
+
/**
|
|
48
|
+
* Check whether a caller path is allowed to access a target path.
|
|
49
|
+
* This is the main enforcement method called from applyTrap.
|
|
50
|
+
*
|
|
51
|
+
* @param {string} callerPath - The calling module's API path.
|
|
52
|
+
* @param {string} targetPath - The target API path being accessed.
|
|
53
|
+
* @param {string|null} [callerFilePath=null] - Caller's source file path (for self-call bypass).
|
|
54
|
+
* @param {string|null} [targetFilePath=null] - Target's source file path (for self-call bypass).
|
|
55
|
+
* @returns {boolean} True if access is allowed.
|
|
56
|
+
* @example
|
|
57
|
+
* const allowed = pm.checkAccess("payments.charge", "db.write", "/src/pay.mjs", "/src/db.mjs");
|
|
58
|
+
*/
|
|
59
|
+
checkAccess(callerPath: string, targetPath: string, callerFilePath?: string | null, targetFilePath?: string | null): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Get all rules that match a given target path.
|
|
62
|
+
*
|
|
63
|
+
* @param {string} targetPath - Target API path to check.
|
|
64
|
+
* @returns {Array<object>} Array of matching rule objects (serialized).
|
|
65
|
+
* @example
|
|
66
|
+
* const rules = pm.getRulesForPath("db.write");
|
|
67
|
+
*/
|
|
68
|
+
getRulesForPath(targetPath: string): Array<object>;
|
|
69
|
+
/**
|
|
70
|
+
* Get all rules owned by a given module.
|
|
71
|
+
*
|
|
72
|
+
* @param {string} moduleID - Module ID to look up.
|
|
73
|
+
* @returns {Array<object>} Array of rule objects (serialized).
|
|
74
|
+
* @example
|
|
75
|
+
* const rules = pm.getRulesByModule("mod_abc123");
|
|
76
|
+
*/
|
|
77
|
+
getRulesByModule(moduleID: string): Array<object>;
|
|
78
|
+
/**
|
|
79
|
+
* Get all rules where the caller pattern matches a given caller path.
|
|
80
|
+
* Used by `self.rules()` to show what rules affect the calling module.
|
|
81
|
+
*
|
|
82
|
+
* @param {string} callerPath - Caller API path.
|
|
83
|
+
* @returns {Array<object>} Array of matching rule objects (serialized).
|
|
84
|
+
* @example
|
|
85
|
+
* const rules = pm.getRulesForCaller("payments.charge");
|
|
86
|
+
*/
|
|
87
|
+
getRulesForCaller(callerPath: string): Array<object>;
|
|
88
|
+
/**
|
|
89
|
+
* Enable the permission system globally.
|
|
90
|
+
*
|
|
91
|
+
* @returns {void}
|
|
92
|
+
* @example
|
|
93
|
+
* pm.enable();
|
|
94
|
+
*/
|
|
95
|
+
enable(): void;
|
|
96
|
+
/**
|
|
97
|
+
* Disable the permission system globally (all calls allowed).
|
|
98
|
+
*
|
|
99
|
+
* @returns {void}
|
|
100
|
+
* @example
|
|
101
|
+
* pm.disable();
|
|
102
|
+
*/
|
|
103
|
+
disable(): void;
|
|
104
|
+
/**
|
|
105
|
+
* Whether the permission system is currently enabled.
|
|
106
|
+
*
|
|
107
|
+
* @returns {boolean} True if enabled.
|
|
108
|
+
* @example
|
|
109
|
+
* if (pm.isEnabled()) { ... }
|
|
110
|
+
*/
|
|
111
|
+
isEnabled(): boolean;
|
|
112
|
+
/**
|
|
113
|
+
* Export all registered rules for replay during full reload.
|
|
114
|
+
*
|
|
115
|
+
* @returns {Array<object>} Snapshot of all current rules.
|
|
116
|
+
* @example
|
|
117
|
+
* const snapshot = pm.exportRules();
|
|
118
|
+
*/
|
|
119
|
+
exportRules(): Array<object>;
|
|
120
|
+
/**
|
|
121
|
+
* Re-register rules exported by {@link exportRules}.
|
|
122
|
+
* Called after a full reload to restore programmatic rules.
|
|
123
|
+
*
|
|
124
|
+
* @param {Array<object>} registrations - Snapshot returned by exportRules().
|
|
125
|
+
* @returns {void}
|
|
126
|
+
* @example
|
|
127
|
+
* pm.importRules(snapshot);
|
|
128
|
+
*/
|
|
129
|
+
importRules(registrations: Array<object>): void;
|
|
130
|
+
/**
|
|
131
|
+
* Cleanup permission manager on shutdown.
|
|
132
|
+
* Clears all internal state.
|
|
133
|
+
*
|
|
134
|
+
* @returns {Promise<void>}
|
|
135
|
+
* @example
|
|
136
|
+
* await pm.shutdown();
|
|
137
|
+
*/
|
|
138
|
+
shutdown(): Promise<void>;
|
|
139
|
+
/**
|
|
140
|
+
* Emit a debug message. Delegates to slothlet.debug().
|
|
141
|
+
*
|
|
142
|
+
* @param {string} category - Debug category.
|
|
143
|
+
* @param {object} data - Debug data.
|
|
144
|
+
* @returns {void}
|
|
145
|
+
* @private
|
|
146
|
+
*/
|
|
147
|
+
private debug;
|
|
148
|
+
#private;
|
|
149
|
+
}
|
|
150
|
+
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
151
|
+
//# sourceMappingURL=permission-manager.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permission-manager.d.mts","sourceRoot":"","sources":["../../../../dist/lib/handlers/permission-manager.mjs"],"names":[],"mappings":"AAgCA;;;;;;;GAOG;AACH;IACC;;;;OAIG;IACH,yBAHU,MAAM,CAG8B;IA8E9C;;;;;;;;;;;;;OAaG;IACH,cAVG;QAAqB,MAAM,EAAnB,MAAM;QACO,MAAM,EAAnB,MAAM;QACO,MAAM,EAAnB,MAAM;KACd,kBAAQ,MAAM,GAAC,IAAI,WACX,MAAM,GAAC,IAAI,GACT,MAAM,CA+BlB;IAED;;;;;;;;;;OAUG;IACH,mBAPW,MAAM,mBACN,MAAM,GAAC,IAAI,GACT,OAAO,CAiCnB;IAED;;;;;;;;;;;OAWG;IACH,wBARW,MAAM,cACN,MAAM,mBACN,MAAM,GAAC,IAAI,mBACX,MAAM,GAAC,IAAI,GACT,OAAO,CAqCnB;IAED;;;;;;;OAOG;IACH,4BALW,MAAM,GACJ,KAAK,CAAC,MAAM,CAAC,CAazB;IAED;;;;;;;OAOG;IACH,2BALW,MAAM,GACJ,KAAK,CAAC,MAAM,CAAC,CAYzB;IAED;;;;;;;;OAQG;IACH,8BALW,MAAM,GACJ,KAAK,CAAC,MAAM,CAAC,CAazB;IAED;;;;;;OAMG;IACH,UAJa,IAAI,CAOhB;IAED;;;;;;OAMG;IACH,WAJa,IAAI,CAOhB;IAED;;;;;;OAMG;IACH,aAJa,OAAO,CAMnB;IAED;;;;;;OAMG;IAIH,eAPa,KAAK,CAAC,MAAM,CAAC,CAgBzB;IAED;;;;;;;;OAQG;IACH,2BALW,KAAK,CAAC,MAAM,CAAC,GACX,IAAI,CAShB;IAGD;;;;;;;OAOG;IACH,YAJa,OAAO,CAAC,IAAI,CAAC,CAWzB;IA8MD;;;;;;;OAOG;IACH,cAEC;;CACD;8BAllB6B,0CAA0C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"unified-wrapper.d.mts","sourceRoot":"","sources":["../../../../dist/lib/handlers/unified-wrapper.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"unified-wrapper.d.mts","sourceRoot":"","sources":["../../../../dist/lib/handlers/unified-wrapper.mjs"],"names":[],"mappings":"AAo0GA;;;;;;;;;;;GAWG;AACH,sCAPW,OAAO,GACL,cAAc,GAAC,IAAI,CAkB/B;;;;;AAhvGD;;;;;;;;;;GAUG;AACH;IAiQC;;;;;;;;;;;;;;;;OAgBG;IACH,0BA8BC;IAED;;;;;;;;;;;;;;;;;;OAkBG;IACH,gCA0DC;IApWD;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,+IAtBG;QAAwB,IAAI,EAApB,MAAM;QACU,OAAO,EAAvB,MAAM;QACW,WAAW;QACT,eAAe;QAChB,UAAU,GAA5B,OAAO;QACW,mBAAmB,GAArC,OAAO;QACU,QAAQ,GAAzB,MAAM;QACW,QAAQ,GAAzB,MAAM;QACW,YAAY,GAA7B,MAAM;KAEd,EA4KF;IA1MD;;;;;;;;;;;OAWG;IACH,4BAFa,MAAO,SAAS,CAK5B;IA+ND;;;;OAIG;IACH,qBAHa,MAAO,IAAI,CAKvB;IAkID;;;;;;;;;;;OAWG;IACH,sBAiCC;IAED;;;;;;;;;;;;OAYG;IACH,mBAgDC;IAED;;;;;;;;;OASG;IACH,qBAmDC;IAED;;;;OAIG;IACH,uBA+FC;IAED;;;;;;;;;OASG;IACH,qBAEC;IAED;;;;;;;;;OASG;IACH,sBAiBC;IAED;;;;;;;;;;OAUG;IACH,6BA2bC;IAED;;;;;;;;;;;OAWG;IACH,8BAwIC;IAED;;;;;;;;;;;;;;;;OAgBG;IACH,8BA+qBC;IAED;;;;;;OAMG;IACH,uCAouCC;IAvVE,mBAA0B;IA7pF7B;;;OAGG;IACH,2EAFa,GAAC,CA8Bb;;CAq9FD;8BA5yG6B,0CAA0C;iBADvD,WAAW"}
|
|
@@ -124,6 +124,22 @@ export class Config extends ComponentBase {
|
|
|
124
124
|
public normalizeEnv(env: any | null | undefined): {
|
|
125
125
|
include: string[];
|
|
126
126
|
} | null;
|
|
127
|
+
/**
|
|
128
|
+
* Normalize permissions configuration.
|
|
129
|
+
*
|
|
130
|
+
* @param {object|null} [permissions] - Raw permissions config from user.
|
|
131
|
+
* @param {string} [permissions.defaultPolicy="allow"] - Fallback policy: "allow" or "deny".
|
|
132
|
+
* @param {boolean} [permissions.enabled=true] - Global toggle.
|
|
133
|
+
* @param {string|boolean} [permissions.audit="default"] - Audit level: `"default"` (denied + self-bypass only),
|
|
134
|
+
* `"verbose"` (all decisions). `true` and `false` are accepted and both normalize to `"default"`.
|
|
135
|
+
* @param {Array<object>} [permissions.rules=[]] - Initial permission rules.
|
|
136
|
+
* @returns {object|null} Normalized permissions config, or null when permissions is absent or not an object.
|
|
137
|
+
*
|
|
138
|
+
* @example
|
|
139
|
+
* normalizePermissions({ defaultPolicy: "deny", rules: [{ caller: "**", target: "admin.**", effect: "deny" }] });
|
|
140
|
+
* // => { defaultPolicy: "deny", enabled: true, audit: "default", rules: [...] }
|
|
141
|
+
*/
|
|
142
|
+
normalizePermissions(permissions?: object | null): object | null;
|
|
127
143
|
}
|
|
128
144
|
import { ComponentBase } from "@cldmv/slothlet/factories/component-base";
|
|
129
145
|
//# sourceMappingURL=config.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/config.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/config.mjs"],"names":[],"mappings":"AAqBA;;;;;GAKG;AACH;IACC,gCAAmC;IAEnC;;;;;;;;;;;;;;;;;;;;;;;;;OAyBG;IACH,qCAxBW,MAAM,MAAO,OAkDvB;IAED;;;;;OAKG;IACH,iCAJW,MAAM,GACJ,MAAM,CAsBlB;IAED;;;;;OAKG;IACH,2BAJW,MAAM,GACJ,MAAM,CAsBlB;IAED;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,+CAeC;IAED;;;;;OAKG;IACH,6BAJW,OAAO,MAAO,OAqExB;IAED;;;;;;OAMG;IACH,0CA+IC;IAED;;;;;OAKG;IACH,uCAJW,OAAO,GAAC,MAAM,MAAO,GACnB,MAAO,IAAI,CAsCvB;IAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;IACH,yBArBW,MAAO,IAAI,GAAC,SAAS,GAEnB;QAAE,OAAO,EAAE,MAAM,EAAE,CAAA;KAAE,GAAC,IAAI,CA4BtC;IAED;;;;;;;;;;;;;;OAcG;IACH,mCAZW,MAAM,GAAC,IAAI,GAMT,MAAM,GAAC,IAAI,CA6EvB;CACD;8BA1iB6B,0CAA0C"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile a glob pattern into a matcher function.
|
|
3
|
+
* Supports: * (any chars except .), ** (any chars including .), ? (single char),
|
|
4
|
+
* {a,b} brace expansion, !pattern negation
|
|
5
|
+
*
|
|
6
|
+
* @param {string} pattern - Glob pattern
|
|
7
|
+
* @param {object} [options={}] - Options
|
|
8
|
+
* @param {Function} [options.onMaxDepth] - Called when brace expansion exceeds max depth.
|
|
9
|
+
* Should throw an error. If not provided, a SlothletError("BRACE_EXPANSION_MAX_DEPTH") is thrown.
|
|
10
|
+
* @returns {function} Matcher function that takes a path and returns boolean
|
|
11
|
+
* @example
|
|
12
|
+
* const matcher = compilePattern("payments.**");
|
|
13
|
+
* matcher("payments.charge"); // true
|
|
14
|
+
* matcher("admin.users"); // false
|
|
15
|
+
*/
|
|
16
|
+
export function compilePattern(pattern: string, options?: {
|
|
17
|
+
onMaxDepth?: Function;
|
|
18
|
+
}): Function;
|
|
19
|
+
/**
|
|
20
|
+
* Expand brace patterns {a,b,c} into multiple patterns.
|
|
21
|
+
* Supports nested braces with configurable depth limit.
|
|
22
|
+
*
|
|
23
|
+
* @param {string} pattern - Pattern with braces to expand
|
|
24
|
+
* @param {number} [depth=0] - Current recursion depth
|
|
25
|
+
* @param {number} [maxDepth=10] - Maximum nesting depth
|
|
26
|
+
* @param {object} [options={}] - Options
|
|
27
|
+
* @param {Function} [options.onMaxDepth] - Called when max depth exceeded. Should throw.
|
|
28
|
+
* @returns {string[]} Array of expanded patterns
|
|
29
|
+
* @example
|
|
30
|
+
* expandBraces("{a,b}.path"); // ["a.path", "b.path"]
|
|
31
|
+
*/
|
|
32
|
+
export function expandBraces(pattern: string, depth?: number, maxDepth?: number, options?: {
|
|
33
|
+
onMaxDepth?: Function;
|
|
34
|
+
}): string[];
|
|
35
|
+
/**
|
|
36
|
+
* Split brace alternatives on commas, respecting nested braces.
|
|
37
|
+
*
|
|
38
|
+
* @param {string} content - Content inside braces
|
|
39
|
+
* @returns {string[]} Array of alternatives
|
|
40
|
+
* @example
|
|
41
|
+
* splitBraceAlternatives("a,b,c"); // ["a", "b", "c"]
|
|
42
|
+
*/
|
|
43
|
+
export function splitBraceAlternatives(content: string): string[];
|
|
44
|
+
//# sourceMappingURL=pattern-matcher.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pattern-matcher.d.mts","sourceRoot":"","sources":["../../../../dist/lib/helpers/pattern-matcher.mjs"],"names":[],"mappings":"AAoCA;;;;;;;;;;;;;;GAcG;AACH,wCAVW,MAAM,YAEd;IAA2B,UAAU;CAErC,YAsCF;AAED;;;;;;;;;;;;GAYG;AACH,sCATW,MAAM,UACN,MAAM,aACN,MAAM,YAEd;IAA2B,UAAU;CACrC,GAAU,MAAM,EAAE,CAwDpB;AAED;;;;;;;GAOG;AACH,gDALW,MAAM,GACJ,MAAM,EAAE,CA+BpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"slothlet.d.mts","sourceRoot":"","sources":["../../dist/slothlet.mjs"],"names":[],"mappings":"AAq/BA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,iCAjCW,eAAe,GACb,OAAO,CAAC,WAAW,CAAC,CAsChC;;;;;;;;;SAWa,MAAM;;;;;;;WACN,OAAO,GAAC,MAAM;;;;;;;cAId,OAAO,GAAC,MAAM;;;;eAId,MAAM;;;;cACN,MAAM,GAAC,IAAI;;;;gBACX,MAAM,GAAC,IAAI;;;;YACX;QAAC,KAAK,EAAE,SAAS,GAAC,MAAM,CAAA;KAAC;;;;UAEpC;QAAuD,SAAS,GAArD,MAAM,GAAC;YAAC,OAAO,EAAE,MAAM,CAAC;YAAC,GAAG,EAAE,MAAM,CAAA;SAAC;QAGxB,SAAS,GAAtB,MAAM;KAEjB;;;;;;;;WAAW,OAAO,GAAC,MAAM,GAAC,MAAM;;;;;YAKrB,OAAO,GAAC,MAAM;;;;aAEd,OAAO;;;;kBACP,OAAO;;;;eACP,OAAO,GAAC,MAAM;;;;4BACd,OAAO;;;;;WACP,MAAM;;;;;;;UAMjB;QAA0B,OAAO,GAAtB,MAAM,EAAE;KACnB;;;;;;;;iBAAW,OAAO,GAAC,MAAM,GAAC,QAAQ,GAAC,MAAM;;;;;;;;wBAK9B,MAAM,cAAU,IAAI;;;;;;;;;;aAWpB,MAAY,IAAI;;;;cAChB,MAAY,IAAI;;;;cAE3B;QAAgE,GAAG,EAAxD,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAC,SAAS,CAAC,CAAC;QACzB,GAAG,EAC/B;YAAkC,GAAG;YACH,MAAM;YACN,MAAM;SACxC;QAA4B,OAAO,EACnC;YAAsC,GAAG;YACO,OAAO,EAA5C,SAAkB;YACS,GAAG;YACH,KAAK;YACL,GAAG;SACzC;QAA6B,IAAI,GACjC;YAAkC,MAAM,GACxC;gBAAqD,GAAG,GAA7C,SAAkB;gBAC0B,eAAe,GAA3D,MAAY,MAAM,EAAE;gBACY,GAAG;aAC9C;YAAkC,OAAO,GAA9B,MAAM;YACmB,QAAQ;YACE,MAAM,GAAzC,SAAkB;YACiB,YAAY,GAA/C,SAAkB;YACK,IAAI,GAA3B,MAAM;YAC6B,OAAO,GAA1C,SAAkB;YACK,KAAK,GACvC;gBAA0C,GAAG;aAC7C;YAAkC,SAAS,GAAhC,MAAM;YACsC,eAAe,GAA3D,MAAY,eAAe;SACtC;QAA4B,IAAI,EAChC;YAAmC,KAAK;YACL,OAAO;YACP,MAAM;YACN,IAAI;YACJ,GAAG;YACH,EAAE;YACF,MAAM;SACzC;QAA4B,SAAS,EACrC;YAAwC,GAAG;YACH,EAAE;SAC1C;QAA4B,WAAW,EACvC;YAAoD,GAAG,EAA5C,SAAkB;YACY,YAAY,EAA1C,OAAO;YAC0C,IAAI,EAArD,MAAY,OAAO,CAAE,IAAI,CAAC;SACrC;QAA4B,QAAQ,EACpC;YAAsD,MAAM,EAAjD,MAAY,MAAO,IAAI;YACK,GAAG;YACH,MAAM;YACN,SAAS;YACM,IAAI,EAA/C,MAAY,MAAO,IAAI;YACK,GAAG;YACH,MAAM;YACN,SAAS;SAChD;QAA4B,KAAK,EACjC;YAAoC,GAAG;SACvC;QAA4B,SAAS,EACrC;YAAwC,GAAG;YACH,UAAU;SAClD;QAA4B,UAAU,EACtC;YAAyC,IAAI;YACJ,UAAU;YACV,UAAU;YACV,kBAAkB;YAClB,kBAAkB;SAC3D;QAA6B,SAAS,GAA3B,MAAM;QACa,MAAM;QACN,GAAG;QACH,KAAK;QACa,QAAQ,EAA7C,MAAY,OAAO,CAAE,IAAI,CAAC;KACvC;;gCAhlC6D,wBAAwB"}
|