@salesforce/b2c-tooling-sdk 1.0.1 → 1.2.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/dist/cjs/cli/base-command.d.ts +33 -8
- package/dist/cjs/cli/base-command.js +92 -35
- package/dist/cjs/cli/base-command.js.map +1 -1
- package/dist/cjs/clients/middleware.d.ts +15 -10
- package/dist/cjs/clients/middleware.js +22 -15
- package/dist/cjs/clients/middleware.js.map +1 -1
- package/dist/cjs/clients/webdav.d.ts +22 -0
- package/dist/cjs/clients/webdav.js +46 -0
- package/dist/cjs/clients/webdav.js.map +1 -1
- package/dist/cjs/config/dw-json.d.ts +32 -0
- package/dist/cjs/config/dw-json.js.map +1 -1
- package/dist/cjs/config/mapping.js +55 -0
- package/dist/cjs/config/mapping.js.map +1 -1
- package/dist/cjs/config/sources/env-source.js +3 -1
- package/dist/cjs/config/sources/env-source.js.map +1 -1
- package/dist/cjs/config/types.d.ts +15 -0
- package/dist/cjs/index.d.ts +3 -2
- package/dist/cjs/index.js +1 -1
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/operations/code/watch.js +98 -75
- package/dist/cjs/operations/code/watch.js.map +1 -1
- package/dist/cjs/operations/debug/dap-adapter.d.ts +72 -0
- package/dist/cjs/operations/debug/dap-adapter.js +505 -0
- package/dist/cjs/operations/debug/dap-adapter.js.map +1 -0
- package/dist/cjs/operations/debug/debug-session.d.ts +51 -0
- package/dist/cjs/operations/debug/debug-session.js +219 -0
- package/dist/cjs/operations/debug/debug-session.js.map +1 -0
- package/dist/cjs/operations/debug/index.d.ts +17 -0
- package/dist/cjs/operations/debug/index.js +19 -0
- package/dist/cjs/operations/debug/index.js.map +1 -0
- package/dist/cjs/operations/debug/sdapi-client.d.ts +44 -0
- package/dist/cjs/operations/debug/sdapi-client.js +169 -0
- package/dist/cjs/operations/debug/sdapi-client.js.map +1 -0
- package/dist/cjs/operations/debug/source-mapping.d.ts +13 -0
- package/dist/cjs/operations/debug/source-mapping.js +57 -0
- package/dist/cjs/operations/debug/source-mapping.js.map +1 -0
- package/dist/cjs/operations/debug/types.d.ts +95 -0
- package/dist/cjs/operations/debug/types.js +2 -0
- package/dist/cjs/operations/debug/types.js.map +1 -0
- package/dist/cjs/operations/debug/variable-store.d.ts +35 -0
- package/dist/cjs/operations/debug/variable-store.js +52 -0
- package/dist/cjs/operations/debug/variable-store.js.map +1 -0
- package/dist/cjs/safety/index.d.ts +7 -2
- package/dist/cjs/safety/index.js +5 -1
- package/dist/cjs/safety/index.js.map +1 -1
- package/dist/cjs/safety/safety-guard.d.ts +92 -0
- package/dist/cjs/safety/safety-guard.js +270 -0
- package/dist/cjs/safety/safety-guard.js.map +1 -0
- package/dist/cjs/safety/safety-middleware.d.ts +86 -1
- package/dist/cjs/safety/safety-middleware.js +165 -16
- package/dist/cjs/safety/safety-middleware.js.map +1 -1
- package/dist/cjs/safety/types.d.ts +81 -0
- package/dist/cjs/safety/types.js +16 -0
- package/dist/cjs/safety/types.js.map +1 -0
- package/dist/cjs/safety/with-confirmation.d.ts +58 -0
- package/dist/cjs/safety/with-confirmation.js +67 -0
- package/dist/cjs/safety/with-confirmation.js.map +1 -0
- package/dist/cjs/ux/confirm.d.ts +14 -0
- package/dist/cjs/ux/confirm.js +36 -0
- package/dist/cjs/ux/confirm.js.map +1 -0
- package/dist/esm/cli/base-command.d.ts +33 -8
- package/dist/esm/cli/base-command.js +92 -35
- package/dist/esm/cli/base-command.js.map +1 -1
- package/dist/esm/clients/middleware.d.ts +15 -10
- package/dist/esm/clients/middleware.js +22 -15
- package/dist/esm/clients/middleware.js.map +1 -1
- package/dist/esm/clients/webdav.d.ts +22 -0
- package/dist/esm/clients/webdav.js +46 -0
- package/dist/esm/clients/webdav.js.map +1 -1
- package/dist/esm/config/dw-json.d.ts +32 -0
- package/dist/esm/config/dw-json.js.map +1 -1
- package/dist/esm/config/mapping.js +55 -0
- package/dist/esm/config/mapping.js.map +1 -1
- package/dist/esm/config/sources/env-source.js +3 -1
- package/dist/esm/config/sources/env-source.js.map +1 -1
- package/dist/esm/config/types.d.ts +15 -0
- package/dist/esm/index.d.ts +3 -2
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/operations/code/watch.js +98 -75
- package/dist/esm/operations/code/watch.js.map +1 -1
- package/dist/esm/operations/debug/dap-adapter.d.ts +72 -0
- package/dist/esm/operations/debug/dap-adapter.js +505 -0
- package/dist/esm/operations/debug/dap-adapter.js.map +1 -0
- package/dist/esm/operations/debug/debug-session.d.ts +51 -0
- package/dist/esm/operations/debug/debug-session.js +219 -0
- package/dist/esm/operations/debug/debug-session.js.map +1 -0
- package/dist/esm/operations/debug/index.d.ts +17 -0
- package/dist/esm/operations/debug/index.js +19 -0
- package/dist/esm/operations/debug/index.js.map +1 -0
- package/dist/esm/operations/debug/sdapi-client.d.ts +44 -0
- package/dist/esm/operations/debug/sdapi-client.js +169 -0
- package/dist/esm/operations/debug/sdapi-client.js.map +1 -0
- package/dist/esm/operations/debug/source-mapping.d.ts +13 -0
- package/dist/esm/operations/debug/source-mapping.js +57 -0
- package/dist/esm/operations/debug/source-mapping.js.map +1 -0
- package/dist/esm/operations/debug/types.d.ts +95 -0
- package/dist/esm/operations/debug/types.js +2 -0
- package/dist/esm/operations/debug/types.js.map +1 -0
- package/dist/esm/operations/debug/variable-store.d.ts +35 -0
- package/dist/esm/operations/debug/variable-store.js +52 -0
- package/dist/esm/operations/debug/variable-store.js.map +1 -0
- package/dist/esm/safety/index.d.ts +7 -2
- package/dist/esm/safety/index.js +5 -1
- package/dist/esm/safety/index.js.map +1 -1
- package/dist/esm/safety/safety-guard.d.ts +92 -0
- package/dist/esm/safety/safety-guard.js +270 -0
- package/dist/esm/safety/safety-guard.js.map +1 -0
- package/dist/esm/safety/safety-middleware.d.ts +86 -1
- package/dist/esm/safety/safety-middleware.js +165 -16
- package/dist/esm/safety/safety-middleware.js.map +1 -1
- package/dist/esm/safety/types.d.ts +81 -0
- package/dist/esm/safety/types.js +16 -0
- package/dist/esm/safety/types.js.map +1 -0
- package/dist/esm/safety/with-confirmation.d.ts +58 -0
- package/dist/esm/safety/with-confirmation.js +67 -0
- package/dist/esm/safety/with-confirmation.js.map +1 -0
- package/dist/esm/ux/confirm.d.ts +14 -0
- package/dist/esm/ux/confirm.js +36 -0
- package/dist/esm/ux/confirm.js.map +1 -0
- package/package.json +14 -3
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for the B2C Commerce Script Debugger API (SDAPI 2.0).
|
|
3
|
+
*
|
|
4
|
+
* @module operations/debug/types
|
|
5
|
+
*/
|
|
6
|
+
import type { CartridgeMapping } from '../code/cartridges.js';
|
|
7
|
+
export interface SdapiLocation {
|
|
8
|
+
function_name: string;
|
|
9
|
+
line_number: number;
|
|
10
|
+
script_path: string;
|
|
11
|
+
}
|
|
12
|
+
export interface SdapiStackFrame {
|
|
13
|
+
index: number;
|
|
14
|
+
location: SdapiLocation;
|
|
15
|
+
}
|
|
16
|
+
export interface SdapiScriptThread {
|
|
17
|
+
id: number;
|
|
18
|
+
status: 'running' | 'halted';
|
|
19
|
+
call_stack: SdapiStackFrame[];
|
|
20
|
+
}
|
|
21
|
+
export interface SdapiScriptThreads {
|
|
22
|
+
_v: string;
|
|
23
|
+
script_threads: SdapiScriptThread[];
|
|
24
|
+
}
|
|
25
|
+
export interface SdapiBreakpoint {
|
|
26
|
+
id: number;
|
|
27
|
+
line_number: number;
|
|
28
|
+
script_path: string;
|
|
29
|
+
condition?: string;
|
|
30
|
+
}
|
|
31
|
+
export interface SdapiBreakpoints {
|
|
32
|
+
_v: string;
|
|
33
|
+
breakpoints: SdapiBreakpoint[];
|
|
34
|
+
}
|
|
35
|
+
export interface SdapiObjectMember {
|
|
36
|
+
name: string;
|
|
37
|
+
parent: string;
|
|
38
|
+
type: string;
|
|
39
|
+
value: string;
|
|
40
|
+
scope?: 'local' | 'closure' | 'global';
|
|
41
|
+
}
|
|
42
|
+
export interface SdapiObjectMembers {
|
|
43
|
+
_v: string;
|
|
44
|
+
count: number;
|
|
45
|
+
start: number;
|
|
46
|
+
total: number;
|
|
47
|
+
object_members: SdapiObjectMember[];
|
|
48
|
+
}
|
|
49
|
+
export interface SdapiEvalResult {
|
|
50
|
+
_v: string;
|
|
51
|
+
expression: string;
|
|
52
|
+
result: string;
|
|
53
|
+
}
|
|
54
|
+
export interface SdapiFault {
|
|
55
|
+
_v: string;
|
|
56
|
+
type: string;
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
export interface BreakpointInput {
|
|
60
|
+
line_number: number;
|
|
61
|
+
script_path: string;
|
|
62
|
+
condition?: string;
|
|
63
|
+
}
|
|
64
|
+
export interface DebugSessionConfig {
|
|
65
|
+
/** B2C instance hostname */
|
|
66
|
+
hostname: string;
|
|
67
|
+
/** Basic auth username (BM user with WebDAV_Manage_Customization) */
|
|
68
|
+
username: string;
|
|
69
|
+
/** Basic auth password / access key */
|
|
70
|
+
password: string;
|
|
71
|
+
/** Client ID for x-dw-client-id header (defaults to "b2c-cli") */
|
|
72
|
+
clientId?: string;
|
|
73
|
+
/** Cartridge mappings for source path resolution */
|
|
74
|
+
cartridgeRoots: CartridgeMapping[];
|
|
75
|
+
/** Thread polling interval in ms (default: 500) */
|
|
76
|
+
pollInterval?: number;
|
|
77
|
+
/** Keepalive/reset interval in ms (default: 15000) */
|
|
78
|
+
keepaliveInterval?: number;
|
|
79
|
+
}
|
|
80
|
+
export interface DebugSessionCallbacks {
|
|
81
|
+
/** Debugger client connected and polling started */
|
|
82
|
+
onConnected?: (hostname: string) => void;
|
|
83
|
+
/** Debugger client disconnected and timers stopped */
|
|
84
|
+
onDisconnected?: () => void;
|
|
85
|
+
/** A thread hit a breakpoint or was otherwise halted */
|
|
86
|
+
onThreadStopped?: (thread: SdapiScriptThread) => void;
|
|
87
|
+
/** A previously halted thread resumed execution */
|
|
88
|
+
onThreadContinued?: (threadId: number) => void;
|
|
89
|
+
/** A thread disappeared from the server (request completed) */
|
|
90
|
+
onThreadExited?: (threadId: number) => void;
|
|
91
|
+
/** The debugger was disabled externally (e.g. BM, another client) */
|
|
92
|
+
onDebuggerDisabled?: () => void;
|
|
93
|
+
/** Non-fatal error during polling or keepalive */
|
|
94
|
+
onError?: (error: Error) => void;
|
|
95
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../src/operations/debug/types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Maps DAP integer variableReference values to SDAPI object_path strings.
|
|
3
|
+
*
|
|
4
|
+
* DAP clients request variables by integer reference. The SDAPI uses
|
|
5
|
+
* dot-delimited object paths for navigating the object tree. This store
|
|
6
|
+
* bridges the two models and supports scope-filtered variable requests.
|
|
7
|
+
*
|
|
8
|
+
* References are cleared whenever execution resumes (continue/step) because
|
|
9
|
+
* SDAPI variable state is only valid while a thread is halted.
|
|
10
|
+
*
|
|
11
|
+
* @module operations/debug/variable-store
|
|
12
|
+
*/
|
|
13
|
+
export interface VariableRef {
|
|
14
|
+
threadId: number;
|
|
15
|
+
frameIndex: number;
|
|
16
|
+
objectPath: string;
|
|
17
|
+
/** If set, this reference is for a scope — filter /variables by this scope. */
|
|
18
|
+
scope?: 'local' | 'closure' | 'global';
|
|
19
|
+
}
|
|
20
|
+
export declare class VariableStore {
|
|
21
|
+
private nextRef;
|
|
22
|
+
private readonly refs;
|
|
23
|
+
/**
|
|
24
|
+
* Get or create an integer reference for the given variable context.
|
|
25
|
+
*/
|
|
26
|
+
getOrCreateReference(threadId: number, frameIndex: number, objectPath: string, scope?: 'local' | 'closure' | 'global'): number;
|
|
27
|
+
/**
|
|
28
|
+
* Resolve an integer reference back to its variable context.
|
|
29
|
+
*/
|
|
30
|
+
resolve(ref: number): VariableRef | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Clear all references. Call on continue/step since variable state becomes stale.
|
|
33
|
+
*/
|
|
34
|
+
clear(): void;
|
|
35
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Maps DAP integer variableReference values to SDAPI object_path strings.
|
|
8
|
+
*
|
|
9
|
+
* DAP clients request variables by integer reference. The SDAPI uses
|
|
10
|
+
* dot-delimited object paths for navigating the object tree. This store
|
|
11
|
+
* bridges the two models and supports scope-filtered variable requests.
|
|
12
|
+
*
|
|
13
|
+
* References are cleared whenever execution resumes (continue/step) because
|
|
14
|
+
* SDAPI variable state is only valid while a thread is halted.
|
|
15
|
+
*
|
|
16
|
+
* @module operations/debug/variable-store
|
|
17
|
+
*/
|
|
18
|
+
export class VariableStore {
|
|
19
|
+
nextRef = 1;
|
|
20
|
+
refs = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* Get or create an integer reference for the given variable context.
|
|
23
|
+
*/
|
|
24
|
+
getOrCreateReference(threadId, frameIndex, objectPath, scope) {
|
|
25
|
+
// Check for existing reference with same parameters
|
|
26
|
+
for (const [ref, entry] of this.refs) {
|
|
27
|
+
if (entry.threadId === threadId &&
|
|
28
|
+
entry.frameIndex === frameIndex &&
|
|
29
|
+
entry.objectPath === objectPath &&
|
|
30
|
+
entry.scope === scope) {
|
|
31
|
+
return ref;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
const ref = this.nextRef++;
|
|
35
|
+
this.refs.set(ref, { threadId, frameIndex, objectPath, scope });
|
|
36
|
+
return ref;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Resolve an integer reference back to its variable context.
|
|
40
|
+
*/
|
|
41
|
+
resolve(ref) {
|
|
42
|
+
return this.refs.get(ref);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Clear all references. Call on continue/step since variable state becomes stale.
|
|
46
|
+
*/
|
|
47
|
+
clear() {
|
|
48
|
+
this.refs.clear();
|
|
49
|
+
this.nextRef = 1;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=variable-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"variable-store.js","sourceRoot":"","sources":["../../../../src/operations/debug/variable-store.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH;;;;;;;;;;;GAWG;AAUH,MAAM,OAAO,aAAa;IAChB,OAAO,GAAG,CAAC,CAAC;IACH,IAAI,GAAG,IAAI,GAAG,EAAuB,CAAC;IAEvD;;OAEG;IACH,oBAAoB,CAClB,QAAgB,EAChB,UAAkB,EAClB,UAAkB,EAClB,KAAsC;QAEtC,oDAAoD;QACpD,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACrC,IACE,KAAK,CAAC,QAAQ,KAAK,QAAQ;gBAC3B,KAAK,CAAC,UAAU,KAAK,UAAU;gBAC/B,KAAK,CAAC,UAAU,KAAK,UAAU;gBAC/B,KAAK,CAAC,KAAK,KAAK,KAAK,EACrB,CAAC;gBACD,OAAO,GAAG,CAAC;YACb,CAAC;QACH,CAAC;QAED,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,EAAC,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAC,CAAC,CAAC;QAC9D,OAAO,GAAG,CAAC;IACb,CAAC;IAED;;OAEG;IACH,OAAO,CAAC,GAAW;QACjB,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;IAC5B,CAAC;IAED;;OAEG;IACH,KAAK;QACH,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC;QAClB,IAAI,CAAC,OAAO,GAAG,CAAC,CAAC;IACnB,CAAC;CACF"}
|
|
@@ -3,5 +3,10 @@
|
|
|
3
3
|
*
|
|
4
4
|
* @module safety
|
|
5
5
|
*/
|
|
6
|
-
export type {
|
|
7
|
-
export {
|
|
6
|
+
export type { SafetyAction, SafetyRule, SafetyOperation, SafetyEvaluation } from './types.js';
|
|
7
|
+
export { isValidSafetyAction, VALID_SAFETY_ACTIONS } from './types.js';
|
|
8
|
+
export type { SafetyLevel, SafetyConfig, SafetyConfigFragment } from './safety-middleware.js';
|
|
9
|
+
export { SafetyBlockedError, SafetyConfirmationRequired, checkSafetyViolation, checkLevelViolation, getSafetyLevel, describeSafetyLevel, maxSafetyLevel, isValidSafetyLevel, parseSafetyLevelString, resolveEffectiveSafetyConfig, loadGlobalSafetyConfig, } from './safety-middleware.js';
|
|
10
|
+
export { SafetyGuard, extractJobIdFromPath } from './safety-guard.js';
|
|
11
|
+
export type { ConfirmHandler } from './with-confirmation.js';
|
|
12
|
+
export { withSafetyConfirmation } from './with-confirmation.js';
|
package/dist/cjs/safety/index.js
CHANGED
|
@@ -3,5 +3,9 @@
|
|
|
3
3
|
* SPDX-License-Identifier: Apache-2
|
|
4
4
|
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
5
|
*/
|
|
6
|
-
export {
|
|
6
|
+
export { isValidSafetyAction, VALID_SAFETY_ACTIONS } from './types.js';
|
|
7
|
+
export { SafetyBlockedError, SafetyConfirmationRequired, checkSafetyViolation, checkLevelViolation, getSafetyLevel, describeSafetyLevel, maxSafetyLevel, isValidSafetyLevel, parseSafetyLevelString, resolveEffectiveSafetyConfig, loadGlobalSafetyConfig, } from './safety-middleware.js';
|
|
8
|
+
// SafetyGuard
|
|
9
|
+
export { SafetyGuard, extractJobIdFromPath } from './safety-guard.js';
|
|
10
|
+
export { withSafetyConfirmation } from './with-confirmation.js';
|
|
7
11
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/safety/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/safety/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAUH,OAAO,EAAC,mBAAmB,EAAE,oBAAoB,EAAC,MAAM,YAAY,CAAC;AAIrE,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,oBAAoB,EACpB,mBAAmB,EACnB,cAAc,EACd,mBAAmB,EACnB,cAAc,EACd,kBAAkB,EAClB,sBAAsB,EACtB,4BAA4B,EAC5B,sBAAsB,GACvB,MAAM,wBAAwB,CAAC;AAEhC,cAAc;AACd,OAAO,EAAC,WAAW,EAAE,oBAAoB,EAAC,MAAM,mBAAmB,CAAC;AAIpE,OAAO,EAAC,sBAAsB,EAAC,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import type { SafetyConfig } from './safety-middleware.js';
|
|
2
|
+
import type { SafetyEvaluation, SafetyOperation, SafetyRule } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Extract a job ID from a URL path if it's a job execution endpoint.
|
|
5
|
+
*
|
|
6
|
+
* Matches patterns like:
|
|
7
|
+
* - `/s/-/dw/data/v24_5/jobs/sfcc-site-archive-import/executions`
|
|
8
|
+
* - `/jobs/sfcc-site-archive-export/executions`
|
|
9
|
+
*/
|
|
10
|
+
export declare function extractJobIdFromPath(path: string): string | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* SafetyGuard evaluates operations against safety rules and levels.
|
|
13
|
+
*
|
|
14
|
+
* The guard provides three levels of API:
|
|
15
|
+
* - {@link evaluate} — returns a {@link SafetyEvaluation} describing what should happen
|
|
16
|
+
* - {@link assert} — throws {@link SafetyBlockedError} or {@link SafetyConfirmationRequired}
|
|
17
|
+
* - {@link temporarilyAllow} — creates a scoped exemption for confirmed operations
|
|
18
|
+
*
|
|
19
|
+
* The HTTP middleware uses the guard internally so all HTTP requests are
|
|
20
|
+
* evaluated automatically. CLI commands and other consumers can use the
|
|
21
|
+
* guard directly for richer safety interaction (command-level checks,
|
|
22
|
+
* confirmation flows).
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* const guard = new SafetyGuard({
|
|
27
|
+
* level: 'NO_UPDATE',
|
|
28
|
+
* confirm: true,
|
|
29
|
+
* rules: [{ job: 'sfcc-site-archive-export', action: 'allow' }],
|
|
30
|
+
* });
|
|
31
|
+
*
|
|
32
|
+
* const evaluation = guard.evaluate({ type: 'job', jobId: 'sfcc-site-archive-export' });
|
|
33
|
+
* // evaluation.action === 'allow'
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export declare class SafetyGuard {
|
|
37
|
+
readonly config: SafetyConfig;
|
|
38
|
+
private temporaryAllows;
|
|
39
|
+
private readonly logger;
|
|
40
|
+
constructor(config: SafetyConfig);
|
|
41
|
+
/**
|
|
42
|
+
* Evaluate an operation against safety rules and level.
|
|
43
|
+
*
|
|
44
|
+
* Evaluation order:
|
|
45
|
+
* 1. Temporary allows (from confirmed retries) — if matched, allow
|
|
46
|
+
* 2. Config rules in order — first matching rule's action wins
|
|
47
|
+
* 3. Level-based default — confirm if `confirm: true`, otherwise block/allow
|
|
48
|
+
*
|
|
49
|
+
* All evaluations are trace-logged for diagnostics.
|
|
50
|
+
*/
|
|
51
|
+
evaluate(operation: SafetyOperation): SafetyEvaluation;
|
|
52
|
+
/**
|
|
53
|
+
* Assert that an operation is allowed.
|
|
54
|
+
*
|
|
55
|
+
* @throws {SafetyBlockedError} if the operation is blocked
|
|
56
|
+
* @throws {SafetyConfirmationRequired} if the operation needs confirmation
|
|
57
|
+
*/
|
|
58
|
+
assert(operation: SafetyOperation): void;
|
|
59
|
+
/**
|
|
60
|
+
* Create a temporary exemption for a confirmed operation.
|
|
61
|
+
*
|
|
62
|
+
* Returns a cleanup function that removes the exemption. Use this
|
|
63
|
+
* to retry an operation after the user has confirmed.
|
|
64
|
+
*/
|
|
65
|
+
temporarilyAllow(operation: SafetyOperation): () => void;
|
|
66
|
+
/**
|
|
67
|
+
* Add a temporary safety rule for a scoped exemption.
|
|
68
|
+
*
|
|
69
|
+
* Unlike {@link temporarilyAllow} which derives a rule from an operation,
|
|
70
|
+
* this accepts an arbitrary rule — useful for granting broad temporary
|
|
71
|
+
* access (e.g., allowing WebDAV DELETE on Impex paths during a job export).
|
|
72
|
+
*
|
|
73
|
+
* Returns a cleanup function that removes the rule.
|
|
74
|
+
*/
|
|
75
|
+
temporarilyAddRule(rule: SafetyRule): () => void;
|
|
76
|
+
/**
|
|
77
|
+
* Evaluate an operation using only the safety level (no rules).
|
|
78
|
+
*/
|
|
79
|
+
private evaluateByLevel;
|
|
80
|
+
/**
|
|
81
|
+
* Convert an operation to a temporary allow rule for retry.
|
|
82
|
+
*/
|
|
83
|
+
private operationToRule;
|
|
84
|
+
/**
|
|
85
|
+
* Describe why a rule matched, for user-facing messages.
|
|
86
|
+
*/
|
|
87
|
+
private describeRuleMatch;
|
|
88
|
+
/**
|
|
89
|
+
* Describe why the level blocked an operation, for user-facing messages.
|
|
90
|
+
*/
|
|
91
|
+
private describeLevelBlock;
|
|
92
|
+
}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2025, Salesforce, Inc.
|
|
3
|
+
* SPDX-License-Identifier: Apache-2
|
|
4
|
+
* For full license text, see the license.txt file in the repo root or http://www.apache.org/licenses/LICENSE-2.0
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* SafetyGuard: SDK-level safety evaluation engine.
|
|
8
|
+
*
|
|
9
|
+
* Evaluates operations against safety rules and levels, producing typed
|
|
10
|
+
* evaluations (allow/block/confirm). Used by both the HTTP middleware
|
|
11
|
+
* (automatic) and command-level checks (opt-in).
|
|
12
|
+
*
|
|
13
|
+
* @module safety/safety-guard
|
|
14
|
+
*/
|
|
15
|
+
import { Minimatch } from 'minimatch';
|
|
16
|
+
import { getLogger } from '../logging/index.js';
|
|
17
|
+
import { SafetyBlockedError, SafetyConfirmationRequired, checkLevelViolation, describeSafetyLevel, } from './safety-middleware.js';
|
|
18
|
+
/** Regex to extract job ID from OCAPI job execution URLs. */
|
|
19
|
+
const JOB_EXECUTION_PATTERN = /\/jobs\/([^/]+)\/executions/;
|
|
20
|
+
/**
|
|
21
|
+
* Extract a job ID from a URL path if it's a job execution endpoint.
|
|
22
|
+
*
|
|
23
|
+
* Matches patterns like:
|
|
24
|
+
* - `/s/-/dw/data/v24_5/jobs/sfcc-site-archive-import/executions`
|
|
25
|
+
* - `/jobs/sfcc-site-archive-export/executions`
|
|
26
|
+
*/
|
|
27
|
+
export function extractJobIdFromPath(path) {
|
|
28
|
+
const match = JOB_EXECUTION_PATTERN.exec(path);
|
|
29
|
+
return match?.[1];
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Test whether a string matches a glob pattern.
|
|
33
|
+
* Uses minimatch with dot matching enabled.
|
|
34
|
+
*/
|
|
35
|
+
function matchGlob(value, pattern) {
|
|
36
|
+
const matcher = new Minimatch(pattern, { dot: true, nocase: true });
|
|
37
|
+
return matcher.match(value);
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Check if a rule matches an operation.
|
|
41
|
+
*/
|
|
42
|
+
function ruleMatchesOperation(rule, operation) {
|
|
43
|
+
// Command matcher
|
|
44
|
+
if (rule.command !== undefined) {
|
|
45
|
+
if (!operation.commandId)
|
|
46
|
+
return false;
|
|
47
|
+
return matchGlob(operation.commandId, rule.command);
|
|
48
|
+
}
|
|
49
|
+
// Job matcher
|
|
50
|
+
if (rule.job !== undefined) {
|
|
51
|
+
const jobId = operation.jobId ?? (operation.path ? extractJobIdFromPath(operation.path) : undefined);
|
|
52
|
+
if (!jobId)
|
|
53
|
+
return false;
|
|
54
|
+
return matchGlob(jobId, rule.job);
|
|
55
|
+
}
|
|
56
|
+
// HTTP method + path matcher
|
|
57
|
+
if (rule.path !== undefined) {
|
|
58
|
+
if (!operation.path)
|
|
59
|
+
return false;
|
|
60
|
+
if (!matchGlob(operation.path, rule.path))
|
|
61
|
+
return false;
|
|
62
|
+
// If method is specified, it must also match
|
|
63
|
+
if (rule.method !== undefined) {
|
|
64
|
+
if (!operation.method)
|
|
65
|
+
return false;
|
|
66
|
+
return matchGlob(operation.method.toUpperCase(), rule.method.toUpperCase());
|
|
67
|
+
}
|
|
68
|
+
return true;
|
|
69
|
+
}
|
|
70
|
+
// Method-only matcher (no path)
|
|
71
|
+
if (rule.method !== undefined) {
|
|
72
|
+
if (!operation.method)
|
|
73
|
+
return false;
|
|
74
|
+
return matchGlob(operation.method.toUpperCase(), rule.method.toUpperCase());
|
|
75
|
+
}
|
|
76
|
+
// Rule has no matchers — does not match anything
|
|
77
|
+
return false;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* SafetyGuard evaluates operations against safety rules and levels.
|
|
81
|
+
*
|
|
82
|
+
* The guard provides three levels of API:
|
|
83
|
+
* - {@link evaluate} — returns a {@link SafetyEvaluation} describing what should happen
|
|
84
|
+
* - {@link assert} — throws {@link SafetyBlockedError} or {@link SafetyConfirmationRequired}
|
|
85
|
+
* - {@link temporarilyAllow} — creates a scoped exemption for confirmed operations
|
|
86
|
+
*
|
|
87
|
+
* The HTTP middleware uses the guard internally so all HTTP requests are
|
|
88
|
+
* evaluated automatically. CLI commands and other consumers can use the
|
|
89
|
+
* guard directly for richer safety interaction (command-level checks,
|
|
90
|
+
* confirmation flows).
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const guard = new SafetyGuard({
|
|
95
|
+
* level: 'NO_UPDATE',
|
|
96
|
+
* confirm: true,
|
|
97
|
+
* rules: [{ job: 'sfcc-site-archive-export', action: 'allow' }],
|
|
98
|
+
* });
|
|
99
|
+
*
|
|
100
|
+
* const evaluation = guard.evaluate({ type: 'job', jobId: 'sfcc-site-archive-export' });
|
|
101
|
+
* // evaluation.action === 'allow'
|
|
102
|
+
* ```
|
|
103
|
+
*/
|
|
104
|
+
export class SafetyGuard {
|
|
105
|
+
config;
|
|
106
|
+
temporaryAllows = [];
|
|
107
|
+
logger;
|
|
108
|
+
constructor(config) {
|
|
109
|
+
this.config = config;
|
|
110
|
+
this.logger = getLogger();
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Evaluate an operation against safety rules and level.
|
|
114
|
+
*
|
|
115
|
+
* Evaluation order:
|
|
116
|
+
* 1. Temporary allows (from confirmed retries) — if matched, allow
|
|
117
|
+
* 2. Config rules in order — first matching rule's action wins
|
|
118
|
+
* 3. Level-based default — confirm if `confirm: true`, otherwise block/allow
|
|
119
|
+
*
|
|
120
|
+
* All evaluations are trace-logged for diagnostics.
|
|
121
|
+
*/
|
|
122
|
+
evaluate(operation) {
|
|
123
|
+
// 1. Check temporary allows (confirmed operations)
|
|
124
|
+
for (const rule of this.temporaryAllows) {
|
|
125
|
+
if (ruleMatchesOperation(rule, operation)) {
|
|
126
|
+
const evaluation = {
|
|
127
|
+
action: 'allow',
|
|
128
|
+
reason: 'Temporarily allowed after confirmation',
|
|
129
|
+
operation,
|
|
130
|
+
rule,
|
|
131
|
+
};
|
|
132
|
+
this.logger.trace({ operation, evaluation }, '[SafetyGuard] Allowed by temporary exemption');
|
|
133
|
+
return evaluation;
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
// 2. Check config rules (first match wins)
|
|
137
|
+
if (this.config.rules) {
|
|
138
|
+
for (const rule of this.config.rules) {
|
|
139
|
+
if (ruleMatchesOperation(rule, operation)) {
|
|
140
|
+
const evaluation = {
|
|
141
|
+
action: rule.action,
|
|
142
|
+
reason: this.describeRuleMatch(rule, operation),
|
|
143
|
+
operation,
|
|
144
|
+
rule,
|
|
145
|
+
};
|
|
146
|
+
this.logger.trace({ operation, rule, action: rule.action }, '[SafetyGuard] Matched rule');
|
|
147
|
+
return evaluation;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
// 3. Fall back to level-based evaluation
|
|
152
|
+
return this.evaluateByLevel(operation);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Assert that an operation is allowed.
|
|
156
|
+
*
|
|
157
|
+
* @throws {SafetyBlockedError} if the operation is blocked
|
|
158
|
+
* @throws {SafetyConfirmationRequired} if the operation needs confirmation
|
|
159
|
+
*/
|
|
160
|
+
assert(operation) {
|
|
161
|
+
const evaluation = this.evaluate(operation);
|
|
162
|
+
switch (evaluation.action) {
|
|
163
|
+
case 'allow':
|
|
164
|
+
return;
|
|
165
|
+
case 'block':
|
|
166
|
+
throw new SafetyBlockedError(evaluation.reason, operation.method ?? '', operation.url ?? '', this.config.level);
|
|
167
|
+
case 'confirm':
|
|
168
|
+
throw new SafetyConfirmationRequired(evaluation);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Create a temporary exemption for a confirmed operation.
|
|
173
|
+
*
|
|
174
|
+
* Returns a cleanup function that removes the exemption. Use this
|
|
175
|
+
* to retry an operation after the user has confirmed.
|
|
176
|
+
*/
|
|
177
|
+
temporarilyAllow(operation) {
|
|
178
|
+
const rule = this.operationToRule(operation);
|
|
179
|
+
return this.temporarilyAddRule(rule);
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Add a temporary safety rule for a scoped exemption.
|
|
183
|
+
*
|
|
184
|
+
* Unlike {@link temporarilyAllow} which derives a rule from an operation,
|
|
185
|
+
* this accepts an arbitrary rule — useful for granting broad temporary
|
|
186
|
+
* access (e.g., allowing WebDAV DELETE on Impex paths during a job export).
|
|
187
|
+
*
|
|
188
|
+
* Returns a cleanup function that removes the rule.
|
|
189
|
+
*/
|
|
190
|
+
temporarilyAddRule(rule) {
|
|
191
|
+
this.temporaryAllows.push(rule);
|
|
192
|
+
this.logger.trace({ rule }, '[SafetyGuard] Added temporary rule');
|
|
193
|
+
return () => {
|
|
194
|
+
const idx = this.temporaryAllows.indexOf(rule);
|
|
195
|
+
if (idx >= 0) {
|
|
196
|
+
this.temporaryAllows.splice(idx, 1);
|
|
197
|
+
this.logger.trace({ rule }, '[SafetyGuard] Removed temporary rule');
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Evaluate an operation using only the safety level (no rules).
|
|
203
|
+
*/
|
|
204
|
+
evaluateByLevel(operation) {
|
|
205
|
+
// For HTTP operations, check the level
|
|
206
|
+
if (operation.method && operation.path) {
|
|
207
|
+
const violation = checkLevelViolation(operation.method, operation.path, this.config.level);
|
|
208
|
+
if (violation) {
|
|
209
|
+
const action = this.config.confirm ? 'confirm' : 'block';
|
|
210
|
+
const evaluation = {
|
|
211
|
+
action,
|
|
212
|
+
reason: this.describeLevelBlock(operation),
|
|
213
|
+
operation,
|
|
214
|
+
};
|
|
215
|
+
this.logger.trace({ operation, action, level: this.config.level }, '[SafetyGuard] Level evaluation');
|
|
216
|
+
return evaluation;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
// For command operations, no level-based blocking (levels are HTTP-level)
|
|
220
|
+
// Commands opt into safety via rules or assertDestructiveOperationAllowed()
|
|
221
|
+
const evaluation = {
|
|
222
|
+
action: 'allow',
|
|
223
|
+
reason: 'No matching rule and level allows this operation',
|
|
224
|
+
operation,
|
|
225
|
+
};
|
|
226
|
+
this.logger.trace({ operation, level: this.config.level }, '[SafetyGuard] Allowed by level');
|
|
227
|
+
return evaluation;
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* Convert an operation to a temporary allow rule for retry.
|
|
231
|
+
*/
|
|
232
|
+
operationToRule(operation) {
|
|
233
|
+
if (operation.commandId) {
|
|
234
|
+
return { command: operation.commandId, action: 'allow' };
|
|
235
|
+
}
|
|
236
|
+
if (operation.jobId) {
|
|
237
|
+
return { job: operation.jobId, action: 'allow' };
|
|
238
|
+
}
|
|
239
|
+
// HTTP operation — match exact method + path
|
|
240
|
+
return {
|
|
241
|
+
method: operation.method,
|
|
242
|
+
path: operation.path,
|
|
243
|
+
action: 'allow',
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
/**
|
|
247
|
+
* Describe why a rule matched, for user-facing messages.
|
|
248
|
+
*/
|
|
249
|
+
describeRuleMatch(rule, operation) {
|
|
250
|
+
if (rule.command) {
|
|
251
|
+
return `Command "${operation.commandId}" matched safety rule (command: "${rule.command}", action: ${rule.action})`;
|
|
252
|
+
}
|
|
253
|
+
if (rule.job) {
|
|
254
|
+
return `Job "${operation.jobId}" matched safety rule (job: "${rule.job}", action: ${rule.action})`;
|
|
255
|
+
}
|
|
256
|
+
const method = operation.method ?? 'unknown';
|
|
257
|
+
const path = operation.path ?? 'unknown';
|
|
258
|
+
return `${method} ${path} matched safety rule (action: ${rule.action})`;
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Describe why the level blocked an operation, for user-facing messages.
|
|
262
|
+
*/
|
|
263
|
+
describeLevelBlock(operation) {
|
|
264
|
+
const method = operation.method ?? 'unknown';
|
|
265
|
+
const path = operation.path ?? 'unknown';
|
|
266
|
+
const levelDesc = describeSafetyLevel(this.config.level);
|
|
267
|
+
return `${method} ${path} blocked by safety level ${this.config.level} — ${levelDesc}`;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
//# sourceMappingURL=safety-guard.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety-guard.js","sourceRoot":"","sources":["../../../src/safety/safety-guard.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH;;;;;;;;GAQG;AAEH,OAAO,EAAC,SAAS,EAAC,MAAM,WAAW,CAAC;AACpC,OAAO,EAAC,SAAS,EAAc,MAAM,qBAAqB,CAAC;AAE3D,OAAO,EACL,kBAAkB,EAClB,0BAA0B,EAC1B,mBAAmB,EACnB,mBAAmB,GACpB,MAAM,wBAAwB,CAAC;AAGhC,6DAA6D;AAC7D,MAAM,qBAAqB,GAAG,6BAA6B,CAAC;AAE5D;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAAY;IAC/C,MAAM,KAAK,GAAG,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED;;;GAGG;AACH,SAAS,SAAS,CAAC,KAAa,EAAE,OAAe;IAC/C,MAAM,OAAO,GAAG,IAAI,SAAS,CAAC,OAAO,EAAE,EAAC,GAAG,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAC,CAAC,CAAC;IAClE,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;AAC9B,CAAC;AAED;;GAEG;AACH,SAAS,oBAAoB,CAAC,IAAgB,EAAE,SAA0B;IACxE,kBAAkB;IAClB,IAAI,IAAI,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;QAC/B,IAAI,CAAC,SAAS,CAAC,SAAS;YAAE,OAAO,KAAK,CAAC;QACvC,OAAO,SAAS,CAAC,SAAS,CAAC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,CAAC;IACtD,CAAC;IAED,cAAc;IACd,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,oBAAoB,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QACrG,IAAI,CAAC,KAAK;YAAE,OAAO,KAAK,CAAC;QACzB,OAAO,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,CAAC;IAED,6BAA6B;IAC7B,IAAI,IAAI,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;QAC5B,IAAI,CAAC,SAAS,CAAC,IAAI;YAAE,OAAO,KAAK,CAAC;QAClC,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC;YAAE,OAAO,KAAK,CAAC;QACxD,6CAA6C;QAC7C,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YAC9B,IAAI,CAAC,SAAS,CAAC,MAAM;gBAAE,OAAO,KAAK,CAAC;YACpC,OAAO,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,IAAI,CAAC;IACd,CAAC;IAED,gCAAgC;IAChC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,IAAI,CAAC,SAAS,CAAC,MAAM;YAAE,OAAO,KAAK,CAAC;QACpC,OAAO,SAAS,CAAC,SAAS,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;IAC9E,CAAC;IAED,iDAAiD;IACjD,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,MAAM,OAAO,WAAW;IAIM;IAHpB,eAAe,GAAiB,EAAE,CAAC;IAC1B,MAAM,CAAS;IAEhC,YAA4B,MAAoB;QAApB,WAAM,GAAN,MAAM,CAAc;QAC9C,IAAI,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;IAC5B,CAAC;IAED;;;;;;;;;OASG;IACH,QAAQ,CAAC,SAA0B;QACjC,mDAAmD;QACnD,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,eAAe,EAAE,CAAC;YACxC,IAAI,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;gBAC1C,MAAM,UAAU,GAAqB;oBACnC,MAAM,EAAE,OAAO;oBACf,MAAM,EAAE,wCAAwC;oBAChD,SAAS;oBACT,IAAI;iBACL,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,UAAU,EAAC,EAAE,8CAA8C,CAAC,CAAC;gBAC3F,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;QAED,2CAA2C;QAC3C,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;YACtB,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC;gBACrC,IAAI,oBAAoB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;oBAC1C,MAAM,UAAU,GAAqB;wBACnC,MAAM,EAAE,IAAI,CAAC,MAAM;wBACnB,MAAM,EAAE,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC;wBAC/C,SAAS;wBACT,IAAI;qBACL,CAAC;oBACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAC,EAAE,4BAA4B,CAAC,CAAC;oBACxF,OAAO,UAAU,CAAC;gBACpB,CAAC;YACH,CAAC;QACH,CAAC;QAED,yCAAyC;QACzC,OAAO,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;IACzC,CAAC;IAED;;;;;OAKG;IACH,MAAM,CAAC,SAA0B;QAC/B,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;QAC5C,QAAQ,UAAU,CAAC,MAAM,EAAE,CAAC;YAC1B,KAAK,OAAO;gBACV,OAAO;YACT,KAAK,OAAO;gBACV,MAAM,IAAI,kBAAkB,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,MAAM,IAAI,EAAE,EAAE,SAAS,CAAC,GAAG,IAAI,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAClH,KAAK,SAAS;gBACZ,MAAM,IAAI,0BAA0B,CAAC,UAAU,CAAC,CAAC;QACrD,CAAC;IACH,CAAC;IAED;;;;;OAKG;IACH,gBAAgB,CAAC,SAA0B;QACzC,MAAM,IAAI,GAAG,IAAI,CAAC,eAAe,CAAC,SAAS,CAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,kBAAkB,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IAED;;;;;;;;OAQG;IACH,kBAAkB,CAAC,IAAgB;QACjC,IAAI,CAAC,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,IAAI,EAAC,EAAE,oCAAoC,CAAC,CAAC;QAEhE,OAAO,GAAG,EAAE;YACV,MAAM,GAAG,GAAG,IAAI,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;YAC/C,IAAI,GAAG,IAAI,CAAC,EAAE,CAAC;gBACb,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;gBACpC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,IAAI,EAAC,EAAE,sCAAsC,CAAC,CAAC;YACpE,CAAC;QACH,CAAC,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,SAA0B;QAChD,uCAAuC;QACvC,IAAI,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC,IAAI,EAAE,CAAC;YACvC,MAAM,SAAS,GAAG,mBAAmB,CAAC,SAAS,CAAC,MAAM,EAAE,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAC3F,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,MAAM,GAAiB,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;gBACvE,MAAM,UAAU,GAAqB;oBACnC,MAAM;oBACN,MAAM,EAAE,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC;oBAC1C,SAAS;iBACV,CAAC;gBACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAC,EAAE,gCAAgC,CAAC,CAAC;gBACnG,OAAO,UAAU,CAAC;YACpB,CAAC;QACH,CAAC;QAED,0EAA0E;QAC1E,4EAA4E;QAC5E,MAAM,UAAU,GAAqB;YACnC,MAAM,EAAE,OAAO;YACf,MAAM,EAAE,kDAAkD;YAC1D,SAAS;SACV,CAAC;QACF,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,EAAC,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,EAAC,EAAE,gCAAgC,CAAC,CAAC;QAC3F,OAAO,UAAU,CAAC;IACpB,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,SAA0B;QAChD,IAAI,SAAS,CAAC,SAAS,EAAE,CAAC;YACxB,OAAO,EAAC,OAAO,EAAE,SAAS,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAC,CAAC;QACzD,CAAC;QACD,IAAI,SAAS,CAAC,KAAK,EAAE,CAAC;YACpB,OAAO,EAAC,GAAG,EAAE,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAC,CAAC;QACjD,CAAC;QACD,6CAA6C;QAC7C,OAAO;YACL,MAAM,EAAE,SAAS,CAAC,MAAM;YACxB,IAAI,EAAE,SAAS,CAAC,IAAI;YACpB,MAAM,EAAE,OAAO;SAChB,CAAC;IACJ,CAAC;IAED;;OAEG;IACK,iBAAiB,CAAC,IAAgB,EAAE,SAA0B;QACpE,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,OAAO,YAAY,SAAS,CAAC,SAAS,oCAAoC,IAAI,CAAC,OAAO,cAAc,IAAI,CAAC,MAAM,GAAG,CAAC;QACrH,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,OAAO,QAAQ,SAAS,CAAC,KAAK,gCAAgC,IAAI,CAAC,GAAG,cAAc,IAAI,CAAC,MAAM,GAAG,CAAC;QACrG,CAAC;QACD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC;QACzC,OAAO,GAAG,MAAM,IAAI,IAAI,iCAAiC,IAAI,CAAC,MAAM,GAAG,CAAC;IAC1E,CAAC;IAED;;OAEG;IACK,kBAAkB,CAAC,SAA0B;QACnD,MAAM,MAAM,GAAG,SAAS,CAAC,MAAM,IAAI,SAAS,CAAC;QAC7C,MAAM,IAAI,GAAG,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC;QACzC,MAAM,SAAS,GAAG,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACzD,OAAO,GAAG,MAAM,IAAI,IAAI,4BAA4B,IAAI,CAAC,MAAM,CAAC,KAAK,MAAM,SAAS,EAAE,CAAC;IACzF,CAAC;CACF"}
|