@veltdev/sdk-staging 6.0.0-beta.9 → 6.0.1
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/app/client/snippyly.model.d.ts +10 -0
- package/app/models/data/comment-events.data.model.d.ts +10 -0
- package/app/models/data/config.data.model.d.ts +154 -0
- package/app/models/data/notification.model.d.ts +14 -0
- package/app/models/data/suggestion.data.model.d.ts +52 -2
- package/app/utils/constants.d.ts +1 -0
- package/app/utils/enums.d.ts +2 -1
- package/chunk-26SHKRTG.js +1 -0
- package/chunk-3YCIOKO7.js +167 -0
- package/{chunk-MNGERQRW.js → chunk-4O7F5WPS.js} +1 -1
- package/{chunk-XAJ4ABBW.js → chunk-6MGKRXSY.js} +1 -1
- package/{chunk-QDQ2XJUX.js → chunk-7M7HPFJW.js} +1 -1
- package/{chunk-W4BGGBK5.js → chunk-BP5ABAKN.js} +1 -1
- package/{chunk-LAUYCNER.js → chunk-CMV6XYEA.js} +1 -1
- package/{chunk-GUGGWPZ7.js → chunk-CN3MG4V7.js} +1 -1
- package/{chunk-3OIAZGVH.js → chunk-DVLF6ZJF.js} +1 -1
- package/chunk-EWNEUCZN.js +2 -0
- package/{chunk-MJDGHV4Y.js → chunk-FXVG7I7B.js} +1 -1
- package/{chunk-ENIVQSM6.js → chunk-JD2Q4WUT.js} +1 -1
- package/chunk-JMH4W4CX.js +1 -0
- package/{chunk-G56O673H.js → chunk-KPEMFTQE.js} +1 -1
- package/chunk-LSGQWTXT.js +13 -0
- package/{chunk-NR3CZ6OR.js → chunk-MJHVVJAE.js} +1 -1
- package/{chunk-G2POMKRC.js → chunk-NWDWX5YO.js} +1 -1
- package/{chunk-2YJ3NBTO.js → chunk-O7QMGDXD.js} +1 -1
- package/chunk-OMM2AMDX.js +1 -0
- package/{chunk-JSZMRBOR.js → chunk-OO7EO3BV.js} +1 -1
- package/{chunk-MX66OK5A.js → chunk-P6UVM6B7.js} +1 -1
- package/{chunk-SQTBBRA3.js → chunk-PNALREKY.js} +1 -1
- package/{chunk-4QPJMZ5V.js → chunk-Q3SFRIYZ.js} +1 -1
- package/{chunk-AMBQ736A.js → chunk-QEJJ3QNA.js} +1 -1
- package/{chunk-DP4GMASO.js → chunk-QYUV5PXV.js} +1 -1
- package/{chunk-J3FNQGWW.js → chunk-RF3TL6SQ.js} +6 -6
- package/chunk-THHKSZTD.js +1 -0
- package/{chunk-3OILJMAX.js → chunk-W6OGMNHQ.js} +1 -1
- package/{chunk-ZMXXM7C4.js → chunk-WQRY6Y6C.js} +1 -1
- package/{chunk-57VK6E6U.js → chunk-WW7AGQRC.js} +1 -1
- package/chunk-XDHXV3V6.js +93 -0
- package/{chunk-XJWB3IUW.js → chunk-YBCNVNZM.js} +1 -1
- package/{chunk-5W33SILU.js → chunk-YQEMM6AB.js} +1 -1
- package/package.json +1 -1
- package/velt-activity-log.js +1 -1
- package/velt-area.js +1 -1
- package/velt-arrow.js +2 -2
- package/velt-comment.js +8 -8
- package/velt-crdt.js +1 -1
- package/velt-cursor.js +2 -2
- package/velt-huddle.js +3 -3
- package/velt-live-state-sync.js +2 -2
- package/velt-notification.js +1 -1
- package/velt-presence.js +1 -1
- package/velt-reaction.js +1 -1
- package/velt-recorder.js +1 -1
- package/velt-rewriter.js +2 -2
- package/velt-selection.js +1 -1
- package/velt-tag.js +1 -1
- package/velt-user-invite.js +1 -1
- package/velt-user-request.js +1 -1
- package/velt-video-player.js +1 -1
- package/velt-views.js +3 -3
- package/velt.js +264 -20
- package/chunk-52EPUXSU.js +0 -13
- package/chunk-5SSUFLRQ.js +0 -1
- package/chunk-6TORUSYX.js +0 -93
- package/chunk-EWNXINED.js +0 -1
- package/chunk-HDABOQPS.js +0 -1
- package/chunk-RMV5EWSF.js +0 -1
- package/chunk-TY3WZ4Q4.js +0 -167
- package/chunk-YSZQAETY.js +0 -1
|
@@ -283,6 +283,16 @@ export declare class Snippyly {
|
|
|
283
283
|
*/
|
|
284
284
|
setDarkMode: (darkMode: boolean) => void;
|
|
285
285
|
|
|
286
|
+
/**
|
|
287
|
+
* Removes (or restores) ALL Velt visual styling at once — headless mode.
|
|
288
|
+
* By default a derived "functional-only" layer is kept so Velt UI retains
|
|
289
|
+
* its layout, positioning and show/hide behavior. Pass
|
|
290
|
+
* `keepFunctionalStyles: false` for total removal. Fully reversible.
|
|
291
|
+
* @param value {boolean} true = unstyled, false = styled (default)
|
|
292
|
+
* @param config {object} { keepFunctionalStyles?: boolean } defaults to true
|
|
293
|
+
*/
|
|
294
|
+
setUnstyledMode: (value: boolean, config?: { keepFunctionalStyles?: boolean }) => void;
|
|
295
|
+
|
|
286
296
|
/**
|
|
287
297
|
* To check if user allowed in provided document or not.
|
|
288
298
|
*/
|
|
@@ -91,6 +91,7 @@ export type CommentEventTypesMap = {
|
|
|
91
91
|
[CommentEventTypes.SIDEBAR_BUTTON_CLICKED]: SidebarButtonClickedEvent;
|
|
92
92
|
[CommentEventTypes.SIDEBAR_OPEN]: SidebarOpenEvent;
|
|
93
93
|
[CommentEventTypes.SIDEBAR_CLOSE]: SidebarCloseEvent;
|
|
94
|
+
[CommentEventTypes.FULLSCREEN_CLICK]: FullscreenClickEvent;
|
|
94
95
|
[CommentEventTypes.COMMENT_CLICK]: CommentClickEvent;
|
|
95
96
|
[CommentEventTypes.COMMENT_NAVIGATION_BUTTON_CLICK]: CommentNavigationButtonClickEvent;
|
|
96
97
|
[CommentEventTypes.ATTACHMENT_DOWNLOAD_CLICKED]: AttachmentDownloadClickedEvent;
|
|
@@ -359,6 +360,15 @@ export interface SidebarOpenEvent {
|
|
|
359
360
|
export interface SidebarCloseEvent {
|
|
360
361
|
metadata?: VeltEventMetadata;
|
|
361
362
|
}
|
|
363
|
+
/**
|
|
364
|
+
* Fired when the sidebar fullscreen toggle is clicked. Subscribe via
|
|
365
|
+
* `commentElement.on('fullscreenClick')`. `fullScreen` is the NEW state after the toggle.
|
|
366
|
+
* (Also surfaced as the `onFullscreenClick` @Output on the sidebar component.)
|
|
367
|
+
*/
|
|
368
|
+
export interface FullscreenClickEvent {
|
|
369
|
+
fullScreen: boolean;
|
|
370
|
+
metadata?: VeltEventMetadata;
|
|
371
|
+
}
|
|
362
372
|
/** Fired when a comment is clicked in the sidebar list. Subscribe via `commentElement.on('commentClick')`. */
|
|
363
373
|
export interface CommentClickEvent {
|
|
364
374
|
documentId?: string | null;
|
|
@@ -66,6 +66,160 @@ export declare class Config {
|
|
|
66
66
|
* Configuration for routing all traffic through reverse proxies.
|
|
67
67
|
*/
|
|
68
68
|
proxyConfig?: ProxyConfig;
|
|
69
|
+
/**
|
|
70
|
+
* Self-hosting / on-prem backend configuration. When set, a deployment can point
|
|
71
|
+
* Velt-infra endpoints (Firebase config, cloud-function URLs, the notifications-hub
|
|
72
|
+
* RTDB URL, the regional setEncryptedData endpoints) at the customer's own infra.
|
|
73
|
+
*
|
|
74
|
+
* Every field is OPTIONAL and every unspecified value falls back to the per-build
|
|
75
|
+
* default in `src/environments/*` — so an existing SaaS build with no `selfHosted`
|
|
76
|
+
* config behaves exactly as before (behavior-preserving).
|
|
77
|
+
*/
|
|
78
|
+
selfHosted?: SelfHostedConfig;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* VENDORED from the backend deployment-profile manifest — source of truth:
|
|
82
|
+
* `shared-firebase-function` repo, `functions/src/deployment-profiles/modules.manifest.ts`
|
|
83
|
+
* (`DeploymentModuleId`, 12 modules; backend plan §8.3; restructured 2026-07-10 in backend
|
|
84
|
+
* iteration-10, owner-directed). Do NOT add, remove, or rename ids here without a matching
|
|
85
|
+
* manifest change — the endpoint→module map in `endpoints.service.ts` and its cross-repo
|
|
86
|
+
* drift-fence test key off this list.
|
|
87
|
+
*
|
|
88
|
+
* 2026-07-10 restructure summary:
|
|
89
|
+
* - DELETED (absorbed into `core`): `notifications`, `analytics-telemetry`, `console`.
|
|
90
|
+
* The agents RUNTIME also moved to `core` (`agents` keeps only the approval engine).
|
|
91
|
+
* - NEW `rest-api`: the customer-facing REST CFs (`commentsapibe`, `documentsapibe`, …),
|
|
92
|
+
* now opt-in (hardDep `core`). None of the SDK's own runtime endpoints live there.
|
|
93
|
+
* - NEW `legacy-v1`: the ~55 standalone V1 REST CFs — EXCLUDED, never provisioned on any
|
|
94
|
+
* self-hosted profile, so this id never appears in a valid `deploymentProfile`.
|
|
95
|
+
* - `core` is the SOLE mandatory module.
|
|
96
|
+
*/
|
|
97
|
+
export declare const DEPLOYMENT_MODULE_IDS: readonly ["core", "rest-api", "recorder-media", "ai", "agents", "huddle-webrtc", "integrations-workflow", "superflow", "billing-stripe", "migrations", "legacy-v1", "velt-internal"];
|
|
98
|
+
/** A backend feature-module id (see {@link DEPLOYMENT_MODULE_IDS} for provenance). */
|
|
99
|
+
export type DeploymentModuleId = typeof DEPLOYMENT_MODULE_IDS[number];
|
|
100
|
+
/**
|
|
101
|
+
* Per-endpoint overrides for the cloud-function fleet. Each value is a fully-configurable
|
|
102
|
+
* ABSOLUTE base URL — do NOT assume the `*.cloudfunctions.net` shape (Tier A now serves the
|
|
103
|
+
* fleet from Cloud Run with arbitrary hostnames). Keys mirror `environment.cloudFunction.*`.
|
|
104
|
+
* Unspecified keys fall back to the `environment` default.
|
|
105
|
+
*/
|
|
106
|
+
export interface SelfHostedCloudFunctionConfig {
|
|
107
|
+
validateClient?: string;
|
|
108
|
+
getPlanDetails?: string;
|
|
109
|
+
sa?: string;
|
|
110
|
+
getIceServers?: string;
|
|
111
|
+
chatgptCompletion?: string;
|
|
112
|
+
rewriterAskAi?: string;
|
|
113
|
+
whisperTranscription?: string;
|
|
114
|
+
getAllowedDocuments?: string;
|
|
115
|
+
getNotificationsForDocuments?: string;
|
|
116
|
+
videoBackend?: string;
|
|
117
|
+
convertRecording?: string;
|
|
118
|
+
processRecording?: string;
|
|
119
|
+
sdkProxy?: string;
|
|
120
|
+
screenshot?: string;
|
|
121
|
+
/**
|
|
122
|
+
* Single override for the write endpoint that collapses the ×5 regional
|
|
123
|
+
* `setEncryptedData` split — when set, it is used for ALL regions. Self-hosted
|
|
124
|
+
* deployments typically run a single region.
|
|
125
|
+
*/
|
|
126
|
+
setEncryptedData?: string;
|
|
127
|
+
/**
|
|
128
|
+
* Optional per-region overrides (used only if the single `setEncryptedData` above is
|
|
129
|
+
* unset). Keys are the `FirebaseRegion` values (`usCentral1`, `asiaSouthEast1`, ...).
|
|
130
|
+
*/
|
|
131
|
+
regions?: {
|
|
132
|
+
[region: string]: {
|
|
133
|
+
setEncryptedData?: string;
|
|
134
|
+
};
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
export interface SelfHostedConfig {
|
|
138
|
+
/**
|
|
139
|
+
* Strict (full self-hosted) mode. Default `false`.
|
|
140
|
+
*
|
|
141
|
+
* - `false` (hybrid / staged rollout): any endpoint WITHOUT an injected override falls
|
|
142
|
+
* back to the Velt default in `src/environments/*` — useful for testing one
|
|
143
|
+
* self-hosted endpoint at a time while the rest stay on Velt SaaS.
|
|
144
|
+
* - `true` (full self-hosting / data sovereignty): there is NO fallback to Velt. An
|
|
145
|
+
* endpoint without an injected override resolves to an inert
|
|
146
|
+
* `velt://self-hosted-disabled/<endpoint>` sentinel that can never produce network
|
|
147
|
+
* egress — the feature behind it is effectively disabled. Missing CORE endpoints
|
|
148
|
+
* (`validateClient`, `sdkProxy`, `setEncryptedData`, `getNotificationsForDocuments`,
|
|
149
|
+
* the notifications DB URL, `firebaseConfig`) are additionally
|
|
150
|
+
* reported once as a loud misconfiguration error, since the SDK cannot function
|
|
151
|
+
* without them (plan §4.3: every endpoint runs in the customer cloud or is disabled).
|
|
152
|
+
*/
|
|
153
|
+
strict?: boolean;
|
|
154
|
+
/**
|
|
155
|
+
* Firebase config override (deep-merged over `environment.firebaseConfig`). Injected
|
|
156
|
+
* keys win; unspecified keys keep the `environment` default. Per-tenant auth-token
|
|
157
|
+
* claims still override this at runtime (within-project tenant routing is preserved).
|
|
158
|
+
*
|
|
159
|
+
* NOTE (strict mode): this is the ONE value that still falls back to the `environment`
|
|
160
|
+
* default when unset, because an undefined base config would break the Firebase
|
|
161
|
+
* bootstrap chain outright. The miss is still reported as a core misconfiguration, and
|
|
162
|
+
* the `identify()` response config overrides this base at runtime anyway. Making the
|
|
163
|
+
* bootstrap itself injectable is the tracked Phase A gap (`app.module.ts` static
|
|
164
|
+
* `initializeApp`).
|
|
165
|
+
*/
|
|
166
|
+
firebaseConfig?: Partial<FirebaseOptions>;
|
|
167
|
+
/** Override for the notifications-hub RTDB URL (`firebaseNotificationsDatabaseURL`). */
|
|
168
|
+
firebaseNotificationsDatabaseURL?: string;
|
|
169
|
+
/** Per-endpoint cloud-function URL overrides. */
|
|
170
|
+
cloudFunction?: SelfHostedCloudFunctionConfig;
|
|
171
|
+
/**
|
|
172
|
+
* Enables defensive consumption of the portable-backend `identify()` response
|
|
173
|
+
* (`{ token, backend, wsEndpoint, apiEndpoint }`, backend §6.1). Default `false`:
|
|
174
|
+
* when false, a portable response is ignored and the existing Firebase path runs
|
|
175
|
+
* unchanged — no behavior change when the backend does not send it.
|
|
176
|
+
*/
|
|
177
|
+
enablePortableBackend?: boolean;
|
|
178
|
+
/**
|
|
179
|
+
* The RESOLVED module closure of the deployment profile (backend plan §8.3) — the
|
|
180
|
+
* enabled-module-id list the backend deploy tooling emits in
|
|
181
|
+
* `velt-deployment-profile.json`. The customer's tooling inlines it at init; the SDK
|
|
182
|
+
* does NOT fetch it at runtime and does NOT re-resolve module dependencies (the
|
|
183
|
+
* backend's `profile-resolver.ts` already computed the fail-closed closure).
|
|
184
|
+
*
|
|
185
|
+
* Semantics (ratified — SDK-side synthesis, no Tier A server router):
|
|
186
|
+
* - Absent, not an array, or an EMPTY array (a valid resolved closure is never empty):
|
|
187
|
+
* ALL modules enabled — byte-identical to today for SaaS and existing selfHosted
|
|
188
|
+
* configs.
|
|
189
|
+
* - Non-empty: LITERAL membership — any endpoint whose module is NOT in the list
|
|
190
|
+
* resolves to the inert `velt://self-hosted-disabled/*` sentinel, so the denial
|
|
191
|
+
* normalizer synthesizes `'unimplemented'` locally with zero egress. Works with or
|
|
192
|
+
* without `strict`. Unknown/typo'd ids enable nothing (fail-closed, mirroring the
|
|
193
|
+
* backend resolver — a malformed profile must not silently re-open Velt egress).
|
|
194
|
+
* - A profile opt-out is authoritative: it wins over an injected endpoint URL, and its
|
|
195
|
+
* endpoints degrade silently even when classified `core` (opt-out ≠ misconfiguration
|
|
196
|
+
* — they are excluded from the strict-mode core-misconfiguration report).
|
|
197
|
+
*/
|
|
198
|
+
deploymentProfile?: DeploymentModuleId[];
|
|
199
|
+
/**
|
|
200
|
+
* The `dataRegions` field of the `velt-deployment-profile.json` v1 document (additive
|
|
201
|
+
* 2026-07-10, GTK-005-safe): which regional `setencrypteddata*` variants the deployment
|
|
202
|
+
* provisioned. Inlined by the customer's tooling alongside {@link deploymentProfile}.
|
|
203
|
+
*
|
|
204
|
+
* - `undefined` / `null` — no region filter (all regional variants provisioned; the
|
|
205
|
+
* SaaS shape). `null` and `[]` are DIFFERENT fleets — never coalesce them.
|
|
206
|
+
* - `[]` — ONLY the base `setencrypteddata` (in the deployment's own region) exists.
|
|
207
|
+
* - `['europe-west1', …]` — the base plus the variants for exactly those GCP regions
|
|
208
|
+
* (known: `europe-west1`, `asia-southeast1`, `australia-southeast1`,
|
|
209
|
+
* `asia-northeast1`).
|
|
210
|
+
*
|
|
211
|
+
* The SDK uses this as a pre-call provisioning check in
|
|
212
|
+
* `EndpointsService.getSetEncryptedDataUrl`: a tenant routed to an UNPROVISIONED
|
|
213
|
+
* regional variant degrades to the base `setEncryptedData` resolution instead of
|
|
214
|
+
* calling a URL that would 404.
|
|
215
|
+
*
|
|
216
|
+
* The filter is AUTHORITATIVE over injected per-region URLs (mirroring how a
|
|
217
|
+
* `deploymentProfile` opt-out wins over an injected endpoint URL): an injected
|
|
218
|
+
* `cloudFunction.regions[X]` override for a region excluded by `dataRegions` is
|
|
219
|
+
* never consulted — the write resolves through the base slot. Don't inject overrides
|
|
220
|
+
* for regions the deployment did not provision.
|
|
221
|
+
*/
|
|
222
|
+
dataRegions?: string[] | null;
|
|
69
223
|
}
|
|
70
224
|
export interface ProxyConfig {
|
|
71
225
|
/** Custom host for the Velt CDN (e.g., 'cdn-proxy.customer.com') */
|
|
@@ -28,6 +28,20 @@ export declare class NotificationRawData {
|
|
|
28
28
|
* Annotation object
|
|
29
29
|
*/
|
|
30
30
|
annotationData?: any;
|
|
31
|
+
/**
|
|
32
|
+
* Comment-visibility stamp for private comments
|
|
33
|
+
* (PM-2026-07-28-private-comment-notification-leak). Absent = public (legacy).
|
|
34
|
+
* The backend enforces visibility from this stamp on the per-user notification
|
|
35
|
+
* fan-out and on every notification read path.
|
|
36
|
+
* - `accessTokens`: the annotation's hashed visibility tokens (authoritative match)
|
|
37
|
+
* - `userIds` / `organizationIds`: the readable mirror (client ids)
|
|
38
|
+
*/
|
|
39
|
+
visibility?: {
|
|
40
|
+
type: string;
|
|
41
|
+
userIds?: string[];
|
|
42
|
+
organizationIds?: string[];
|
|
43
|
+
accessTokens: string[];
|
|
44
|
+
};
|
|
31
45
|
/**
|
|
32
46
|
* Comment object for comment annotation
|
|
33
47
|
*/
|
|
@@ -98,8 +98,24 @@ export interface TargetEditDetails<T = unknown> {
|
|
|
98
98
|
* auto-commit so a subscriber to `targetEditCommit` can drive it explicitly.
|
|
99
99
|
*/
|
|
100
100
|
export interface TargetEditCommitResult {
|
|
101
|
-
/**
|
|
101
|
+
/**
|
|
102
|
+
* Override the SDK's default diff summary (`Replace: "{old}" with "{new}"`;
|
|
103
|
+
* `Add:`/`Remove:` when one side is absent; a per-key op list when both
|
|
104
|
+
* values are plain objects). When provided without `summaryHtml`, it is
|
|
105
|
+
* used for BOTH the plain `commentText` and (escaped) the `commentHtml`
|
|
106
|
+
* of the seeded first comment.
|
|
107
|
+
*/
|
|
102
108
|
summary?: string;
|
|
109
|
+
/**
|
|
110
|
+
* Optional HTML version of the summary, used as the `commentHtml` of the
|
|
111
|
+
* suggestion's seeded first comment (the plain `summary` — or the SDK's
|
|
112
|
+
* default diff summary — stays in `commentText`). When BOTH are omitted,
|
|
113
|
+
* the SDK renders a default styled HTML diff (old/removed values in red
|
|
114
|
+
* italic, new/added values in green italic). Sanitized with DOMPurify at
|
|
115
|
+
* render time — script/event-handler content is stripped; inline `style`
|
|
116
|
+
* attributes are preserved.
|
|
117
|
+
*/
|
|
118
|
+
summaryHtml?: string;
|
|
103
119
|
/** Customer metadata persisted on the resulting Suggestion. */
|
|
104
120
|
metadata?: Record<string, unknown>;
|
|
105
121
|
}
|
|
@@ -134,6 +150,24 @@ export interface EnableSuggestionModeConfig {
|
|
|
134
150
|
* to event subscribers.
|
|
135
151
|
*/
|
|
136
152
|
onTargetEditCommit?: TargetEditCommitHandler;
|
|
153
|
+
/**
|
|
154
|
+
* When active AND no `onTargetEditCommit` handler is provided, every
|
|
155
|
+
* detected commit auto-commits with the SDK's default summary/summaryHtml
|
|
156
|
+
* (equivalent to a handler returning `{}`).
|
|
157
|
+
*
|
|
158
|
+
* **Default: true** — a bare `enableSuggestionMode()` turns edits into
|
|
159
|
+
* suggestions with zero config. Pass `autoCommit: false` for detect-only
|
|
160
|
+
* mode (events fire, nothing commits until a subscriber calls the event's
|
|
161
|
+
* `commitSuggestion` builder).
|
|
162
|
+
*
|
|
163
|
+
* A provided `onTargetEditCommit` handler always wins — including its
|
|
164
|
+
* null-return deferral contract — so handler-based integrations are
|
|
165
|
+
* unaffected. The `targetEditCommit` event still fires; its pre-bound
|
|
166
|
+
* `commitSuggestion` builder becomes a no-op for edits already
|
|
167
|
+
* auto-committed by this flag (same double-commit guard as the handler
|
|
168
|
+
* path).
|
|
169
|
+
*/
|
|
170
|
+
autoCommit?: boolean;
|
|
137
171
|
}
|
|
138
172
|
/**
|
|
139
173
|
* SDK-managed suggestion data persisted on a CommentAnnotation.
|
|
@@ -245,8 +279,24 @@ export interface CommitSuggestionConfig<T = unknown> {
|
|
|
245
279
|
targetId: string;
|
|
246
280
|
/** Any JSON-serializable value. Customer's apply handler interprets it. */
|
|
247
281
|
newValue: T;
|
|
248
|
-
/**
|
|
282
|
+
/**
|
|
283
|
+
* Optional human-readable string for logs and notifications. When provided
|
|
284
|
+
* without `summaryHtml`, it is used for BOTH the seeded comment's plain
|
|
285
|
+
* `commentText` and (escaped) its `commentHtml`. When omitted, the seeded
|
|
286
|
+
* comment falls back to the SDK's default diff summary
|
|
287
|
+
* (`Replace: "{old}" with "{new}"`; `Add:`/`Remove:` when one side is
|
|
288
|
+
* absent; a per-key op list when both values are plain objects).
|
|
289
|
+
*/
|
|
249
290
|
summary?: string;
|
|
291
|
+
/**
|
|
292
|
+
* Optional HTML version of the summary — becomes the `commentHtml` of the
|
|
293
|
+
* suggestion's seeded first comment (plain `summary` or the default diff
|
|
294
|
+
* summary stays in `commentText`). When BOTH are omitted, the SDK renders
|
|
295
|
+
* a default styled HTML diff (old/removed values in red italic, new/added
|
|
296
|
+
* values in green italic). Sanitized with DOMPurify at render time; inline
|
|
297
|
+
* `style` attributes are preserved so rich diff styling survives.
|
|
298
|
+
*/
|
|
299
|
+
summaryHtml?: string;
|
|
250
300
|
/** Optional customer-defined metadata. Stored on Suggestion.metadata. */
|
|
251
301
|
metadata?: Record<string, unknown>;
|
|
252
302
|
}
|
package/app/utils/constants.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export declare class Constants {
|
|
|
12
12
|
static LISTENER_CONTEXT_BATCH_SIZE: number;
|
|
13
13
|
static DEFAULT_VELT_CONTEXT: string;
|
|
14
14
|
static VISIBILITY_SELF_PREFIX: string;
|
|
15
|
+
static VISIBILITY_ORG_PREFIX: string;
|
|
15
16
|
static FIREBASE_PARTIAL_PATH_ORGANIZATIONS: string;
|
|
16
17
|
static FIREBASE_PARTIAL_PATH_FOLDERS: string;
|
|
17
18
|
static FIREBASE_PARTIAL_PATH_DOCS: string;
|
package/app/utils/enums.d.ts
CHANGED
|
@@ -100,6 +100,7 @@ export declare const CommentEventTypes: {
|
|
|
100
100
|
readonly SIDEBAR_BUTTON_CLICKED: "sidebarButtonClicked";
|
|
101
101
|
readonly SIDEBAR_OPEN: "sidebarOpen";
|
|
102
102
|
readonly SIDEBAR_CLOSE: "sidebarClose";
|
|
103
|
+
readonly FULLSCREEN_CLICK: "fullscreenClick";
|
|
103
104
|
readonly COMMENT_CLICK: "commentClick";
|
|
104
105
|
readonly COMMENT_NAVIGATION_BUTTON_CLICK: "commentNavigationButtonClick";
|
|
105
106
|
readonly ATTACHMENT_DOWNLOAD_CLICKED: "attachmentDownloadClicked";
|
|
@@ -332,7 +333,7 @@ export type RecorderType = 'audio' | 'video' | 'screen';
|
|
|
332
333
|
export type RecorderFileFormat = 'mp3' | 'mp4' | 'webm';
|
|
333
334
|
export type RecorderLayoutMode = 'floating' | 'thread';
|
|
334
335
|
export type SupportedMimeType = 'audio' | 'video';
|
|
335
|
-
export type FirebaseRegion = 'usCentral1' | 'asiaSouthEast1' | 'europeWest1' | 'australiaSouthEast1';
|
|
336
|
+
export type FirebaseRegion = 'usCentral1' | 'asiaSouthEast1' | 'europeWest1' | 'australiaSouthEast1' | 'asiaNorthEast1';
|
|
336
337
|
export type VideoEventType = 'play' | 'pause' | 'ratechange' | 'seeked' | 'timeupdate' | 'volumechange';
|
|
337
338
|
export type RewriterType = 'copywriter' | 'generic';
|
|
338
339
|
export type RecorderStatusType = 'started' | 'paused' | 'resumed' | 'stopped' | 'error' | null;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
import{ca as ie}from"./chunk-RF3TL6SQ.js";import{$ as K,$e as R,Cf as $,Ch as E,Df as _,Dh as V,Ee as N,Ef as A,Ff as T,Fi as Q,Gi as ee,Hi as re,L as w,Mf as L,Od as W,Pi as se,Vf as M,_e as U,a as f,af as I,b as y,be as v,ca as P,da as x,g,ki as X,l as D,li as q,oi as H,qh as b,qi as Y,tf as S,th as j,ti as Z,uf as l,uh as B,v as G,wh as J,xh as z,zh as F}from"./chunk-3YCIOKO7.js";var p="public",ye=(()=>{let O=class O{constructor(e,r,s,i,t,o,c,a,n,d){this.authService=e,this.docService=r,this.loggingService=s,this.commonDbService=i,this.usersService=t,this.commentUtilsService=o,this.coreActionsService=c,this.functions=a,this.configService=n,this.contactService=d,this.endpointsService=x(H),this.currentUserPermissions$=new D(null),this.permissionsCache$=new D(null),this.permissionProvider$=new D(null),this.clientResolverProdWarned=!1,this.clientResolverNoResolverWarned=!1,this.requestKeyedPermissionsCache=new Map,this.inFlightPermissionsRequests=new Map,this.permissionsCacheGeneration=0,this.REVOKE_DELAY_MS=3e3,this.pendingRevokeRequests=new Map,this.pendingRevokeTimeoutId=null,this.pendingRevokeUniqueId="",this.pendingRevokeUserId="";try{this.docService.setUserPermissionService(this),this.authService.setUserPermissionService(this),this.commentUtilsService.setUserPermissionService(this),this.contactService.setUserPermissionService(this)}catch(h){this.loggingService.catch("Error in UserPermissionService constructor:",h)}}ngOnDestroy(){try{this.pendingRevokeTimeoutId&&(clearTimeout(this.pendingRevokeTimeoutId),this.pendingRevokeTimeoutId=null)}catch(e){this.loggingService.catch("Error in UserPermissionService ngOnDestroy:",e)}}collectRevokeRequest(e,r,s,i,t,o){try{return e.find(a=>a.resourceId===s&&a.type===i&&a.organizationId===t&&a.userId===o)?(r.push({userId:o,resourceId:s,organizationId:t,type:i,hasAccess:!1}),e.filter(a=>!(a.resourceId===s&&a.type===i&&a.organizationId===t&&a.userId===o))):e}catch(c){return this.loggingService.catch("Error in UsersPermissionService collectRevokeRequest:",c),e}}hasUserContextAccess({userId:e,accessFields:r}){try{if(!this.getIsContextEnabled()||r.includes(N.DEFAULT_VELT_CONTEXT))return!0;let s=r.filter(t=>!L(t));if(!s.length){if(r.some(c=>c.startsWith(N.VISIBILITY_ORG_PREFIX)))return!0;let o=`${N.VISIBILITY_SELF_PREFIX}${$(e).toString()}`;return r.includes(o)}let i=this.contactService.getUserAccessFieldsByUserId(e);return i?.length?s.every(t=>i.includes(t)):!0}catch(s){return this.loggingService.catch("Error in UserPermissionService hasUserContextAccess:",s),!1}}organizationDetails(e){return g(this,null,function*(){try{let r=yield this.commonDbService?.getData({feature:"organizationMetadata",properties:{organizationId:e,suppressError:!0}});return r&&r?.errorCode?{errorCode:l.PERMISSION_DENIED,error:!0}:r&&!r?.metadata?{errorCode:l.DOES_NOT_EXIST,error:!0}:{error:!1}}catch(r){return this.loggingService.catch("Error in UserPermissionService organizationDetails:",r),{errorCode:l.SOMETHING_WENT_WRONG,error:!0}}})}documentDetails(s){return g(this,arguments,function*({documentId:e,organizationId:r}){try{let i=yield this.commonDbService?.getData({feature:"documentMetadata",properties:{documentId:e,organizationId:r,suppressError:!0}});if(i&&i?.errorCode)return{errorCode:l.PERMISSION_DENIED,error:!0};if(i&&!i?.metadata)return{errorCode:l.DOES_NOT_EXIST,error:!0};let t=this.docService.getDocumentMetadata(e)??{};this.docService.setDocumentMetadata(e,f(f({},t),i?.metadata??{}));let o,c=i?.metadata?.veltFolderId;if(c)try{o=(yield this.commonDbService?.getData({feature:"folderMetadata",properties:{folderId:c,organizationId:r}}))?.folderIamConfig?.accessType}catch(a){this.loggingService.catch("Error fetching folder accessType for document:",a)}return o||(o=i?.docIamConfig?.accessType),{error:!1,accessType:o}}catch(i){return this.loggingService.catch("Error in UserPermissionService documentDetails:",i),{errorCode:l.SOMETHING_WENT_WRONG,error:!0}}})}folderDetails(s){return g(this,arguments,function*({folderId:e,organizationId:r}){try{let i=yield this.commonDbService?.getData({feature:"folderMetadata",properties:{folderId:e,organizationId:r,suppressError:!0}});return i&&i?.errorCode?{errorCode:l.PERMISSION_DENIED,error:!0}:i&&!i?.metadata?{errorCode:l.DOES_NOT_EXIST,error:!0}:{error:!1,accessType:i?.folderIamConfig?.accessType}}catch(i){return this.loggingService.catch("Error in UserPermissionService folderDetails:",i),{errorCode:l.SOMETHING_WENT_WRONG,error:!0}}})}getUserPermissions(e){return g(this,null,function*(){let r=this.permissionsCacheGeneration;try{if(!this.authService.getUser())return this.loggingService.catch("User not set. [source: getUserPermissions]",void 0,void 0,!0),{};let s=this.authService.getUser()?.userId,i=this.extractResourceIds(e);if(!i.clientOrganizationId||!i.organizationId)return this.loggingService.catch("Client organization id or organization id not set during getUserPermissions",void 0,void 0,!0),{};let t=yield this.validateResources(i),[o,c]=yield this.fetchUserPermissionsFromDB(i),a=this.authService.getUser()?.userId;if(s!==a)return{};let n=this.buildPermissionsResponse(i,t,o,c);if(Object.keys(n).length>0){if(!e)this.setCurrentUserPermissions(n);else if(this.permissionsCacheGeneration===r){let d=this.buildPermissionsCacheKey(e);d!==null&&this.requestKeyedPermissionsCache.set(d,JSON.parse(JSON.stringify(n)))}}return n}catch(s){return this.loggingService.catch("Error in UserPermissionService getUserPermissions:",s),{}}})}getUserPermissionsFromCacheOrFetch(e){return g(this,null,function*(){try{if(!e)return yield this.getUserPermissions(e);let r=this.buildPermissionsCacheKey(e);if(r===null)return yield this.getUserPermissions(e);let s=this.permissionsCacheGeneration,i=this.requestKeyedPermissionsCache.get(r);if(i)return JSON.parse(JSON.stringify(i));let t=this.inFlightPermissionsRequests.get(r);if(t){let a=yield t;return this.permissionsCacheGeneration!==s?yield this.getUserPermissions(e):JSON.parse(JSON.stringify(a))}let o=this.getUserPermissions(e);this.inFlightPermissionsRequests.set(r,o),o.finally(()=>{this.inFlightPermissionsRequests.get(r)===o&&this.inFlightPermissionsRequests.delete(r)}).catch(()=>{});let c=yield o;return this.permissionsCacheGeneration!==s?yield this.getUserPermissions(e):JSON.parse(JSON.stringify(c))}catch(r){return this.loggingService.catch("Error in UserPermissionService getUserPermissionsFromCacheOrFetch:",r),{}}})}clearRequestKeyedPermissionsCache(){try{this.requestKeyedPermissionsCache.clear(),this.inFlightPermissionsRequests.clear(),this.permissionsCacheGeneration++}catch(e){this.loggingService.catch("Error in UserPermissionService clearRequestKeyedPermissionsCache:",e)}}invalidateAllPermissionsState(){try{this.requestKeyedPermissionsCache.clear(),this.inFlightPermissionsRequests.clear(),this.permissionsCacheGeneration++}catch(e){this.loggingService.catch("Error in UserPermissionService invalidateAllPermissionsState:",e)}}buildPermissionsCacheKey(e){try{let r={};return Object.keys(e).sort().forEach(s=>{let i=e[s];i!==void 0&&(r[s]=Array.isArray(i)?[...i].sort():i)}),r.__userId=this.authService.getUser()?.userId??null,JSON.stringify(r)}catch(r){return this.loggingService.catch("Error in UserPermissionService buildPermissionsCacheKey:",r),null}}extractResourceIds(e){let r=this.docService.getDocumentPaths(),s=this.docService.getDocumentIds();if(e){let o=e.organizationId??r?.clientOrganizationId;return{folderIds:e.folderIds??[],documentIds:e.documentIds??[],clientOrganizationId:o,organizationId:o?A(o):void 0}}let i=r?.clientOrganizationId;return{folderIds:r?.folderId?[r.folderId]:[],documentIds:s.map(o=>o.clientDocumentId),clientOrganizationId:i,organizationId:i?A(i):void 0}}validateResources(e){return g(this,null,function*(){let{folderIds:r,documentIds:s,organizationId:i,clientOrganizationId:t}=e,o=[],c=[],a=r.length>0||s.length>0;i&&!a&&(o.push(this.organizationDetails(i)),c.push({id:t??"",type:"organization"})),r.forEach(u=>{o.push(this.folderDetails({folderId:T(u),organizationId:i??""})),c.push({id:u,type:"folder"})}),s.forEach(u=>{o.push(this.documentDetails({documentId:_(u),organizationId:i??""})),c.push({id:u,type:"document"})});let[n,d]=yield Promise.all([Promise.allSettled(o),this.getDefaultDocumentAccessType()]),h=this.processValidationResults(n,c);return y(f({},this.suppressResolverGrantedFailures(h,t)),{defaultDocumentAccessType:d})})}suppressResolverGrantedFailures(e,r){try{let s=this.authService.getUser()?.userId;if(!s)return e;let i=this.getPermissionsCache()??[];if(i.length===0)return e;let t=(n,d,h)=>i.some(u=>u?.userId===s&&u?.resourceId===n&&u?.type===d&&(!h||u?.organizationId===h)&&u?.hasAccess===!0),o=e.failedDocumentIds.filter(n=>!(n.errorCode===l.PERMISSION_DENIED&&t(n.id,I.DOCUMENT,r))),c=e.failedFolderIds.filter(n=>!(n.errorCode===l.PERMISSION_DENIED&&t(n.id,I.FOLDER,r))),a=e.failedOrganizationId;return a&&a.errorCode===l.PERMISSION_DENIED&&r&&t(r,I.ORGANIZATION,r)&&(a=void 0),{failedFolderIds:c,failedDocumentIds:o,failedOrganizationId:a,folderAccessTypes:e.folderAccessTypes,documentAccessTypes:e.documentAccessTypes}}catch(s){return this.loggingService.catch("Error in UserPermissionService suppressResolverGrantedFailures:",s),e}}getDefaultDocumentAccessType(){return g(this,null,function*(){try{return(yield this.commonDbService?.getData({feature:"apiKeyMetadata",properties:{}}))?.defaultDocumentAccessType}catch(e){this.loggingService.catch("Error fetching defaultDocumentAccessType:",e);return}})}processValidationResults(e,r){let s=[],i=[],t,o={},c={};for(let a=0;a<e.length;a++){let n=e[a],d=r[a];if(n.status==="rejected"||n.status==="fulfilled"&&n.value.error){let u=n.status==="fulfilled"?n.value.errorCode??l.SOMETHING_WENT_WRONG:l.SOMETHING_WENT_WRONG,m={id:d.id,errorCode:u};switch(d.type){case"organization":if(t=m,u===l.DOES_NOT_EXIST)throw new Error(`Organization with id '${d.id}' does not exist`);break;case"folder":s.push(m);break;case"document":i.push(m);break}}else if(n.status==="fulfilled")switch(d.type){case"folder":n.value.accessType&&(o[d.id]=n.value.accessType);break;case"document":n.value.accessType&&(c[d.id]=n.value.accessType);break}}return{failedFolderIds:s,failedDocumentIds:i,failedOrganizationId:t,folderAccessTypes:o,documentAccessTypes:c}}fetchUserPermissionsFromDB(e){return g(this,null,function*(){let{folderIds:r,documentIds:s,organizationId:i}=e,t=[this.authService.getUser()?.userId??""],o=[...r.map(n=>T(n)),...s.map(n=>_(n)),i??""],[c,a]=yield Promise.allSettled([this.usersService.getUsersFromDBWithBatching({userIds:t,organizationId:i}),this.usersService.getTemporaryUsersFromDBWithBatching({userIds:t,organizationId:i,resourceIds:o})]);return[c.status==="fulfilled"?c.value:[],a.status==="fulfilled"?a.value:[]]})}buildPermissionsResponse(e,r,s,i){let{folderIds:t,documentIds:o,clientOrganizationId:c,organizationId:a}=e,{failedFolderIds:n,failedDocumentIds:d,failedOrganizationId:h}=r,u={};return this.processRegularUserPermissions(u,s,t,o,c??"",a??"",n,d,h,r.folderAccessTypes,r.documentAccessTypes,r.defaultDocumentAccessType),this.ensureCurrentUserFailuresRecorded(u,c??"",n,d,h,r.folderAccessTypes,r.documentAccessTypes,r.defaultDocumentAccessType),this.processTemporaryUserPermissions(u,i),this.processContextPermissions(u),u}processContextPermissions(e){try{let r=this.authService.getUser()?.userId;if(r){let s=this.contactService.getUserAccessFieldsByUserId(r);s?.length&&(e[r]||(e[r]={}),e[r].context={accessFields:s})}}catch(r){this.loggingService.catch("Error in UserPermissionService processContextPermissions:",r);return}}processRegularUserPermissions(e,r,s,i,t,o,c,a,n,d,h,u){for(let m of r)for(let C of m)C?.user?.userId&&(e[C.user.userId]=y(f({},s.length&&{folders:this.buildFolderPermissions(s,C,c,d,u)}),{documents:this.buildDocumentPermissions(i,C,a,h,u),organization:{[t]:this.buildOrganizationPermission(o,C,n)}}))}ensureCurrentUserFailuresRecorded(e,r,s,i,t,o,c,a){try{let n=this.authService.getUser()?.userId;if(!n)return;let d=!!t&&!!r,h=(s?.length??0)>0,u=(i?.length??0)>0;if(!d&&!h&&!u)return;if(e[n]||(e[n]={}),d&&(e[n].organization||(e[n].organization={}),e[n].organization[r]||(e[n].organization[r]={error:this.getErrorMessage(t.errorCode,"organization"),errorCode:t.errorCode})),h){e[n].folders||(e[n].folders={});for(let m of s)e[n].folders[m.id]||(e[n].folders[m.id]=f({error:this.getErrorMessage(m.errorCode,"folder"),errorCode:m.errorCode},m.errorCode===l.PERMISSION_DENIED&&{accessType:o[m.id]??a??p}))}if(u){e[n].documents||(e[n].documents={});for(let m of i)e[n].documents[m.id]||(e[n].documents[m.id]=f({error:this.getErrorMessage(m.errorCode,"document"),errorCode:m.errorCode},m.errorCode===l.PERMISSION_DENIED&&{accessType:c[m.id]??a??p}))}}catch(n){this.loggingService.catch("Error in UserPermissionService ensureCurrentUserFailuresRecorded:",n)}}getErrorMessage(e,r){try{switch(this.loggingService.log(`Error in UserPermissionService getErrorMessage: ${e} ${r}`),e){case l.DOES_NOT_EXIST:return`${r} does not exist`;case l.PERMISSION_DENIED:return`User does not have access to ${r}`;case l.SOMETHING_WENT_WRONG:return"Something went wrong";default:return"Something went wrong"}}catch(s){return this.loggingService.catch("Error in UserPermissionService getErrorMessage:",s),"Something went wrong"}}buildFolderPermissions(e,r,s,i,t){return e.reduce((o,c)=>{let a=s.find(n=>n.id===c);return a?o[c]=f({error:this.getErrorMessage(a.errorCode,"folder"),errorCode:a.errorCode},a.errorCode===l.PERMISSION_DENIED&&{accessType:i[c]??t??p}):o[c]={accessRole:r.viewerFolderIds?.includes(T(c))?S.VIEWER:S.EDITOR,accessType:i[c]??t??p},o},{})}buildDocumentPermissions(e,r,s,i,t){return e.reduce((o,c)=>{let a=s.find(n=>n.id===c);return a?o[c]=f({error:this.getErrorMessage(a.errorCode,"document"),errorCode:a.errorCode},a.errorCode===l.PERMISSION_DENIED&&{accessType:i[c]??t??p}):o[c]={accessRole:r.viewerDocumentIds?.includes(_(c))?S.VIEWER:S.EDITOR,accessType:i[c]??t??p},o},{})}buildOrganizationPermission(e,r,s){return s?{error:this.getErrorMessage(s.errorCode,"organization"),errorCode:s.errorCode}:{accessRole:r.viewerOrganizationIds?.includes(e)?S.VIEWER:S.EDITOR}}processTemporaryUserPermissions(e,r){for(let s of r)if(s?.userId)switch(this.ensureUserPermissionStructure(e,s.userId),s.type){case"folder":this.addTemporaryFolderPermission(e,s);break;case"document":this.addTemporaryDocumentPermission(e,s);break;case"organization":this.addTemporaryOrganizationPermission(e,s);break}}ensureUserPermissionStructure(e,r){e[r]||(e[r]={})}addTemporaryFolderPermission(e,r){let{userId:s,resourceId:i,role:t,expiresAt:o}=r;e[s].folders||(e[s].folders={}),e[s].folders[i]={accessRole:t??S.EDITOR,expiresAt:o}}addTemporaryDocumentPermission(e,r){let{userId:s,resourceId:i,role:t,expiresAt:o}=r;e[s].documents||(e[s].documents={}),e[s].documents[i]={accessRole:t??S.EDITOR,expiresAt:o}}addTemporaryOrganizationPermission(e,r){let{userId:s,resourceId:i,role:t,expiresAt:o}=r;e[s].organization||(e[s].organization={}),e[s].organization[i]={accessRole:t??S.EDITOR,expiresAt:o}}hasEditAccess({organizationId:e,folderId:r,documentId:s}){try{let i=!0,t=this.getCurrentUserPermissionsWithServerIds(),o=this.authService.getUser()?.userId??"";return t&&(e&&typeof e=="string"&&t?.[o]?.organization?.[e]&&(t?.[o]?.organization?.[e]?.accessRole===S.VIEWER||t?.[o]?.organization?.[e]?.errorCode===l.PERMISSION_DENIED)&&(i=!1),r&&typeof r=="string"&&t?.[o]?.folders?.[r]&&(t?.[o]?.folders?.[r]?.accessRole===S.VIEWER||t?.[o]?.folders?.[r]?.errorCode===l.PERMISSION_DENIED)&&(i=!1),s&&typeof s=="string"&&t?.[o]?.documents?.[s]&&(t?.[o]?.documents?.[s]?.accessRole===S.VIEWER||t?.[o]?.documents?.[s]?.errorCode===l.PERMISSION_DENIED)&&(i=!1)),i}catch{return!0}}getCurrentUserPermissions$(){return this.currentUserPermissions$.asObservable().pipe(w(b))}getCurrentUserPermissions(){return this.currentUserPermissions$.value}refactorPermissionsWithServerIds(e){try{let r=JSON.parse(JSON.stringify(e??{})),s=this.authService.getUser()?.userId??"";if(r?.[s]){let i=this.docService.getDocumentPaths()?.clientOrganizationId??"";if(r?.[s]?.organization?.[i]){let t=A(i);r[s].organization&&(r[s].organization[t]=r[s].organization[i],delete r[s].organization[i])}r?.[s]?.folders&&(r[s].folders=Object.fromEntries(Object.entries(r?.[s]?.folders??{}).map(([t,o])=>[T(t),o]))),r?.[s]?.documents&&(r[s].documents=Object.fromEntries(Object.entries(r?.[s]?.documents??{}).map(([t,o])=>[_(t),o])))}return r}catch(r){return this.loggingService.catch("Error in UsersPermissionService refactorPermissionsWithServerIds:",r),e}}getCurrentUserPermissionsWithServerIds$(){return this.currentUserPermissions$.asObservable().pipe(G(e=>this.refactorPermissionsWithServerIds(e)),w(b))}getCurrentUserPermissionsWithServerIds(){return this.refactorPermissionsWithServerIds(this.currentUserPermissions$.value)}setCurrentUserPermissions(e){try{this.loggingService.log("%c[WB] Calling UsersService FUNCTION: setCurrentUserPermissions","color: green;");let r=null;e&&(r=JSON.parse(JSON.stringify(e))),this.currentUserPermissions$.next(r)}catch(r){this.loggingService.catch("Error in UsersPermissionService setCurrentUserPermissions:",r)}}getIsContextEnabled(){return this.loggingService.log("%c[WB] Calling FUNCTION: getIsContextEnabled","color: green;"),this.permissionProvider$.value?.isContextEnabled??!1}setPermissionProvider(e){try{this.loggingService.log("%c[WB] Calling UsersService FUNCTION: setPermissionProvider","color: green;"),this.clientResolverProdWarned=!1,this.clientResolverNoResolverWarned=!1,this.permissionProvider$.next(e)}catch(r){this.loggingService.catch("Error in UsersPermissionService setPermissionProvider:",r)}}get isRevokeAccessOnDocumentUnsetEnabled(){return this.permissionProvider$.value?.revokeAccessOn?.some(e=>e.type===U.DOCUMENT_UNSET)??!1}get isRevokeAccessOnUserLogoutEnabled(){return this.permissionProvider$.value?.revokeAccessOn?.some(e=>e.type===U.USER_LOGOUT)??!1}get isRevokeOrganizationAccessOnUserLogoutEnabled(){return this.permissionProvider$.value?.revokeAccessOn?.some(e=>e.type===U.USER_LOGOUT&&e.revokeOrganizationAccess)??!1}get isRevokeOrganizationAccessOnDocumentUnsetEnabled(){return this.permissionProvider$.value?.revokeAccessOn?.some(e=>e.type===U.DOCUMENT_UNSET&&e.revokeOrganizationAccess)??!1}getPermissionProviderRetryConfig(){return this.permissionProvider$.value?.retryConfig??{retryCount:0,retryDelay:0}}revokeAccessOnUserLogout(){return g(this,null,function*(){let e=M();try{if(this.isRevokeAccessOnUserLogoutEnabled){let r=[],s=this.authService.getUser()?.userId??"";if((this.getPermissionsCache()??[]).forEach(t=>{t.userId===s&&t.hasAccess&&(t.type===I.ORGANIZATION?this.isRevokeOrganizationAccessOnUserLogoutEnabled&&r.push(y(f({},t),{hasAccess:!1})):r.push(y(f({},t),{hasAccess:!1})))}),r.length>0){this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_USER_LOGOUT_FORMED,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_USER_LOGOUT,source:"internal",payload:{requests:r}}),this.setPermissionsCache([]),this.clearRequestKeyedPermissionsCache(),this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_USER_LOGOUT_TRIGGERED,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_USER_LOGOUT,source:"internal",payload:{requests:r}});let t=yield this.revokeAccess({requests:r,userId:this.authService.getUser()?.userId??""});t.success?this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_USER_LOGOUT_RESULT,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_USER_LOGOUT,source:"internal",payload:{result:{data:t,success:!0,statusCode:200}}}):this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_USER_LOGOUT_ERROR,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_USER_LOGOUT,source:"internal",payload:{result:{data:t,success:!1,statusCode:500}}})}}}catch(r){this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_USER_LOGOUT_ERROR,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_USER_LOGOUT,source:"internal",payload:{error:r}}),this.loggingService.catch("Error in UsersPermissionService revokeAccessOnUserLogout:",r)}})}getRevokeKey(e){try{return`${e.userId}_${e.resourceId}_${e.type}_${e.organizationId}`}catch(r){return this.loggingService.catch("Error in UsersPermissionService getRevokeKey:",r),""}}cancelPendingRevokes(e){try{e.forEach(r=>{let s=this.getRevokeKey({userId:r.userId,resourceId:r.resource.id,type:r.resource.type,organizationId:r.resource.organizationId});this.pendingRevokeRequests.has(s)&&this.pendingRevokeRequests.delete(s)}),this.pendingRevokeRequests.size===0&&this.pendingRevokeTimeoutId&&(clearTimeout(this.pendingRevokeTimeoutId),this.pendingRevokeTimeoutId=null)}catch(r){this.loggingService.catch("Error in UsersPermissionService cancelPendingRevokes:",r)}}flushPendingRevokes(){return g(this,null,function*(){let e=this.pendingRevokeUniqueId,r=this.pendingRevokeUserId;try{let s=Array.from(this.pendingRevokeRequests.values());if(this.pendingRevokeRequests.clear(),this.pendingRevokeTimeoutId=null,this.pendingRevokeUniqueId="",this.pendingRevokeUserId="",s.length===0)return;let i=this.getPermissionsCache()??[];s.forEach(c=>{i=i.filter(a=>!(a.resourceId===c.resourceId&&a.type===c.type&&a.organizationId===c.organizationId&&a.userId===c.userId))}),this.setPermissionsCache(i);let t=this.docService.getDocContext(),o=yield this.revokeAccess({requests:s,userId:r,currentContext:t});o.success?this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_RESULT,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{result:{data:o,success:!0,statusCode:200}}}):this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_ERROR,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{result:{data:o,success:!1,statusCode:500}}})}catch(s){this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_ERROR,timestamp:new Date().getTime(),uniqueId:e,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{error:s}}),this.loggingService.catch("Error in UsersPermissionService flushPendingRevokes:",s)}})}revokeAccessOnDocumentUnset(i){return g(this,arguments,function*({documentIds:e,folderId:r,context:s}){let t=M();try{if(this.isRevokeAccessOnDocumentUnsetEnabled){let o=[],c=this.docService.getOrganizationConfig()?.clientOrganizationId??"",a=this.authService.getUser()?.userId??"",n=this.getPermissionsCache()??[];e.forEach(d=>{n=this.collectRevokeRequest(n,o,d.clientDocumentId,I.DOCUMENT,c,a)}),r&&(n=this.collectRevokeRequest(n,o,r,I.FOLDER,c,a)),c&&this.isRevokeOrganizationAccessOnDocumentUnsetEnabled&&(n=this.collectRevokeRequest(n,o,c,I.ORGANIZATION,c,a)),s&&this.getIsContextEnabled()&&J({input:s}).forEach(h=>{let u=JSON.stringify(h.access);n=this.collectRevokeRequest(n,o,u,I.CONTEXT,c,a)}),this.setPermissionsCache(n),o.length>0&&(this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_FORMED,timestamp:new Date().getTime(),uniqueId:t,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{requests:o}}),this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_TRIGGERED,timestamp:new Date().getTime(),uniqueId:t,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{requests:o}}),o.forEach(d=>{this.pendingRevokeRequests.set(this.getRevokeKey(d),d)}),this.pendingRevokeUniqueId=t,this.pendingRevokeUserId=a,this.pendingRevokeTimeoutId&&clearTimeout(this.pendingRevokeTimeoutId),this.pendingRevokeTimeoutId=setTimeout(()=>this.flushPendingRevokes(),this.REVOKE_DELAY_MS))}}catch(o){this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.REVOKE_ACCESS_ON_DOCUMENT_UNSET_ERROR,timestamp:new Date().getTime(),uniqueId:t,methodName:R.REVOKE_ACCESS_ON_DOCUMENT_UNSET,source:"internal",payload:{error:o}}),this.loggingService.catch("Error in UsersPermissionService revokeAccessOnDocumentUnset:",o)}})}getAccess(s){return g(this,arguments,function*({requests:e,userId:r}){let i={retryConfig:this.getPermissionProviderRetryConfig()};return this.isClientDevResolverActive()?i.clientResolvedResults=yield this.resolveClientSide(e):this.getPermissionProvider()?.dev&&this.warnNoResolverOnce(),this.sendGetAccessToProxy({requests:e,userId:r,metadata:i})})}sendGetAccessToProxy(i){return g(this,arguments,function*({requests:e,userId:r,metadata:s}){let t=V(this.functions,F({url:this.endpointsService.getCloudFunctionUrl("sdkProxy"),apiProxyDomain:this.configService?.getApiProxyDomain()}));return yield z({methodName:"getAccess",data:{type:"getAccess",data:e,metadata:s},getSdkProxy:t,userId:r})})}isClientDevResolverActive(){return!!this.getPermissionProvider()?.dev&&this.isClientDevResolverConfigured()}resolveClientSidePermissions(e){return g(this,null,function*(){if(!this.isClientDevResolverActive())throw new Error("Client-side dev permission resolver is not active");return this.resolveClientSide(e)})}isClientDevResolverConfigured(){let e=this.getPermissionProvider();return e?!!e.endpointConfig?.url?.trim()||typeof e.resolvePermissions=="function":!1}resolveClientSide(e){return g(this,null,function*(){this.warnClientResolverEnabledOnce();let r=this.getPermissionProvider(),s=this.getPermissionProviderRetryConfig(),i=r?.resolveTimeout??6e4,t=yield j(()=>this.withResolverTimeout(()=>this.invokeResolver(e,r),i),"clientPermissionResolver",{retryCount:s?.retryCount??0,retryDelay:s?.retryDelay??0});if(!t||!t.success||t.statusCode!==200)throw new Error(t?.message??"Client permission resolver failed");let o=t.data;if(!Array.isArray(o))throw new Error("Client permission resolver returned a malformed payload");return o})}invokeResolver(e,r){return g(this,null,function*(){let s={data:{requests:e}},i=r.endpointConfig?.url?.trim();if(i)return B(i,r.endpointConfig?.headers,s,!0,r.endpointConfig?.credentials);let t=yield r.resolvePermissions(s);if(Array.isArray(t))return{data:t,success:!0,statusCode:200};let o=t,c=o?.statusCode??(o?.success===!1?500:200),a=o?.success!==!1&&c===200;return{data:Array.isArray(o?.data)?o.data:void 0,success:a,statusCode:a?200:c===200?500:c,message:o?.message}})}withResolverTimeout(e,r){return g(this,null,function*(){if(!r||r<=0)return e();let s,i=new Promise((t,o)=>{s=setTimeout(()=>o(new Error("Client permission resolver timed out")),r)});try{return yield Promise.race([e(),i])}finally{s&&clearTimeout(s)}})}warnClientResolverEnabledOnce(){this.clientResolverProdWarned||(this.clientResolverProdWarned=!0,console.warn("[Velt] Client-side dev permission resolver is enabled (dev: true). Permissions are resolved in the browser for local development only \u2014 DO NOT use this in production. Production API keys ignore browser-resolved results and fall back to the server-side permission provider."))}warnNoResolverOnce(){this.clientResolverNoResolverWarned||(this.clientResolverNoResolverWarned=!0,console.warn("[Velt] setPermissionProvider was called with dev: true but no endpointConfig.url or resolvePermissions callback was provided. Falling back to the server-side permission provider."))}revokeAccess(i){return g(this,arguments,function*({requests:e,userId:r,currentContext:s}){let t=V(this.functions,F({url:this.endpointsService.getCloudFunctionUrl("sdkProxy"),apiProxyDomain:this.configService?.getApiProxyDomain()}));return yield z({methodName:"revokeAccess",data:{type:"revokeAccess",data:e,metadata:f({retryConfig:this.getPermissionProviderRetryConfig()},s?.access&&{currentContext:s})},getSdkProxy:t,userId:r})})}onResourceAccessRequired(o){return g(this,arguments,function*({requests:e,uniqueId:r,methodName:s,userId:i,fromCache:t=!0}){try{if(!e?.length)return;let c=[],a=this.getPermissionsCache()??[];if(!this.forceRefreshPermissions()&&t&&(e.forEach(n=>{let d=a?.find(h=>h.resourceId===n.resource.id&&h.type===n.resource.type&&h.userId===n.userId&&h.organizationId===n.resource.organizationId);d&&c.push(d)}),c.length>0&&(e=e.filter(n=>!c.find(d=>d.resourceId===n.resource.id&&d.type===n.resource.type&&d.userId===n.userId&&d.organizationId===n.resource.organizationId)))),e.length>0){this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.RESOURCE_ACCESS_REQUEST_TRIGGERED,timestamp:new Date().getTime(),uniqueId:r,methodName:s,source:"internal",payload:{requests:e,fromCache:t,clientResolved:this.isClientDevResolverActive()}});let n=yield this.getAccess({requests:e,userId:this.authService.getUser()?.userId??i??""});return this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.RESOURCE_ACCESS_RESULT,timestamp:new Date().getTime(),uniqueId:r,methodName:s,source:"internal",payload:{result:n,clientResolved:this.isClientDevResolverActive()}}),n?.success&&n?.data?.length&&(this.setPermissionsCache([...a,...n.data]),n.data=[...c,...n.data]),n}else if(c.length>0)return this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.RESOURCE_ACCESS_RESULT_FROM_CACHE,timestamp:new Date().getTime(),methodName:s,source:"internal",uniqueId:r,payload:{results:{data:c,success:!0,statusCode:200}}}),{data:c,success:!0,statusCode:200};return}catch(c){this.loggingService.catch("Error in UsersPermissionService onResourceAccessRequired:",c),this.coreActionsService.triggerAction(v.PERMISSION_PROVIDER,{event:E.Events.PermissionProvider.RESOURCE_ACCESS_ERROR,timestamp:new Date().getTime(),methodName:s,source:"internal",uniqueId:r,payload:{error:c,requests:e,fromCache:t}});return}})}getPermissionsCache(){return this.forceRefreshPermissions()?[]:this.permissionsCache$.getValue()}forceRefreshPermissions(){return this.getPermissionProvider()?.forceRefresh??!1}setPermissionsCache(e){try{let r=new Map;e.forEach(i=>{let t=`${i.userId}_${i.resourceId}_${i.organizationId}_${i.type}`;r.set(t,i)});let s=JSON.parse(JSON.stringify(Array.from(r.values())));this.permissionsCache$.next(s)}catch(r){this.loggingService.catch("Error in UsersPermissionService setPermissionsCache:",r)}}isPermissionProviderAvailable(){try{return!!this.permissionProvider$.getValue()}catch(e){return this.loggingService.catch("Error in UsersPermissionService isPermissionProviderAvailable:",e),!1}}getPermissionProvider(){try{return this.permissionProvider$.getValue()}catch(e){return this.loggingService.catch("Error in UsersPermissionService getPermissionProvider:",e),null}}getPermissionProvider$(){return this.permissionProvider$.asObservable()}};O.\u0275fac=function(r){return new(r||O)(P(Z),P(Q),P(X),P(se),P(ee),P(re),P(Y),P(W),P(q),P(ie))},O.\u0275prov=K({token:O,factory:O.\u0275fac,providedIn:"root"});let k=O;return k})();export{ye as a};
|