@harborclient/team-hub-api 0.3.4 → 0.3.6
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/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/invitationLinks.d.ts +114 -0
- package/dist/invitationLinks.d.ts.map +1 -0
- package/dist/invitationLinks.js +222 -0
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -6,5 +6,6 @@ export { toTeamHubAuth, type TeamHubAuthConfig, type TeamHubAuthType } from './a
|
|
|
6
6
|
export { isTeamHubCollectionDeleteForbiddenError } from './isTeamHubCollectionDeleteForbiddenError.js';
|
|
7
7
|
export { isTeamHubSnippetsUnsupportedError } from './isTeamHubSnippetsUnsupportedError.js';
|
|
8
8
|
export { isTeamHubSnippetsForbiddenError } from './isTeamHubSnippetsForbiddenError.js';
|
|
9
|
+
export { HARBOR_PROTOCOL, INVITATION_CODE_PREFIX, TEAM_HUB_JOIN_QUERY_KEYS, buildTeamHubJoinDeepLink, buildTeamHubJoinUrl, isInvitationCodeFormat, isTeamHubBaseUrl, normalizeTeamHubBaseUrl, parseTeamHubJoinDeepLink, parseTeamHubJoinUrl, summarizeInvitationAccess, type InvitationLinkParams } from './invitationLinks.js';
|
|
9
10
|
export type { AdminEntityConfig, AdminResourceOption, CollectionRecord, CreateCollectionInput, CreateEnvironmentInput, CreateFolderInput, CreateHubTokenInput, CreateHubUserInput, CreateInvitedHubUserInput, CreateUserInvitationInput, CreateRequestInput, CreateRunResultInput, CreateSnippetInput, CreatedHubToken, CreatedHubUser, CreatedInvitedHubUser, EnvironmentRecord, FolderRecord, HealthResponse, HubApiTokenRecord, HubInvitationPreview, HubInvitationPreviewUser, HubInvitationRecord, HubInvitationStatus, HubUserRecord, HubUserRole, MoveRequestInput, PluginSourcesResponse, PreviewHubInvitationInput, RedeemHubInvitationInput, RenameFolderInput, ReorderFoldersInput, ReorderRequestsInput, ReloadConfigResponse, ReloadConfigSectionResult, ReloadConfigSectionName, ReloadConfigSectionStatus, RunResultDetail, RunResultKind, RunResultRecord, RunResultSummaryCounts, SavedRequestRecord, SessionCapabilities, SessionResponse, SnippetRecord, SnippetScope, TeamHubAdminResourceOptions, TeamHubClientConfig, UpdateCollectionInput, UpdateEnvironmentInput, UpdateHubUserInput, UpdateRequestInput, UpdateSnippetInput } from './types.js';
|
|
10
11
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,mCAAmC,EACnC,aAAa,EACb,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,uCAAuC,EAAE,MAAM,8CAA8C,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAC3F,OAAO,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AACvF,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,kBAAkB,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,eAAe,CAAC;AAC/F,YAAY,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAC1D,OAAO,EACL,mCAAmC,EACnC,aAAa,EACb,KAAK,kBAAkB,EACxB,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,KAAK,iBAAiB,EAAE,KAAK,eAAe,EAAE,MAAM,WAAW,CAAC;AACxF,OAAO,EAAE,uCAAuC,EAAE,MAAM,8CAA8C,CAAC;AACvG,OAAO,EAAE,iCAAiC,EAAE,MAAM,wCAAwC,CAAC;AAC3F,OAAO,EAAE,+BAA+B,EAAE,MAAM,sCAAsC,CAAC;AACvF,OAAO,EACL,eAAe,EACf,sBAAsB,EACtB,wBAAwB,EACxB,wBAAwB,EACxB,mBAAmB,EACnB,sBAAsB,EACtB,gBAAgB,EAChB,uBAAuB,EACvB,wBAAwB,EACxB,mBAAmB,EACnB,yBAAyB,EACzB,KAAK,oBAAoB,EAC1B,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EACV,iBAAiB,EACjB,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,sBAAsB,EACtB,iBAAiB,EACjB,mBAAmB,EACnB,kBAAkB,EAClB,yBAAyB,EACzB,yBAAyB,EACzB,kBAAkB,EAClB,oBAAoB,EACpB,kBAAkB,EAClB,eAAe,EACf,cAAc,EACd,qBAAqB,EACrB,iBAAiB,EACjB,YAAY,EACZ,cAAc,EACd,iBAAiB,EACjB,oBAAoB,EACpB,wBAAwB,EACxB,mBAAmB,EACnB,mBAAmB,EACnB,aAAa,EACb,WAAW,EACX,gBAAgB,EAChB,qBAAqB,EACrB,yBAAyB,EACzB,wBAAwB,EACxB,iBAAiB,EACjB,mBAAmB,EACnB,oBAAoB,EACpB,oBAAoB,EACpB,yBAAyB,EACzB,uBAAuB,EACvB,yBAAyB,EACzB,eAAe,EACf,aAAa,EACb,eAAe,EACf,sBAAsB,EACtB,kBAAkB,EAClB,mBAAmB,EACnB,eAAe,EACf,aAAa,EACb,YAAY,EACZ,2BAA2B,EAC3B,mBAAmB,EACnB,qBAAqB,EACrB,sBAAsB,EACtB,kBAAkB,EAClB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,YAAY,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -4,3 +4,4 @@ export { toTeamHubAuth } from './auth.js';
|
|
|
4
4
|
export { isTeamHubCollectionDeleteForbiddenError } from './isTeamHubCollectionDeleteForbiddenError.js';
|
|
5
5
|
export { isTeamHubSnippetsUnsupportedError } from './isTeamHubSnippetsUnsupportedError.js';
|
|
6
6
|
export { isTeamHubSnippetsForbiddenError } from './isTeamHubSnippetsForbiddenError.js';
|
|
7
|
+
export { HARBOR_PROTOCOL, INVITATION_CODE_PREFIX, TEAM_HUB_JOIN_QUERY_KEYS, buildTeamHubJoinDeepLink, buildTeamHubJoinUrl, isInvitationCodeFormat, isTeamHubBaseUrl, normalizeTeamHubBaseUrl, parseTeamHubJoinDeepLink, parseTeamHubJoinUrl, summarizeInvitationAccess } from './invitationLinks.js';
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom URL scheme registered by HarborClient for deep links from the web.
|
|
3
|
+
*/
|
|
4
|
+
export declare const HARBOR_PROTOCOL = "harborclient";
|
|
5
|
+
/**
|
|
6
|
+
* Prefix applied to generated invitation secrets.
|
|
7
|
+
*/
|
|
8
|
+
export declare const INVITATION_CODE_PREFIX = "hbi_";
|
|
9
|
+
/**
|
|
10
|
+
* Query parameter names shared by HTTPS join links and harborclient:// join links.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TEAM_HUB_JOIN_QUERY_KEYS: {
|
|
13
|
+
readonly url: "url";
|
|
14
|
+
readonly name: "name";
|
|
15
|
+
readonly role: "role";
|
|
16
|
+
readonly exp: "exp";
|
|
17
|
+
readonly hub: "hub";
|
|
18
|
+
readonly access: "access";
|
|
19
|
+
readonly code: "code";
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Fields used to build and parse Team Hub onboarding invitation links.
|
|
23
|
+
*/
|
|
24
|
+
export interface InvitationLinkParams {
|
|
25
|
+
/**
|
|
26
|
+
* Team Hub server base URL used for connection and redemption.
|
|
27
|
+
*/
|
|
28
|
+
baseUrl: string;
|
|
29
|
+
/**
|
|
30
|
+
* One-time invitation secret prefixed with `hbi_`.
|
|
31
|
+
*/
|
|
32
|
+
code: string;
|
|
33
|
+
/**
|
|
34
|
+
* Invited user display name shown in confirmation UI.
|
|
35
|
+
*/
|
|
36
|
+
name: string;
|
|
37
|
+
/**
|
|
38
|
+
* Invited user role shown in confirmation UI.
|
|
39
|
+
*/
|
|
40
|
+
role: 'admin' | 'user';
|
|
41
|
+
/**
|
|
42
|
+
* ISO-8601 expiry timestamp for the invitation.
|
|
43
|
+
*/
|
|
44
|
+
expiresAt: string;
|
|
45
|
+
/**
|
|
46
|
+
* Optional friendly hub label shown in confirmation UI.
|
|
47
|
+
*/
|
|
48
|
+
hubName?: string;
|
|
49
|
+
/**
|
|
50
|
+
* Optional human-readable access summary shown in confirmation UI.
|
|
51
|
+
*/
|
|
52
|
+
accessSummary?: string;
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns whether a string looks like a Team Hub invitation secret.
|
|
56
|
+
*
|
|
57
|
+
* @param value - Candidate invitation code.
|
|
58
|
+
*/
|
|
59
|
+
export declare function isInvitationCodeFormat(value: string): boolean;
|
|
60
|
+
/**
|
|
61
|
+
* Returns whether a string is a valid HTTP or HTTPS Team Hub base URL.
|
|
62
|
+
*
|
|
63
|
+
* @param value - Candidate Team Hub base URL.
|
|
64
|
+
*/
|
|
65
|
+
export declare function isTeamHubBaseUrl(value: string): boolean;
|
|
66
|
+
/**
|
|
67
|
+
* Normalizes a Team Hub base URL by trimming and removing trailing slashes.
|
|
68
|
+
*
|
|
69
|
+
* @param baseUrl - Raw Team Hub base URL.
|
|
70
|
+
*/
|
|
71
|
+
export declare function normalizeTeamHubBaseUrl(baseUrl: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Builds an HTTPS join link with display info in the query string and the
|
|
74
|
+
* invitation secret in the URL fragment.
|
|
75
|
+
*
|
|
76
|
+
* @param params - Invitation link parameters.
|
|
77
|
+
* @returns Clickable HTTPS join URL suitable for email and chat delivery.
|
|
78
|
+
*/
|
|
79
|
+
export declare function buildTeamHubJoinUrl(params: InvitationLinkParams): string;
|
|
80
|
+
/**
|
|
81
|
+
* Parses an HTTPS Team Hub join link into invitation parameters.
|
|
82
|
+
*
|
|
83
|
+
* @param url - Raw HTTPS join URL from a browser or pasted invite link.
|
|
84
|
+
* @returns Parsed invitation parameters, or null when invalid.
|
|
85
|
+
*/
|
|
86
|
+
export declare function parseTeamHubJoinUrl(url: string): InvitationLinkParams | null;
|
|
87
|
+
/**
|
|
88
|
+
* Builds a harborclient:// join deep link with the invitation secret in the query.
|
|
89
|
+
*
|
|
90
|
+
* @param params - Invitation link parameters.
|
|
91
|
+
* @returns Deep link URL suitable for launching HarborClient.
|
|
92
|
+
*/
|
|
93
|
+
export declare function buildTeamHubJoinDeepLink(params: InvitationLinkParams): string;
|
|
94
|
+
/**
|
|
95
|
+
* Parses a harborclient:// Team Hub join deep link into invitation parameters.
|
|
96
|
+
*
|
|
97
|
+
* @param url - Raw harborclient:// join URL from the OS protocol handler.
|
|
98
|
+
* @returns Parsed invitation parameters, or null when invalid.
|
|
99
|
+
*/
|
|
100
|
+
export declare function parseTeamHubJoinDeepLink(url: string): InvitationLinkParams | null;
|
|
101
|
+
/**
|
|
102
|
+
* Builds a short human-readable access summary from hub user access lists.
|
|
103
|
+
*
|
|
104
|
+
* @param input - Access list fields from a hub user record.
|
|
105
|
+
* @returns Summary string suitable for invite link query parameters.
|
|
106
|
+
*/
|
|
107
|
+
export declare function summarizeInvitationAccess(input: {
|
|
108
|
+
collectionAccess: string[];
|
|
109
|
+
environmentAccess: string[];
|
|
110
|
+
snippetAccess: string[];
|
|
111
|
+
llmAccess: boolean;
|
|
112
|
+
llmModels: string[];
|
|
113
|
+
}): string;
|
|
114
|
+
//# sourceMappingURL=invitationLinks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"invitationLinks.d.ts","sourceRoot":"","sources":["../src/invitationLinks.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,eAAO,MAAM,eAAe,iBAAiB,CAAC;AAE9C;;GAEG;AACH,eAAO,MAAM,sBAAsB,SAAS,CAAC;AAE7C;;GAEG;AACH,eAAO,MAAM,wBAAwB;;;;;;;;CAQ3B,CAAC;AAEX;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,IAAI,EAAE,MAAM,CAAC;IAEb;;OAEG;IACH,IAAI,EAAE,OAAO,GAAG,MAAM,CAAC;IAEvB;;OAEG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;OAEG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,aAAa,CAAC,EAAE,MAAM,CAAC;CACxB;AAED;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAI7D;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAOvD;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAE/D;AAgED;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAOxE;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CA8B5E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,MAAM,EAAE,oBAAoB,GAAG,MAAM,CAI7E;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,GAAG,IAAI,CA2BjF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,KAAK,EAAE;IAC/C,gBAAgB,EAAE,MAAM,EAAE,CAAC;IAC3B,iBAAiB,EAAE,MAAM,EAAE,CAAC;IAC5B,aAAa,EAAE,MAAM,EAAE,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,GAAG,MAAM,CAcT"}
|
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Custom URL scheme registered by HarborClient for deep links from the web.
|
|
3
|
+
*/
|
|
4
|
+
export const HARBOR_PROTOCOL = 'harborclient';
|
|
5
|
+
/**
|
|
6
|
+
* Prefix applied to generated invitation secrets.
|
|
7
|
+
*/
|
|
8
|
+
export const INVITATION_CODE_PREFIX = 'hbi_';
|
|
9
|
+
/**
|
|
10
|
+
* Query parameter names shared by HTTPS join links and harborclient:// join links.
|
|
11
|
+
*/
|
|
12
|
+
export const TEAM_HUB_JOIN_QUERY_KEYS = {
|
|
13
|
+
url: 'url',
|
|
14
|
+
name: 'name',
|
|
15
|
+
role: 'role',
|
|
16
|
+
exp: 'exp',
|
|
17
|
+
hub: 'hub',
|
|
18
|
+
access: 'access',
|
|
19
|
+
code: 'code'
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Returns whether a string looks like a Team Hub invitation secret.
|
|
23
|
+
*
|
|
24
|
+
* @param value - Candidate invitation code.
|
|
25
|
+
*/
|
|
26
|
+
export function isInvitationCodeFormat(value) {
|
|
27
|
+
return (value.startsWith(INVITATION_CODE_PREFIX) && value.length > INVITATION_CODE_PREFIX.length + 8);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Returns whether a string is a valid HTTP or HTTPS Team Hub base URL.
|
|
31
|
+
*
|
|
32
|
+
* @param value - Candidate Team Hub base URL.
|
|
33
|
+
*/
|
|
34
|
+
export function isTeamHubBaseUrl(value) {
|
|
35
|
+
try {
|
|
36
|
+
const parsed = new URL(value);
|
|
37
|
+
return parsed.protocol === 'http:' || parsed.protocol === 'https:';
|
|
38
|
+
}
|
|
39
|
+
catch {
|
|
40
|
+
return false;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Normalizes a Team Hub base URL by trimming and removing trailing slashes.
|
|
45
|
+
*
|
|
46
|
+
* @param baseUrl - Raw Team Hub base URL.
|
|
47
|
+
*/
|
|
48
|
+
export function normalizeTeamHubBaseUrl(baseUrl) {
|
|
49
|
+
return baseUrl.trim().replace(/\/+$/, '');
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Builds the non-secret query string shared by HTTPS and deep links.
|
|
53
|
+
*
|
|
54
|
+
* @param params - Invitation link parameters.
|
|
55
|
+
*/
|
|
56
|
+
function buildJoinQueryParams(params) {
|
|
57
|
+
const query = new URLSearchParams({
|
|
58
|
+
[TEAM_HUB_JOIN_QUERY_KEYS.url]: normalizeTeamHubBaseUrl(params.baseUrl),
|
|
59
|
+
[TEAM_HUB_JOIN_QUERY_KEYS.name]: params.name.trim(),
|
|
60
|
+
[TEAM_HUB_JOIN_QUERY_KEYS.role]: params.role,
|
|
61
|
+
[TEAM_HUB_JOIN_QUERY_KEYS.exp]: params.expiresAt
|
|
62
|
+
});
|
|
63
|
+
if (params.hubName?.trim()) {
|
|
64
|
+
query.set(TEAM_HUB_JOIN_QUERY_KEYS.hub, params.hubName.trim());
|
|
65
|
+
}
|
|
66
|
+
if (params.accessSummary?.trim()) {
|
|
67
|
+
query.set(TEAM_HUB_JOIN_QUERY_KEYS.access, params.accessSummary.trim());
|
|
68
|
+
}
|
|
69
|
+
return query;
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Parses shared invitation link query parameters into {@link InvitationLinkParams}.
|
|
73
|
+
*
|
|
74
|
+
* @param query - Parsed query string from an HTTPS or deep link.
|
|
75
|
+
* @param code - Invitation secret from the fragment or query string.
|
|
76
|
+
*/
|
|
77
|
+
function parseJoinQueryParams(query, code) {
|
|
78
|
+
const baseUrl = query.get(TEAM_HUB_JOIN_QUERY_KEYS.url)?.trim();
|
|
79
|
+
const name = query.get(TEAM_HUB_JOIN_QUERY_KEYS.name)?.trim();
|
|
80
|
+
const role = query.get(TEAM_HUB_JOIN_QUERY_KEYS.role)?.trim();
|
|
81
|
+
const expiresAt = query.get(TEAM_HUB_JOIN_QUERY_KEYS.exp)?.trim();
|
|
82
|
+
if (!baseUrl || !name || !role || !expiresAt || !isTeamHubBaseUrl(baseUrl)) {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
if (role !== 'admin' && role !== 'user') {
|
|
86
|
+
return null;
|
|
87
|
+
}
|
|
88
|
+
if (!isInvitationCodeFormat(code)) {
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
const hubName = query.get(TEAM_HUB_JOIN_QUERY_KEYS.hub)?.trim();
|
|
92
|
+
const accessSummary = query.get(TEAM_HUB_JOIN_QUERY_KEYS.access)?.trim();
|
|
93
|
+
return {
|
|
94
|
+
baseUrl: normalizeTeamHubBaseUrl(baseUrl),
|
|
95
|
+
code,
|
|
96
|
+
name,
|
|
97
|
+
role,
|
|
98
|
+
expiresAt,
|
|
99
|
+
hubName: hubName || undefined,
|
|
100
|
+
accessSummary: accessSummary || undefined
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Builds an HTTPS join link with display info in the query string and the
|
|
105
|
+
* invitation secret in the URL fragment.
|
|
106
|
+
*
|
|
107
|
+
* @param params - Invitation link parameters.
|
|
108
|
+
* @returns Clickable HTTPS join URL suitable for email and chat delivery.
|
|
109
|
+
*/
|
|
110
|
+
export function buildTeamHubJoinUrl(params) {
|
|
111
|
+
const baseUrl = normalizeTeamHubBaseUrl(params.baseUrl);
|
|
112
|
+
const query = buildJoinQueryParams(params);
|
|
113
|
+
const fragment = new URLSearchParams({
|
|
114
|
+
[TEAM_HUB_JOIN_QUERY_KEYS.code]: params.code.trim()
|
|
115
|
+
});
|
|
116
|
+
return `${baseUrl}/join?${query.toString()}#${fragment.toString()}`;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Parses an HTTPS Team Hub join link into invitation parameters.
|
|
120
|
+
*
|
|
121
|
+
* @param url - Raw HTTPS join URL from a browser or pasted invite link.
|
|
122
|
+
* @returns Parsed invitation parameters, or null when invalid.
|
|
123
|
+
*/
|
|
124
|
+
export function parseTeamHubJoinUrl(url) {
|
|
125
|
+
const trimmed = url.trim();
|
|
126
|
+
if (!trimmed) {
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
let parsed;
|
|
130
|
+
try {
|
|
131
|
+
parsed = new URL(trimmed);
|
|
132
|
+
}
|
|
133
|
+
catch {
|
|
134
|
+
return null;
|
|
135
|
+
}
|
|
136
|
+
if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
139
|
+
if (!parsed.pathname.endsWith('/join')) {
|
|
140
|
+
return null;
|
|
141
|
+
}
|
|
142
|
+
const fragmentParams = new URLSearchParams(parsed.hash.startsWith('#') ? parsed.hash.slice(1) : parsed.hash);
|
|
143
|
+
const code = fragmentParams.get(TEAM_HUB_JOIN_QUERY_KEYS.code)?.trim();
|
|
144
|
+
if (!code) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
return parseJoinQueryParams(parsed.searchParams, code);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Builds a harborclient:// join deep link with the invitation secret in the query.
|
|
151
|
+
*
|
|
152
|
+
* @param params - Invitation link parameters.
|
|
153
|
+
* @returns Deep link URL suitable for launching HarborClient.
|
|
154
|
+
*/
|
|
155
|
+
export function buildTeamHubJoinDeepLink(params) {
|
|
156
|
+
const query = buildJoinQueryParams(params);
|
|
157
|
+
query.set(TEAM_HUB_JOIN_QUERY_KEYS.code, params.code.trim());
|
|
158
|
+
return `${HARBOR_PROTOCOL}://team-hub/join?${query.toString()}`;
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parses a harborclient:// Team Hub join deep link into invitation parameters.
|
|
162
|
+
*
|
|
163
|
+
* @param url - Raw harborclient:// join URL from the OS protocol handler.
|
|
164
|
+
* @returns Parsed invitation parameters, or null when invalid.
|
|
165
|
+
*/
|
|
166
|
+
export function parseTeamHubJoinDeepLink(url) {
|
|
167
|
+
const trimmed = url.trim();
|
|
168
|
+
if (!trimmed) {
|
|
169
|
+
return null;
|
|
170
|
+
}
|
|
171
|
+
let parsed;
|
|
172
|
+
try {
|
|
173
|
+
parsed = new URL(trimmed);
|
|
174
|
+
}
|
|
175
|
+
catch {
|
|
176
|
+
return null;
|
|
177
|
+
}
|
|
178
|
+
if (parsed.protocol !== `${HARBOR_PROTOCOL}:`) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
if (parsed.hostname !== 'team-hub' || parsed.pathname !== '/join') {
|
|
182
|
+
return null;
|
|
183
|
+
}
|
|
184
|
+
const code = parsed.searchParams.get(TEAM_HUB_JOIN_QUERY_KEYS.code)?.trim();
|
|
185
|
+
if (!code) {
|
|
186
|
+
return null;
|
|
187
|
+
}
|
|
188
|
+
return parseJoinQueryParams(parsed.searchParams, code);
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Builds a short human-readable access summary from hub user access lists.
|
|
192
|
+
*
|
|
193
|
+
* @param input - Access list fields from a hub user record.
|
|
194
|
+
* @returns Summary string suitable for invite link query parameters.
|
|
195
|
+
*/
|
|
196
|
+
export function summarizeInvitationAccess(input) {
|
|
197
|
+
const parts = [];
|
|
198
|
+
parts.push(`Collections: ${formatAccessList(input.collectionAccess)}`);
|
|
199
|
+
parts.push(`Environments: ${formatAccessList(input.environmentAccess)}`);
|
|
200
|
+
parts.push(`Snippets: ${formatAccessList(input.snippetAccess)}`);
|
|
201
|
+
if (input.llmAccess) {
|
|
202
|
+
parts.push(`LLM: ${formatAccessList(input.llmModels)}`);
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
parts.push('LLM: disabled');
|
|
206
|
+
}
|
|
207
|
+
return parts.join(' · ');
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Formats one access list for display in invite summaries.
|
|
211
|
+
*
|
|
212
|
+
* @param values - Access list values from a hub user record.
|
|
213
|
+
*/
|
|
214
|
+
function formatAccessList(values) {
|
|
215
|
+
if (values.includes('*')) {
|
|
216
|
+
return 'all';
|
|
217
|
+
}
|
|
218
|
+
if (values.length === 0) {
|
|
219
|
+
return 'none';
|
|
220
|
+
}
|
|
221
|
+
return values.join(', ');
|
|
222
|
+
}
|