@uipath/uipath-typescript 1.3.10 → 1.4.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/agent-memory/index.cjs +1765 -0
- package/dist/agent-memory/index.d.ts +588 -0
- package/dist/agent-memory/index.mjs +1763 -0
- package/dist/agents/index.cjs +1726 -0
- package/dist/agents/index.d.ts +502 -0
- package/dist/agents/index.mjs +1724 -0
- package/dist/assets/index.cjs +155 -30
- package/dist/assets/index.d.ts +84 -5
- package/dist/assets/index.mjs +155 -30
- package/dist/attachments/index.cjs +37 -6
- package/dist/attachments/index.d.ts +1 -0
- package/dist/attachments/index.mjs +37 -6
- package/dist/buckets/index.cjs +37 -6
- package/dist/buckets/index.d.ts +1 -0
- package/dist/buckets/index.mjs +37 -6
- package/dist/cases/index.cjs +192 -10
- package/dist/cases/index.d.ts +208 -7
- package/dist/cases/index.mjs +192 -11
- package/dist/conversational-agent/index.cjs +124 -57
- package/dist/conversational-agent/index.d.ts +190 -122
- package/dist/conversational-agent/index.mjs +124 -57
- package/dist/core/index.cjs +413 -105
- package/dist/core/index.d.ts +15 -0
- package/dist/core/index.mjs +413 -105
- package/dist/entities/index.cjs +135 -70
- package/dist/entities/index.d.ts +146 -45
- package/dist/entities/index.mjs +135 -70
- package/dist/feedback/index.cjs +37 -6
- package/dist/feedback/index.d.ts +1 -0
- package/dist/feedback/index.mjs +37 -6
- package/dist/governance/index.cjs +1782 -0
- package/dist/governance/index.d.ts +598 -0
- package/dist/governance/index.mjs +1780 -0
- package/dist/index.cjs +1050 -291
- package/dist/index.d.ts +1313 -134
- package/dist/index.mjs +1050 -292
- package/dist/index.umd.js +4546 -3770
- package/dist/jobs/index.cjs +37 -6
- package/dist/jobs/index.d.ts +1 -0
- package/dist/jobs/index.mjs +37 -6
- package/dist/maestro-processes/index.cjs +224 -18
- package/dist/maestro-processes/index.d.ts +221 -9
- package/dist/maestro-processes/index.mjs +224 -18
- package/dist/processes/index.cjs +37 -6
- package/dist/processes/index.d.ts +1 -0
- package/dist/processes/index.mjs +37 -6
- package/dist/queues/index.cjs +37 -6
- package/dist/queues/index.d.ts +1 -0
- package/dist/queues/index.mjs +37 -6
- package/dist/tasks/index.cjs +37 -6
- package/dist/tasks/index.d.ts +1 -0
- package/dist/tasks/index.mjs +37 -6
- package/dist/traces/index.cjs +1933 -0
- package/dist/traces/index.d.ts +566 -0
- package/dist/traces/index.mjs +1931 -0
- package/package.json +42 -2
package/dist/core/index.cjs
CHANGED
|
@@ -4013,7 +4013,7 @@ object({
|
|
|
4013
4013
|
secret: string().optional(),
|
|
4014
4014
|
clientId: string().optional(),
|
|
4015
4015
|
redirectUri: string().url().optional(),
|
|
4016
|
-
scope: string().optional()
|
|
4016
|
+
scope: string().optional(),
|
|
4017
4017
|
});
|
|
4018
4018
|
class UiPathConfig {
|
|
4019
4019
|
constructor(options) {
|
|
@@ -4064,6 +4064,32 @@ class ExecutionContext {
|
|
|
4064
4064
|
*/
|
|
4065
4065
|
const isBrowser = typeof window !== 'undefined' && typeof window.document !== 'undefined';
|
|
4066
4066
|
const isInActionCenter = isBrowser && window.self != window.top && window.location.href.includes('source=ActionCenter');
|
|
4067
|
+
const _params = isBrowser ? new URLSearchParams(window.location.search) : null;
|
|
4068
|
+
/**
|
|
4069
|
+
* True when the coded app has been loaded inside a host frame that explicitly
|
|
4070
|
+
* opted into token delegation by adding `?host=embed` to the iframe src URL.
|
|
4071
|
+
*/
|
|
4072
|
+
const isHostEmbedded = isBrowser && window.self !== window.top && _params?.get('host') === 'embed';
|
|
4073
|
+
/**
|
|
4074
|
+
* The validated parent origin, read from the `?basedomain=` query param set
|
|
4075
|
+
* by the embedding host in the iframe src URL.
|
|
4076
|
+
* Mirrors the same mechanism used by ActionCenterTokenManager.
|
|
4077
|
+
* Non-null only when `?host=embed` is present and `?basedomain=` is a valid URL.
|
|
4078
|
+
*/
|
|
4079
|
+
const embeddingOrigin = (() => {
|
|
4080
|
+
if (!isHostEmbedded)
|
|
4081
|
+
return null;
|
|
4082
|
+
const basedomain = _params?.get('basedomain');
|
|
4083
|
+
if (!basedomain)
|
|
4084
|
+
return null;
|
|
4085
|
+
try {
|
|
4086
|
+
return new URL(basedomain).origin;
|
|
4087
|
+
}
|
|
4088
|
+
catch {
|
|
4089
|
+
console.warn('embeddingOrigin: basedomain query param is not a valid URL', basedomain);
|
|
4090
|
+
return null;
|
|
4091
|
+
}
|
|
4092
|
+
})();
|
|
4067
4093
|
|
|
4068
4094
|
/**
|
|
4069
4095
|
* Session storage keys used by the auth module
|
|
@@ -4496,6 +4522,96 @@ var ActionCenterEventNames;
|
|
|
4496
4522
|
})(ActionCenterEventNames || (ActionCenterEventNames = {}));
|
|
4497
4523
|
|
|
4498
4524
|
const AUTHENTICATION_TIMEOUT = 8000;
|
|
4525
|
+
const ALLOWED_HOST_ORIGINS = new Set([
|
|
4526
|
+
'https://alpha.uipath.com',
|
|
4527
|
+
'https://staging.uipath.com',
|
|
4528
|
+
'https://cloud.uipath.com',
|
|
4529
|
+
]);
|
|
4530
|
+
/**
|
|
4531
|
+
* Returns true if the origin is a trusted UiPath host that may initiate
|
|
4532
|
+
* token delegation. Mirrors the same allowlist used by ActionCenterTokenManager.
|
|
4533
|
+
*/
|
|
4534
|
+
function isValidHostOrigin(origin) {
|
|
4535
|
+
if (!origin)
|
|
4536
|
+
return false;
|
|
4537
|
+
if (ALLOWED_HOST_ORIGINS.has(origin))
|
|
4538
|
+
return true;
|
|
4539
|
+
try {
|
|
4540
|
+
return new URL(origin).hostname === 'localhost';
|
|
4541
|
+
}
|
|
4542
|
+
catch {
|
|
4543
|
+
console.warn('isValidHostOrigin: received a malformed origin URL', origin);
|
|
4544
|
+
return false;
|
|
4545
|
+
}
|
|
4546
|
+
}
|
|
4547
|
+
function isTokenExpired(tokenInfo) {
|
|
4548
|
+
if (!tokenInfo?.expiresAt)
|
|
4549
|
+
return true;
|
|
4550
|
+
return new Date() >= tokenInfo.expiresAt;
|
|
4551
|
+
}
|
|
4552
|
+
/**
|
|
4553
|
+
* Waits for the next window message that satisfies `filter`.
|
|
4554
|
+
* Rejects if the AbortSignal fires before a matching message arrives.
|
|
4555
|
+
*/
|
|
4556
|
+
function waitForMessage(filter, signal) {
|
|
4557
|
+
return new Promise((resolve, reject) => {
|
|
4558
|
+
const handler = (event) => {
|
|
4559
|
+
if (!filter(event))
|
|
4560
|
+
return;
|
|
4561
|
+
window.removeEventListener('message', handler);
|
|
4562
|
+
resolve(event);
|
|
4563
|
+
};
|
|
4564
|
+
signal.addEventListener('abort', () => {
|
|
4565
|
+
window.removeEventListener('message', handler);
|
|
4566
|
+
reject(signal.reason);
|
|
4567
|
+
}, { once: true });
|
|
4568
|
+
window.addEventListener('message', handler);
|
|
4569
|
+
});
|
|
4570
|
+
}
|
|
4571
|
+
/**
|
|
4572
|
+
* Sends a token-refresh request to a parent host frame and waits for the
|
|
4573
|
+
* response. Handles timeout, origin filtering, and listener cleanup.
|
|
4574
|
+
*
|
|
4575
|
+
* Both ActionCenterTokenManager and EmbeddedTokenManager delegate to this
|
|
4576
|
+
* function; they differ only in the event names and message shape they use.
|
|
4577
|
+
*/
|
|
4578
|
+
function requestHostToken(options) {
|
|
4579
|
+
const { pinnedOrigin, sendRequest, responseEventType, extractToken, onTokenRefreshed } = options;
|
|
4580
|
+
const controller = new AbortController();
|
|
4581
|
+
const cancel = () => controller.abort(new AuthenticationError({
|
|
4582
|
+
message: 'Token refresh cancelled',
|
|
4583
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4584
|
+
}));
|
|
4585
|
+
const promise = (async () => {
|
|
4586
|
+
const timer = setTimeout(() => controller.abort(new AuthenticationError({
|
|
4587
|
+
message: `Token refresh timed out after ${AUTHENTICATION_TIMEOUT}ms waiting for host response`,
|
|
4588
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4589
|
+
})), AUTHENTICATION_TIMEOUT);
|
|
4590
|
+
try {
|
|
4591
|
+
// Register listener before sending — avoids any race between send and response
|
|
4592
|
+
const responsePromise = waitForMessage(event => event.origin === pinnedOrigin && event.data?.eventType === responseEventType, controller.signal);
|
|
4593
|
+
sendRequest();
|
|
4594
|
+
const event = await responsePromise;
|
|
4595
|
+
const token = extractToken(event.data);
|
|
4596
|
+
if (!token) {
|
|
4597
|
+
throw new AuthenticationError({
|
|
4598
|
+
message: 'Host responded but did not include a valid access token',
|
|
4599
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4600
|
+
});
|
|
4601
|
+
}
|
|
4602
|
+
// type: 'secret' intentionally prevents the SDK's internal OAuth refresh path
|
|
4603
|
+
// from running — the host manager owns the refresh cycle via requestHostToken.
|
|
4604
|
+
// This mirrors the same pattern used by ActionCenterTokenManager.
|
|
4605
|
+
onTokenRefreshed({ token: token.accessToken, type: 'secret', expiresAt: token.expiresAt });
|
|
4606
|
+
return token.accessToken;
|
|
4607
|
+
}
|
|
4608
|
+
finally {
|
|
4609
|
+
clearTimeout(timer);
|
|
4610
|
+
}
|
|
4611
|
+
})();
|
|
4612
|
+
return { promise, cancel };
|
|
4613
|
+
}
|
|
4614
|
+
|
|
4499
4615
|
class ActionCenterTokenManager {
|
|
4500
4616
|
constructor(config, onTokenRefreshed) {
|
|
4501
4617
|
this.config = config;
|
|
@@ -4504,85 +4620,283 @@ class ActionCenterTokenManager {
|
|
|
4504
4620
|
this.refreshPromise = null;
|
|
4505
4621
|
}
|
|
4506
4622
|
async refreshAccessToken(tokenInfo) {
|
|
4507
|
-
if (!
|
|
4623
|
+
if (!isTokenExpired(tokenInfo)) {
|
|
4508
4624
|
return tokenInfo.token;
|
|
4509
4625
|
}
|
|
4510
4626
|
if (this.refreshPromise) {
|
|
4511
4627
|
return this.refreshPromise;
|
|
4512
4628
|
}
|
|
4513
|
-
|
|
4514
|
-
|
|
4629
|
+
const parentOrigin = this.parentOrigin;
|
|
4630
|
+
if (!parentOrigin) {
|
|
4631
|
+
return Promise.reject(new AuthenticationError({
|
|
4632
|
+
message: 'Cannot refresh token: basedomain query parameter is missing',
|
|
4633
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4634
|
+
}));
|
|
4635
|
+
}
|
|
4636
|
+
// Guard before requestHostToken registers the inbound listener — an untrusted
|
|
4637
|
+
// basedomain would otherwise leave the listener live for the full timeout window,
|
|
4638
|
+
// accepting a forged TOKENREFRESHED from that origin.
|
|
4639
|
+
if (!isValidHostOrigin(parentOrigin)) {
|
|
4640
|
+
return Promise.reject(new AuthenticationError({
|
|
4641
|
+
message: 'Cannot refresh token: basedomain is not a trusted UiPath host origin',
|
|
4642
|
+
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4643
|
+
}));
|
|
4644
|
+
}
|
|
4645
|
+
const { promise } = requestHostToken({
|
|
4646
|
+
pinnedOrigin: parentOrigin,
|
|
4647
|
+
sendRequest: () => this.sendMessageToParent(ActionCenterEventNames.REFRESHTOKEN, {
|
|
4515
4648
|
clientId: this.config.clientId,
|
|
4516
4649
|
scope: this.config.scope,
|
|
4517
|
-
}
|
|
4518
|
-
|
|
4519
|
-
|
|
4520
|
-
|
|
4521
|
-
|
|
4522
|
-
|
|
4523
|
-
|
|
4524
|
-
|
|
4525
|
-
|
|
4526
|
-
const { accessToken, expiresAt } = event.data.content.token;
|
|
4527
|
-
this.onTokenRefreshed({ token: accessToken, type: 'secret', expiresAt });
|
|
4528
|
-
resolve(accessToken);
|
|
4529
|
-
}
|
|
4530
|
-
else {
|
|
4531
|
-
reject(new AuthenticationError({
|
|
4532
|
-
message: 'Failed to fetch access token',
|
|
4533
|
-
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4534
|
-
}));
|
|
4535
|
-
}
|
|
4536
|
-
this.refreshPromise = null;
|
|
4537
|
-
this.cleanup(messageListener);
|
|
4538
|
-
};
|
|
4539
|
-
const timer = setTimeout(() => {
|
|
4540
|
-
reject(new AuthenticationError({
|
|
4541
|
-
message: 'Failed to fetch access token',
|
|
4542
|
-
statusCode: HttpStatus.UNAUTHORIZED,
|
|
4543
|
-
}));
|
|
4544
|
-
this.refreshPromise = null;
|
|
4545
|
-
this.cleanup(messageListener);
|
|
4546
|
-
}, AUTHENTICATION_TIMEOUT);
|
|
4547
|
-
window.addEventListener('message', messageListener);
|
|
4650
|
+
}),
|
|
4651
|
+
responseEventType: ActionCenterEventNames.TOKENREFRESHED,
|
|
4652
|
+
extractToken: (data) => {
|
|
4653
|
+
const token = data?.content?.token;
|
|
4654
|
+
if (!token?.accessToken)
|
|
4655
|
+
return undefined;
|
|
4656
|
+
return { accessToken: token.accessToken, expiresAt: token.expiresAt };
|
|
4657
|
+
},
|
|
4658
|
+
onTokenRefreshed: this.onTokenRefreshed,
|
|
4548
4659
|
});
|
|
4549
|
-
|
|
4550
|
-
|
|
4551
|
-
|
|
4552
|
-
|
|
4553
|
-
|
|
4660
|
+
this.refreshPromise = promise;
|
|
4661
|
+
try {
|
|
4662
|
+
return await this.refreshPromise;
|
|
4663
|
+
}
|
|
4664
|
+
finally {
|
|
4665
|
+
this.refreshPromise = null;
|
|
4554
4666
|
}
|
|
4555
|
-
return new Date() >= tokenInfo.expiresAt;
|
|
4556
4667
|
}
|
|
4557
4668
|
sendMessageToParent(eventType, content) {
|
|
4558
|
-
if (window.parent &&
|
|
4669
|
+
if (window.parent && isValidHostOrigin(this.parentOrigin)) {
|
|
4559
4670
|
try {
|
|
4560
4671
|
window.parent.postMessage({ eventType, content }, this.parentOrigin);
|
|
4561
4672
|
}
|
|
4562
4673
|
catch (error) {
|
|
4563
|
-
console.warn('
|
|
4674
|
+
console.warn('ActionCenterTokenManager: postMessage to host failed', JSON.stringify(error));
|
|
4564
4675
|
}
|
|
4565
4676
|
}
|
|
4566
4677
|
}
|
|
4567
|
-
|
|
4568
|
-
|
|
4678
|
+
}
|
|
4679
|
+
|
|
4680
|
+
/**
|
|
4681
|
+
* Event names and payload types for the UIP.* postMessage protocol used
|
|
4682
|
+
* when a coded app is embedded inside a UiPath host (e.g. Governance Portal, Insights UI).
|
|
4683
|
+
*
|
|
4684
|
+
* Flow — app-initiated, mirrors the Action Center protocol:
|
|
4685
|
+
* App → Host: UIP.refreshToken (requests a token; carries clientId + scope
|
|
4686
|
+
* so the host knows which OAuth client to use)
|
|
4687
|
+
* Host → App: UIP.tokenRefreshed (delivers the access token)
|
|
4688
|
+
*
|
|
4689
|
+
* Detection: the host signals embedding via `?host=embed&basedomain=<origin>` in
|
|
4690
|
+
* the iframe src URL. No explicit init message from the host is required.
|
|
4691
|
+
*/
|
|
4692
|
+
var UipEmbeddedEventNames;
|
|
4693
|
+
(function (UipEmbeddedEventNames) {
|
|
4694
|
+
UipEmbeddedEventNames["REFRESH_TOKEN"] = "UIP.refreshToken";
|
|
4695
|
+
UipEmbeddedEventNames["TOKEN_REFRESHED"] = "UIP.tokenRefreshed";
|
|
4696
|
+
})(UipEmbeddedEventNames || (UipEmbeddedEventNames = {}));
|
|
4697
|
+
|
|
4698
|
+
function parseExpiresAt(raw) {
|
|
4699
|
+
const d = new Date(raw);
|
|
4700
|
+
if (isNaN(d.getTime())) {
|
|
4701
|
+
console.warn('EmbeddedTokenManager: host sent a malformed expiresAt value — treating token as already expired', raw);
|
|
4702
|
+
return new Date(0);
|
|
4569
4703
|
}
|
|
4570
|
-
|
|
4571
|
-
|
|
4572
|
-
|
|
4573
|
-
|
|
4704
|
+
return d;
|
|
4705
|
+
}
|
|
4706
|
+
function extractToken(data) {
|
|
4707
|
+
const token = data?.content?.token;
|
|
4708
|
+
if (!token?.accessToken)
|
|
4709
|
+
return undefined;
|
|
4710
|
+
return { accessToken: token.accessToken, expiresAt: parseExpiresAt(token.expiresAt) };
|
|
4711
|
+
}
|
|
4712
|
+
/**
|
|
4713
|
+
* Handles token delegation for coded apps embedded inside a UiPath host
|
|
4714
|
+
* (e.g. Governance Portal, Insights UI).
|
|
4715
|
+
*
|
|
4716
|
+
* Detection: the host signals embedding via `?host=embed&basedomain=<origin>`
|
|
4717
|
+
* in the iframe src URL. `parentOrigin` is read from `?basedomain=` and validated
|
|
4718
|
+
* against the trusted UiPath host allowlist before this manager is constructed.
|
|
4719
|
+
* This mirrors the mechanism used by ActionCenterTokenManager.
|
|
4720
|
+
*
|
|
4721
|
+
* On every token expiry the SDK sends `UIP.refreshToken` with `clientId` and
|
|
4722
|
+
* `scope`; the host performs silent SSO and responds with `UIP.tokenRefreshed`.
|
|
4723
|
+
*/
|
|
4724
|
+
class EmbeddedTokenManager {
|
|
4725
|
+
/**
|
|
4726
|
+
* @param parentOrigin Validated UiPath host origin from the `?basedomain=` query parameter.
|
|
4727
|
+
* @param config SDK configuration — `clientId` and `scope` are required and forwarded
|
|
4728
|
+
* in every `UIP.refreshToken` request so the host knows which OAuth client to use.
|
|
4729
|
+
* @param onTokenRefreshed Called with the refreshed TokenInfo so the caller
|
|
4730
|
+
* can persist it in the execution context.
|
|
4731
|
+
* @throws {AuthenticationError} if `config.clientId` or `config.scope` are not set.
|
|
4732
|
+
*/
|
|
4733
|
+
constructor(parentOrigin, config, onTokenRefreshed) {
|
|
4734
|
+
this.parentOrigin = parentOrigin;
|
|
4735
|
+
this.onTokenRefreshed = onTokenRefreshed;
|
|
4736
|
+
this.refreshPromise = null;
|
|
4737
|
+
this.cancelRefresh = null;
|
|
4738
|
+
if (!config.clientId || !config.scope) {
|
|
4739
|
+
throw new ValidationError({
|
|
4740
|
+
message: 'EmbeddedTokenManager requires clientId and scope to be configured for host-delegated authentication',
|
|
4741
|
+
});
|
|
4574
4742
|
}
|
|
4575
|
-
|
|
4576
|
-
|
|
4743
|
+
this.clientId = config.clientId;
|
|
4744
|
+
this.scope = config.scope;
|
|
4745
|
+
}
|
|
4746
|
+
async refreshAccessToken(tokenInfo) {
|
|
4747
|
+
if (!isTokenExpired(tokenInfo)) {
|
|
4748
|
+
return tokenInfo.token;
|
|
4577
4749
|
}
|
|
4750
|
+
if (this.refreshPromise) {
|
|
4751
|
+
return this.refreshPromise;
|
|
4752
|
+
}
|
|
4753
|
+
const { promise, cancel } = requestHostToken({
|
|
4754
|
+
pinnedOrigin: this.parentOrigin,
|
|
4755
|
+
sendRequest: () => {
|
|
4756
|
+
try {
|
|
4757
|
+
const message = {
|
|
4758
|
+
eventType: UipEmbeddedEventNames.REFRESH_TOKEN,
|
|
4759
|
+
content: { clientId: this.clientId, scope: this.scope },
|
|
4760
|
+
};
|
|
4761
|
+
window.parent.postMessage(message, this.parentOrigin);
|
|
4762
|
+
}
|
|
4763
|
+
catch (error) {
|
|
4764
|
+
console.warn('EmbeddedTokenManager: postMessage to host failed', error);
|
|
4765
|
+
}
|
|
4766
|
+
},
|
|
4767
|
+
responseEventType: UipEmbeddedEventNames.TOKEN_REFRESHED,
|
|
4768
|
+
extractToken,
|
|
4769
|
+
onTokenRefreshed: this.onTokenRefreshed,
|
|
4770
|
+
});
|
|
4771
|
+
this.cancelRefresh = cancel;
|
|
4772
|
+
this.refreshPromise = promise;
|
|
4578
4773
|
try {
|
|
4579
|
-
|
|
4580
|
-
return url.hostname === 'localhost';
|
|
4774
|
+
return await this.refreshPromise;
|
|
4581
4775
|
}
|
|
4582
|
-
|
|
4583
|
-
|
|
4776
|
+
finally {
|
|
4777
|
+
this.refreshPromise = null;
|
|
4778
|
+
this.cancelRefresh = null;
|
|
4779
|
+
}
|
|
4780
|
+
}
|
|
4781
|
+
/** Cancels any in-flight token-refresh request. */
|
|
4782
|
+
destroy() {
|
|
4783
|
+
this.cancelRefresh?.();
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4786
|
+
|
|
4787
|
+
/**
|
|
4788
|
+
* SDK Telemetry constants.
|
|
4789
|
+
*
|
|
4790
|
+
* Only the SDK's identity (version, service name, role name, …) lives
|
|
4791
|
+
* here. The Application Insights connection string is injected into
|
|
4792
|
+
* `@uipath/core-telemetry` itself at publish time, and the generic attribute
|
|
4793
|
+
* keys (`Version`, `Service`, `CloudOrganizationName`, …) are owned by
|
|
4794
|
+
* `@uipath/core-telemetry` and consumed there — they are not part of the
|
|
4795
|
+
* SDK's public API.
|
|
4796
|
+
*/
|
|
4797
|
+
/** SDK version placeholder — patched by the SDK publish workflow. */
|
|
4798
|
+
const SDK_VERSION = '1.4.0';
|
|
4799
|
+
const CLOUD_ROLE_NAME = 'uipath-ts-sdk';
|
|
4800
|
+
const SDK_SERVICE_NAME = 'UiPath.TypeScript.Sdk';
|
|
4801
|
+
const SDK_LOGGER_NAME = 'uipath-ts-sdk-telemetry';
|
|
4802
|
+
const SDK_RUN_EVENT = 'Sdk.Run';
|
|
4803
|
+
|
|
4804
|
+
/**
|
|
4805
|
+
* UiPath TypeScript SDK Telemetry
|
|
4806
|
+
*
|
|
4807
|
+
* Constructs the SDK's own `TelemetryClient` and binds the SDK-local
|
|
4808
|
+
* `track` / `trackEvent` to it. Each consumer of `@uipath/core-telemetry`
|
|
4809
|
+
* does this independently, so events carry their own consumer's identity
|
|
4810
|
+
* and tenant context.
|
|
4811
|
+
*/
|
|
4812
|
+
// Keyed by `CLOUD_ROLE_NAME` so every SDK subpath bundle resolves to the
|
|
4813
|
+
// same `TelemetryClient` instance at runtime. A single `initialize(...)`
|
|
4814
|
+
// from the `UiPath` constructor therefore wires up `@track` decorators
|
|
4815
|
+
// across every subpath bundle (`assets`, `feedback`, `tasks`, …).
|
|
4816
|
+
const sdkClient = coreTelemetry.getOrCreateClient(CLOUD_ROLE_NAME);
|
|
4817
|
+
const track = coreTelemetry.createTrack(sdkClient);
|
|
4818
|
+
const trackEvent = coreTelemetry.createTrackEvent(sdkClient);
|
|
4819
|
+
const telemetryClient = {
|
|
4820
|
+
initialize(context) {
|
|
4821
|
+
sdkClient.initialize({
|
|
4822
|
+
sdkVersion: SDK_VERSION,
|
|
4823
|
+
serviceName: SDK_SERVICE_NAME,
|
|
4824
|
+
cloudRoleName: CLOUD_ROLE_NAME,
|
|
4825
|
+
loggerName: SDK_LOGGER_NAME,
|
|
4826
|
+
defaultEventName: SDK_RUN_EVENT,
|
|
4827
|
+
context,
|
|
4828
|
+
});
|
|
4829
|
+
},
|
|
4830
|
+
/**
|
|
4831
|
+
* Sets the authenticated user's id so every subsequently emitted event
|
|
4832
|
+
* carries it as `CloudUserId`.
|
|
4833
|
+
*/
|
|
4834
|
+
setUserId(userId) {
|
|
4835
|
+
sdkClient.setUserId(userId);
|
|
4836
|
+
},
|
|
4837
|
+
};
|
|
4838
|
+
|
|
4839
|
+
/**
|
|
4840
|
+
* Base64 encoding/decoding
|
|
4841
|
+
*/
|
|
4842
|
+
/**
|
|
4843
|
+
* Decodes a base64 string
|
|
4844
|
+
* @param base64 - The base64 string to decode
|
|
4845
|
+
* @returns Decoded string
|
|
4846
|
+
*/
|
|
4847
|
+
function decodeBase64(base64) {
|
|
4848
|
+
let bytes;
|
|
4849
|
+
if (isBrowser) {
|
|
4850
|
+
// Browser environment
|
|
4851
|
+
const binaryString = atob(base64);
|
|
4852
|
+
bytes = new Uint8Array(binaryString.length);
|
|
4853
|
+
for (let i = 0; i < binaryString.length; i++) {
|
|
4854
|
+
bytes[i] = binaryString.charCodeAt(i);
|
|
4584
4855
|
}
|
|
4585
4856
|
}
|
|
4857
|
+
else {
|
|
4858
|
+
// Node.js environment
|
|
4859
|
+
bytes = new Uint8Array(Buffer.from(base64, 'base64'));
|
|
4860
|
+
}
|
|
4861
|
+
// TextDecoder for UTF-8 decoding (works in both browser and Node.js)
|
|
4862
|
+
const decoder = new TextDecoder();
|
|
4863
|
+
return decoder.decode(bytes);
|
|
4864
|
+
}
|
|
4865
|
+
|
|
4866
|
+
/**
|
|
4867
|
+
* JWT decoding helpers — payload inspection only, no signature verification.
|
|
4868
|
+
*/
|
|
4869
|
+
const BASE64URL_DASH_RE = /-/g;
|
|
4870
|
+
const BASE64URL_UNDERSCORE_RE = /_/g;
|
|
4871
|
+
/**
|
|
4872
|
+
* Converts a base64url-encoded JWT segment to standard base64 with padding.
|
|
4873
|
+
*/
|
|
4874
|
+
function base64UrlToBase64(value) {
|
|
4875
|
+
const base64 = value
|
|
4876
|
+
.replace(BASE64URL_DASH_RE, '+')
|
|
4877
|
+
.replace(BASE64URL_UNDERSCORE_RE, '/');
|
|
4878
|
+
return base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), '=');
|
|
4879
|
+
}
|
|
4880
|
+
/**
|
|
4881
|
+
* Extracts the user id (`sub` claim) from a JWT access token payload.
|
|
4882
|
+
* Returns an empty string for opaque (non-JWT) tokens or malformed payloads.
|
|
4883
|
+
*
|
|
4884
|
+
* @param token - The access token to inspect
|
|
4885
|
+
* @returns The user id, or an empty string if it cannot be extracted
|
|
4886
|
+
*/
|
|
4887
|
+
function extractUserIdFromToken(token) {
|
|
4888
|
+
try {
|
|
4889
|
+
const payload = token.split('.')[1];
|
|
4890
|
+
if (!payload) {
|
|
4891
|
+
return '';
|
|
4892
|
+
}
|
|
4893
|
+
const claims = JSON.parse(decodeBase64(base64UrlToBase64(payload)));
|
|
4894
|
+
const sub = claims['sub'];
|
|
4895
|
+
return typeof sub === 'string' && sub ? sub : '';
|
|
4896
|
+
}
|
|
4897
|
+
catch {
|
|
4898
|
+
return '';
|
|
4899
|
+
}
|
|
4586
4900
|
}
|
|
4587
4901
|
|
|
4588
4902
|
/**
|
|
@@ -4604,10 +4918,15 @@ class TokenManager {
|
|
|
4604
4918
|
this.isOAuth = isOAuth;
|
|
4605
4919
|
this.refreshPromise = null;
|
|
4606
4920
|
this.actionCenterTokenManager = null;
|
|
4921
|
+
this.embeddedTokenManager = null;
|
|
4607
4922
|
if (isInActionCenter) {
|
|
4608
4923
|
this.actionCenterTokenManager = new ActionCenterTokenManager(config, (tokenInfo) => this.setToken(tokenInfo));
|
|
4609
4924
|
this.isOAuth = false;
|
|
4610
4925
|
}
|
|
4926
|
+
else if (isHostEmbedded && embeddingOrigin && isValidHostOrigin(embeddingOrigin)) {
|
|
4927
|
+
this.embeddedTokenManager = new EmbeddedTokenManager(embeddingOrigin, config, tokenInfo => this.setToken(tokenInfo));
|
|
4928
|
+
this.isOAuth = false;
|
|
4929
|
+
}
|
|
4611
4930
|
}
|
|
4612
4931
|
/**
|
|
4613
4932
|
* Checks if a token is expired
|
|
@@ -4638,6 +4957,10 @@ class TokenManager {
|
|
|
4638
4957
|
if (this.actionCenterTokenManager) {
|
|
4639
4958
|
return await this.actionCenterTokenManager.refreshAccessToken(tokenInfo);
|
|
4640
4959
|
}
|
|
4960
|
+
// Generic embedded path — active whenever the app is embedded in a UiPath host page
|
|
4961
|
+
if (this.embeddedTokenManager) {
|
|
4962
|
+
return await this.embeddedTokenManager.refreshAccessToken(tokenInfo);
|
|
4963
|
+
}
|
|
4641
4964
|
// For secret-based tokens, they never expire
|
|
4642
4965
|
if (tokenInfo.type === 'secret') {
|
|
4643
4966
|
return tokenInfo.token;
|
|
@@ -4776,6 +5099,13 @@ class TokenManager {
|
|
|
4776
5099
|
}
|
|
4777
5100
|
return true;
|
|
4778
5101
|
}
|
|
5102
|
+
/**
|
|
5103
|
+
* Releases resources held by this instance.
|
|
5104
|
+
* Must be called when the TokenManager is no longer needed to prevent listener leaks.
|
|
5105
|
+
*/
|
|
5106
|
+
destroy() {
|
|
5107
|
+
this.embeddedTokenManager?.destroy();
|
|
5108
|
+
}
|
|
4779
5109
|
/**
|
|
4780
5110
|
* Clears the current token
|
|
4781
5111
|
*/
|
|
@@ -4797,6 +5127,7 @@ class TokenManager {
|
|
|
4797
5127
|
*/
|
|
4798
5128
|
_updateExecutionContext(tokenInfo) {
|
|
4799
5129
|
this.executionContext.set('tokenInfo', tokenInfo);
|
|
5130
|
+
telemetryClient.setUserId(extractUserIdFromToken(tokenInfo.token));
|
|
4800
5131
|
}
|
|
4801
5132
|
/**
|
|
4802
5133
|
* Refreshes the access token using the stored refresh token.
|
|
@@ -4826,6 +5157,9 @@ class TokenManager {
|
|
|
4826
5157
|
* Internal method to perform the actual token refresh
|
|
4827
5158
|
*/
|
|
4828
5159
|
async _doRefreshToken() {
|
|
5160
|
+
// Destructure before the type guard — hasOAuthConfig narrows this.config to
|
|
5161
|
+
// { clientId, redirectUri, scope } which does not include BaseConfig fields.
|
|
5162
|
+
const { orgName, baseUrl } = this.config;
|
|
4829
5163
|
// Check if we're in OAuth flow
|
|
4830
5164
|
if (!hasOAuthConfig(this.config)) {
|
|
4831
5165
|
throw new Error('refreshAccessToken is only available in OAuth flow');
|
|
@@ -4835,13 +5169,12 @@ class TokenManager {
|
|
|
4835
5169
|
if (!tokenInfo?.refreshToken) {
|
|
4836
5170
|
throw new Error('No refresh token available. User may need to re-authenticate.');
|
|
4837
5171
|
}
|
|
4838
|
-
const orgName = this.config.orgName;
|
|
4839
5172
|
const body = new URLSearchParams({
|
|
4840
5173
|
grant_type: 'refresh_token',
|
|
4841
5174
|
client_id: this.config.clientId,
|
|
4842
5175
|
refresh_token: tokenInfo.refreshToken
|
|
4843
5176
|
});
|
|
4844
|
-
const response = await fetch(`${
|
|
5177
|
+
const response = await fetch(`${baseUrl}/${orgName}/identity_/connect/token`, {
|
|
4845
5178
|
method: 'POST',
|
|
4846
5179
|
headers: {
|
|
4847
5180
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
@@ -5301,51 +5634,6 @@ function normalizeBaseUrl(url) {
|
|
|
5301
5634
|
return url.endsWith('/') ? url.slice(0, -1) : url;
|
|
5302
5635
|
}
|
|
5303
5636
|
|
|
5304
|
-
/**
|
|
5305
|
-
* SDK Telemetry constants.
|
|
5306
|
-
*
|
|
5307
|
-
* Only the SDK's identity (version, service name, role name, …) lives
|
|
5308
|
-
* here. The Application Insights connection string is injected into
|
|
5309
|
-
* `@uipath/core-telemetry` itself at publish time, and the generic attribute
|
|
5310
|
-
* keys (`Version`, `Service`, `CloudOrganizationName`, …) are owned by
|
|
5311
|
-
* `@uipath/core-telemetry` and consumed there — they are not part of the
|
|
5312
|
-
* SDK's public API.
|
|
5313
|
-
*/
|
|
5314
|
-
/** SDK version placeholder — patched by the SDK publish workflow. */
|
|
5315
|
-
const SDK_VERSION = '1.3.10';
|
|
5316
|
-
const CLOUD_ROLE_NAME = 'uipath-ts-sdk';
|
|
5317
|
-
const SDK_SERVICE_NAME = 'UiPath.TypeScript.Sdk';
|
|
5318
|
-
const SDK_LOGGER_NAME = 'uipath-ts-sdk-telemetry';
|
|
5319
|
-
const SDK_RUN_EVENT = 'Sdk.Run';
|
|
5320
|
-
|
|
5321
|
-
/**
|
|
5322
|
-
* UiPath TypeScript SDK Telemetry
|
|
5323
|
-
*
|
|
5324
|
-
* Constructs the SDK's own `TelemetryClient` and binds the SDK-local
|
|
5325
|
-
* `track` / `trackEvent` to it. Each consumer of `@uipath/core-telemetry`
|
|
5326
|
-
* does this independently, so events carry their own consumer's identity
|
|
5327
|
-
* and tenant context.
|
|
5328
|
-
*/
|
|
5329
|
-
// Keyed by `CLOUD_ROLE_NAME` so every SDK subpath bundle resolves to the
|
|
5330
|
-
// same `TelemetryClient` instance at runtime. A single `initialize(...)`
|
|
5331
|
-
// from the `UiPath` constructor therefore wires up `@track` decorators
|
|
5332
|
-
// across every subpath bundle (`assets`, `feedback`, `tasks`, …).
|
|
5333
|
-
const sdkClient = coreTelemetry.getOrCreateClient(CLOUD_ROLE_NAME);
|
|
5334
|
-
const track = coreTelemetry.createTrack(sdkClient);
|
|
5335
|
-
const trackEvent = coreTelemetry.createTrackEvent(sdkClient);
|
|
5336
|
-
const telemetryClient = {
|
|
5337
|
-
initialize(context) {
|
|
5338
|
-
sdkClient.initialize({
|
|
5339
|
-
sdkVersion: SDK_VERSION,
|
|
5340
|
-
serviceName: SDK_SERVICE_NAME,
|
|
5341
|
-
cloudRoleName: CLOUD_ROLE_NAME,
|
|
5342
|
-
loggerName: SDK_LOGGER_NAME,
|
|
5343
|
-
defaultEventName: SDK_RUN_EVENT,
|
|
5344
|
-
context,
|
|
5345
|
-
});
|
|
5346
|
-
},
|
|
5347
|
-
};
|
|
5348
|
-
|
|
5349
5637
|
/**
|
|
5350
5638
|
* SDK Internals Registry - Internal registry for SDK instances
|
|
5351
5639
|
*
|
|
@@ -5455,7 +5743,7 @@ function loadFromMetaTags() {
|
|
|
5455
5743
|
return hasAnyValue ? config : null;
|
|
5456
5744
|
}
|
|
5457
5745
|
|
|
5458
|
-
var _UiPath_instances, _UiPath_config, _UiPath_authService, _UiPath_initialized, _UiPath_partialConfig, _UiPath_multiLogin, _UiPath_metaFolderKey, _UiPath_initializeWithConfig, _UiPath_loadConfig;
|
|
5746
|
+
var _UiPath_instances, _UiPath_config, _UiPath_authService, _UiPath_initialized, _UiPath_partialConfig, _UiPath_multiLogin, _UiPath_metaFolderKey, _UiPath_metaOrgId, _UiPath_metaTenantId, _UiPath_initializeWithConfig, _UiPath_loadConfig;
|
|
5459
5747
|
/**
|
|
5460
5748
|
* UiPath - Core SDK class for authentication and configuration management.
|
|
5461
5749
|
*
|
|
@@ -5500,9 +5788,18 @@ class UiPath {
|
|
|
5500
5788
|
// deployments). Not accepted via the public constructor; lives here so the
|
|
5501
5789
|
// SDK can flow it through to BaseService.config without polluting BaseConfig.
|
|
5502
5790
|
_UiPath_metaFolderKey.set(this, void 0);
|
|
5791
|
+
// Org/tenant ids captured from the meta tags before the constructor config
|
|
5792
|
+
// is merged in. The `uipath:org-name`/`uipath:tenant-name` meta tags always
|
|
5793
|
+
// carry org/tenant *ids* in coded-app deployments, whereas a
|
|
5794
|
+
// constructor-supplied `orgName`/`tenantName` may be actual names — so the
|
|
5795
|
+
// telemetry ids must be read from the meta tags.
|
|
5796
|
+
_UiPath_metaOrgId.set(this, void 0);
|
|
5797
|
+
_UiPath_metaTenantId.set(this, void 0);
|
|
5503
5798
|
// Load configuration from meta tags
|
|
5504
5799
|
const configFromMetaTags = loadFromMetaTags();
|
|
5505
5800
|
__classPrivateFieldSet(this, _UiPath_metaFolderKey, configFromMetaTags?.folderKey, "f");
|
|
5801
|
+
__classPrivateFieldSet(this, _UiPath_metaOrgId, configFromMetaTags?.orgName, "f");
|
|
5802
|
+
__classPrivateFieldSet(this, _UiPath_metaTenantId, configFromMetaTags?.tenantName, "f");
|
|
5506
5803
|
// Merge configuration: constructor config overrides meta tags
|
|
5507
5804
|
const mergedConfig = config ? { ...configFromMetaTags, ...config } : configFromMetaTags;
|
|
5508
5805
|
if (mergedConfig && isCompleteConfig(mergedConfig)) {
|
|
@@ -5609,6 +5906,13 @@ class UiPath {
|
|
|
5609
5906
|
getToken() {
|
|
5610
5907
|
return __classPrivateFieldGet(this, _UiPath_authService, "f")?.getToken();
|
|
5611
5908
|
}
|
|
5909
|
+
/**
|
|
5910
|
+
* Releases resources held by this SDK instance.
|
|
5911
|
+
* Cancels any in-flight token-refresh request. Call this when the coded app is unmounted.
|
|
5912
|
+
*/
|
|
5913
|
+
destroy() {
|
|
5914
|
+
__classPrivateFieldGet(this, _UiPath_authService, "f")?.getTokenManager()?.destroy();
|
|
5915
|
+
}
|
|
5612
5916
|
/**
|
|
5613
5917
|
* Logout from the SDK, clearing all authentication state.
|
|
5614
5918
|
* After calling this method, the user will need to re-initialize to authenticate again.
|
|
@@ -5631,7 +5935,7 @@ class UiPath {
|
|
|
5631
5935
|
__classPrivateFieldGet(this, _UiPath_authService, "f")?.updateToken(tokenInfo);
|
|
5632
5936
|
}
|
|
5633
5937
|
}
|
|
5634
|
-
_UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap(), _UiPath_partialConfig = new WeakMap(), _UiPath_multiLogin = new WeakMap(), _UiPath_metaFolderKey = new WeakMap(), _UiPath_instances = new WeakSet(), _UiPath_initializeWithConfig = function _UiPath_initializeWithConfig(config) {
|
|
5938
|
+
_UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_initialized = new WeakMap(), _UiPath_partialConfig = new WeakMap(), _UiPath_multiLogin = new WeakMap(), _UiPath_metaFolderKey = new WeakMap(), _UiPath_metaOrgId = new WeakMap(), _UiPath_metaTenantId = new WeakMap(), _UiPath_instances = new WeakSet(), _UiPath_initializeWithConfig = function _UiPath_initializeWithConfig(config) {
|
|
5635
5939
|
// Validate and normalize the configuration
|
|
5636
5940
|
validateConfig(config);
|
|
5637
5941
|
const hasSecretAuth = hasSecretConfig(config);
|
|
@@ -5667,9 +5971,11 @@ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_ini
|
|
|
5667
5971
|
orgName: internalConfig.orgName,
|
|
5668
5972
|
tenantName: internalConfig.tenantName
|
|
5669
5973
|
};
|
|
5670
|
-
// Initialize telemetry with SDK configuration
|
|
5974
|
+
// Initialize telemetry with SDK configuration.
|
|
5671
5975
|
telemetryClient.initialize({
|
|
5672
5976
|
baseUrl: config.baseUrl,
|
|
5977
|
+
orgId: __classPrivateFieldGet(this, _UiPath_metaOrgId, "f"),
|
|
5978
|
+
tenantId: __classPrivateFieldGet(this, _UiPath_metaTenantId, "f"),
|
|
5673
5979
|
orgName: config.orgName,
|
|
5674
5980
|
tenantName: config.tenantName,
|
|
5675
5981
|
clientId: hasOAuthAuth ? config.clientId : undefined,
|
|
@@ -5688,6 +5994,8 @@ _UiPath_config = new WeakMap(), _UiPath_authService = new WeakMap(), _UiPath_ini
|
|
|
5688
5994
|
// Load from meta tags
|
|
5689
5995
|
const metaConfig = loadFromMetaTags();
|
|
5690
5996
|
__classPrivateFieldSet(this, _UiPath_metaFolderKey, metaConfig?.folderKey, "f");
|
|
5997
|
+
__classPrivateFieldSet(this, _UiPath_metaOrgId, metaConfig?.orgName, "f");
|
|
5998
|
+
__classPrivateFieldSet(this, _UiPath_metaTenantId, metaConfig?.tenantName, "f");
|
|
5691
5999
|
// Merge with any partial config from constructor (constructor overrides meta tags)
|
|
5692
6000
|
const merged = { ...metaConfig, ...__classPrivateFieldGet(this, _UiPath_partialConfig, "f") };
|
|
5693
6001
|
if (!isCompleteConfig(merged)) {
|