@keeper-security/keeper-sdk-javascript 0.1.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/auth/ConsoleAuthUI.d.ts +10 -0
- package/dist/auth/ConsoleAuthUI.js +152 -0
- package/dist/auth/ConsoleAuthUI.js.map +1 -0
- package/dist/auth/ConsoleLogin.d.ts +8 -0
- package/dist/auth/ConsoleLogin.js +266 -0
- package/dist/auth/ConsoleLogin.js.map +1 -0
- package/dist/auth/SessionManager.d.ts +66 -0
- package/dist/auth/SessionManager.js +211 -0
- package/dist/auth/SessionManager.js.map +1 -0
- package/dist/index.d.ts +17 -0
- package/dist/index.js +61 -0
- package/dist/index.js.map +1 -0
- package/dist/records/RecordOperations.d.ts +79 -0
- package/dist/records/RecordOperations.js +346 -0
- package/dist/records/RecordOperations.js.map +1 -0
- package/dist/records/RecordUtils.d.ts +36 -0
- package/dist/records/RecordUtils.js +224 -0
- package/dist/records/RecordUtils.js.map +1 -0
- package/dist/sharing/Sharing.d.ts +27 -0
- package/dist/sharing/Sharing.js +125 -0
- package/dist/sharing/Sharing.js.map +1 -0
- package/dist/src/auth/ConsoleAuthUI.d.ts +10 -0
- package/dist/src/auth/ConsoleAuthUI.js +161 -0
- package/dist/src/auth/ConsoleAuthUI.js.map +1 -0
- package/dist/src/auth/ConsoleLogin.d.ts +8 -0
- package/dist/src/auth/ConsoleLogin.js +311 -0
- package/dist/src/auth/ConsoleLogin.js.map +1 -0
- package/dist/src/auth/SessionManager.d.ts +67 -0
- package/dist/src/auth/SessionManager.js +212 -0
- package/dist/src/auth/SessionManager.js.map +1 -0
- package/dist/src/folders/FolderManager.d.ts +57 -0
- package/dist/src/folders/FolderManager.js +108 -0
- package/dist/src/folders/FolderManager.js.map +1 -0
- package/dist/src/folders/addFolder.d.ts +32 -0
- package/dist/src/folders/addFolder.js +207 -0
- package/dist/src/folders/addFolder.js.map +1 -0
- package/dist/src/folders/changeDirectory.d.ts +19 -0
- package/dist/src/folders/changeDirectory.js +171 -0
- package/dist/src/folders/changeDirectory.js.map +1 -0
- package/dist/src/folders/deleteFolder.d.ts +17 -0
- package/dist/src/folders/deleteFolder.js +237 -0
- package/dist/src/folders/deleteFolder.js.map +1 -0
- package/dist/src/folders/folderHelpers.d.ts +48 -0
- package/dist/src/folders/folderHelpers.js +100 -0
- package/dist/src/folders/folderHelpers.js.map +1 -0
- package/dist/src/folders/folderTree.d.ts +29 -0
- package/dist/src/folders/folderTree.js +250 -0
- package/dist/src/folders/folderTree.js.map +1 -0
- package/dist/src/folders/getFolder.d.ts +56 -0
- package/dist/src/folders/getFolder.js +143 -0
- package/dist/src/folders/getFolder.js.map +1 -0
- package/dist/src/folders/listFolder.d.ts +48 -0
- package/dist/src/folders/listFolder.js +276 -0
- package/dist/src/folders/listFolder.js.map +1 -0
- package/dist/src/folders/updateFolder.d.ts +31 -0
- package/dist/src/folders/updateFolder.js +137 -0
- package/dist/src/folders/updateFolder.js.map +1 -0
- package/dist/src/index.d.ts +49 -0
- package/dist/src/index.js +151 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/records/RecordOperations.d.ts +80 -0
- package/dist/src/records/RecordOperations.js +356 -0
- package/dist/src/records/RecordOperations.js.map +1 -0
- package/dist/src/records/RecordUtils.d.ts +37 -0
- package/dist/src/records/RecordUtils.js +263 -0
- package/dist/src/records/RecordUtils.js.map +1 -0
- package/dist/src/records/Totp.d.ts +14 -0
- package/dist/src/records/Totp.js +111 -0
- package/dist/src/records/Totp.js.map +1 -0
- package/dist/src/sharedFolders/SharedFolderManager.d.ts +20 -0
- package/dist/src/sharedFolders/SharedFolderManager.js +33 -0
- package/dist/src/sharedFolders/SharedFolderManager.js.map +1 -0
- package/dist/src/sharedFolders/listSharedFolders.d.ts +29 -0
- package/dist/src/sharedFolders/listSharedFolders.js +127 -0
- package/dist/src/sharedFolders/listSharedFolders.js.map +1 -0
- package/dist/src/sharedFolders/shareFolder.d.ts +36 -0
- package/dist/src/sharedFolders/shareFolder.js +352 -0
- package/dist/src/sharedFolders/shareFolder.js.map +1 -0
- package/dist/src/sharing/Sharing.d.ts +50 -0
- package/dist/src/sharing/Sharing.js +195 -0
- package/dist/src/sharing/Sharing.js.map +1 -0
- package/dist/src/storage/InMemoryStorage.d.ts +24 -0
- package/dist/src/storage/InMemoryStorage.js +139 -0
- package/dist/src/storage/InMemoryStorage.js.map +1 -0
- package/dist/src/teams/TeamManager.d.ts +17 -0
- package/dist/src/teams/TeamManager.js +38 -0
- package/dist/src/teams/TeamManager.js.map +1 -0
- package/dist/src/teams/enterpriseData.d.ts +106 -0
- package/dist/src/teams/enterpriseData.js +319 -0
- package/dist/src/teams/enterpriseData.js.map +1 -0
- package/dist/src/teams/listTeams.d.ts +42 -0
- package/dist/src/teams/listTeams.js +308 -0
- package/dist/src/teams/listTeams.js.map +1 -0
- package/dist/src/teams/viewTeam.d.ts +35 -0
- package/dist/src/teams/viewTeam.js +177 -0
- package/dist/src/teams/viewTeam.js.map +1 -0
- package/dist/src/utils/Logger.d.ts +28 -0
- package/dist/src/utils/Logger.js +62 -0
- package/dist/src/utils/Logger.js.map +1 -0
- package/dist/src/utils/constants.d.ts +50 -0
- package/dist/src/utils/constants.js +64 -0
- package/dist/src/utils/constants.js.map +1 -0
- package/dist/src/utils/errors.d.ts +10 -0
- package/dist/src/utils/errors.js +117 -0
- package/dist/src/utils/errors.js.map +1 -0
- package/dist/src/utils/guards.d.ts +7 -0
- package/dist/src/utils/guards.js +29 -0
- package/dist/src/utils/guards.js.map +1 -0
- package/dist/src/utils/index.d.ts +7 -0
- package/dist/src/utils/index.js +39 -0
- package/dist/src/utils/index.js.map +1 -0
- package/dist/src/utils/patterns.d.ts +9 -0
- package/dist/src/utils/patterns.js +20 -0
- package/dist/src/utils/patterns.js.map +1 -0
- package/dist/src/utils/types.d.ts +12 -0
- package/dist/src/utils/types.js +3 -0
- package/dist/src/utils/types.js.map +1 -0
- package/dist/src/vault/KeeperVault.d.ts +116 -0
- package/dist/src/vault/KeeperVault.js +443 -0
- package/dist/src/vault/KeeperVault.js.map +1 -0
- package/dist/storage/InMemoryStorage.d.ts +24 -0
- package/dist/storage/InMemoryStorage.js +132 -0
- package/dist/storage/InMemoryStorage.js.map +1 -0
- package/dist/utils/Logger.d.ts +28 -0
- package/dist/utils/Logger.js +62 -0
- package/dist/utils/Logger.js.map +1 -0
- package/dist/utils/constants.d.ts +26 -0
- package/dist/utils/constants.js +37 -0
- package/dist/utils/constants.js.map +1 -0
- package/dist/utils/errors.d.ts +10 -0
- package/dist/utils/errors.js +117 -0
- package/dist/utils/errors.js.map +1 -0
- package/dist/utils/index.d.ts +4 -0
- package/dist/utils/index.js +22 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/vault/KeeperVault.d.ts +72 -0
- package/dist/vault/KeeperVault.js +338 -0
- package/dist/vault/KeeperVault.js.map +1 -0
- package/package.json +32 -0
- package/src/auth/ConsoleAuthUI.ts +169 -0
- package/src/auth/ConsoleLogin.ts +351 -0
- package/src/auth/SessionManager.ts +293 -0
- package/src/folders/FolderManager.ts +174 -0
- package/src/folders/addFolder.ts +294 -0
- package/src/folders/changeDirectory.ts +217 -0
- package/src/folders/deleteFolder.ts +293 -0
- package/src/folders/folderHelpers.ts +99 -0
- package/src/folders/folderTree.ts +321 -0
- package/src/folders/getFolder.ts +234 -0
- package/src/folders/listFolder.ts +358 -0
- package/src/folders/updateFolder.ts +210 -0
- package/src/index.ts +242 -0
- package/src/records/RecordOperations.ts +549 -0
- package/src/records/RecordUtils.ts +282 -0
- package/src/records/Totp.ts +119 -0
- package/src/sharedFolders/SharedFolderManager.ts +57 -0
- package/src/sharedFolders/listSharedFolders.ts +173 -0
- package/src/sharedFolders/shareFolder.ts +457 -0
- package/src/sharing/Sharing.ts +282 -0
- package/src/storage/InMemoryStorage.ts +163 -0
- package/src/teams/TeamManager.ts +61 -0
- package/src/teams/enterpriseData.ts +453 -0
- package/src/teams/listTeams.ts +373 -0
- package/src/teams/viewTeam.ts +248 -0
- package/src/utils/Logger.ts +71 -0
- package/src/utils/constants.ts +63 -0
- package/src/utils/errors.ts +108 -0
- package/src/utils/guards.ts +24 -0
- package/src/utils/index.ts +22 -0
- package/src/utils/patterns.ts +20 -0
- package/src/utils/types.ts +11 -0
- package/src/vault/KeeperVault.ts +612 -0
- package/tsconfig.json +16 -0
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import type { Auth } from '@keeper-security/keeperapi'
|
|
2
|
+
import { isNumber, TOKEN_SEPARATOR_PATTERN } from '../utils'
|
|
3
|
+
import {
|
|
4
|
+
EnterpriseDataInclude,
|
|
5
|
+
EnterpriseDataManager,
|
|
6
|
+
type DecryptedRoleNames,
|
|
7
|
+
type EnterpriseDisplayNames,
|
|
8
|
+
type EnterpriseNode,
|
|
9
|
+
type EnterpriseRole,
|
|
10
|
+
type EnterpriseTeamRecord,
|
|
11
|
+
type EnterpriseTeamUserLink,
|
|
12
|
+
type EnterpriseUser,
|
|
13
|
+
type GetEnterpriseDataResponse,
|
|
14
|
+
} from './enterpriseData'
|
|
15
|
+
|
|
16
|
+
export enum TeamColumn {
|
|
17
|
+
Restricts = 'restricts',
|
|
18
|
+
Node = 'node',
|
|
19
|
+
UserCount = 'user_count',
|
|
20
|
+
Users = 'users',
|
|
21
|
+
RoleCount = 'role_count',
|
|
22
|
+
Roles = 'roles',
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export type TeamColumnInput = TeamColumn | `${TeamColumn}`
|
|
26
|
+
|
|
27
|
+
export const SUPPORTED_TEAM_COLUMNS: readonly TeamColumn[] = Object.values(TeamColumn)
|
|
28
|
+
|
|
29
|
+
export const DEFAULT_TEAM_COLUMNS: readonly TeamColumn[] = [
|
|
30
|
+
TeamColumn.Restricts,
|
|
31
|
+
TeamColumn.Node,
|
|
32
|
+
TeamColumn.UserCount,
|
|
33
|
+
TeamColumn.RoleCount,
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
const NODE_PATH_SEPARATOR = '\\'
|
|
37
|
+
const MIN_ASCII_COL_WIDTH = 2
|
|
38
|
+
const ALL_COLUMNS_WILDCARD = '*'
|
|
39
|
+
|
|
40
|
+
const HEADER_BY_COLUMN: Record<TeamColumn, string> = {
|
|
41
|
+
[TeamColumn.Restricts]: 'Restricts',
|
|
42
|
+
[TeamColumn.Node]: 'Node',
|
|
43
|
+
[TeamColumn.UserCount]: 'User Count',
|
|
44
|
+
[TeamColumn.Users]: 'Users',
|
|
45
|
+
[TeamColumn.RoleCount]: 'Role Count',
|
|
46
|
+
[TeamColumn.Roles]: 'Roles',
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export type ListTeamsOptions = {
|
|
50
|
+
pattern?: string | null
|
|
51
|
+
columns?: TeamColumnInput[] | typeof ALL_COLUMNS_WILDCARD | string | null
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export type ListTeamRow = {
|
|
55
|
+
team_uid: string
|
|
56
|
+
name: string
|
|
57
|
+
restricts?: string
|
|
58
|
+
node?: string
|
|
59
|
+
user_count?: number
|
|
60
|
+
users?: string[]
|
|
61
|
+
role_count?: number
|
|
62
|
+
roles?: string[]
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export type FormattedTeamsTable = {
|
|
66
|
+
headers: string[]
|
|
67
|
+
rows: string[][]
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
export type FormatTeamsTableOptions = {
|
|
71
|
+
columns?: ListTeamsOptions['columns']
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
type DecorateContext = {
|
|
75
|
+
nodePaths: Map<number, string>
|
|
76
|
+
teamUsers: Map<string, Set<number>>
|
|
77
|
+
roleTeams: Map<string, Set<number>>
|
|
78
|
+
usernameById: Map<number, string>
|
|
79
|
+
roleNameById: Map<number, string>
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function formatTeamRestricts(team: EnterpriseTeamRecord): string {
|
|
83
|
+
const r = team.restrict_view === true ? 'R ' : ' '
|
|
84
|
+
const w = team.restrict_edit === true ? 'W ' : ' '
|
|
85
|
+
const restrictShare = team.restrict_share === true || team.restrict_sharing === true
|
|
86
|
+
const s = restrictShare ? 'S' : ' '
|
|
87
|
+
return r + w + s
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export async function listTeams(auth: Auth, options: ListTeamsOptions = {}): Promise<ListTeamRow[]> {
|
|
91
|
+
const columns = resolveColumns(options.columns)
|
|
92
|
+
const includes = includesForColumns(columns)
|
|
93
|
+
const wantsDisplayNames = columns.includes(TeamColumn.Node) || columns.includes(TeamColumn.Roles)
|
|
94
|
+
|
|
95
|
+
const enterpriseData = new EnterpriseDataManager(auth)
|
|
96
|
+
const emptyDisplayNames: EnterpriseDisplayNames = { nodes: new Map(), roles: new Map() }
|
|
97
|
+
const [response, displayNames] = await Promise.all([
|
|
98
|
+
enterpriseData.getData(includes),
|
|
99
|
+
wantsDisplayNames ? enterpriseData.getDisplayNames() : Promise.resolve(emptyDisplayNames),
|
|
100
|
+
])
|
|
101
|
+
|
|
102
|
+
const teams = response.teams || []
|
|
103
|
+
const nodes = response.nodes || []
|
|
104
|
+
applyDecryptedNodeNames(nodes, displayNames.nodes)
|
|
105
|
+
|
|
106
|
+
const context: DecorateContext = {
|
|
107
|
+
nodePaths: buildNodePathLookup(nodes),
|
|
108
|
+
teamUsers: buildTeamUserMap(response.team_users || []),
|
|
109
|
+
roleTeams: buildRoleTeamMap(response),
|
|
110
|
+
usernameById: buildUserUsernameMap(response.users || []),
|
|
111
|
+
roleNameById: buildRoleNameMap(response.roles || [], displayNames.roles),
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
const pattern = options.pattern?.trim() || null
|
|
115
|
+
const rows: ListTeamRow[] = []
|
|
116
|
+
for (const team of teams) {
|
|
117
|
+
const row: ListTeamRow = {
|
|
118
|
+
team_uid: team.team_uid,
|
|
119
|
+
name: teamDisplayName(team),
|
|
120
|
+
}
|
|
121
|
+
decorateRow(row, team, columns, context)
|
|
122
|
+
if (pattern && !rowMatchesPattern(row, pattern)) continue
|
|
123
|
+
rows.push(row)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
rows.sort((a, b) => a.name.localeCompare(b.name, undefined, { sensitivity: 'base' }))
|
|
127
|
+
return rows
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export function formatTeamsTable(
|
|
131
|
+
rows: ListTeamRow[],
|
|
132
|
+
options: FormatTeamsTableOptions = {}
|
|
133
|
+
): FormattedTeamsTable {
|
|
134
|
+
const columns = resolveColumns(options.columns)
|
|
135
|
+
const headers: string[] = ['#', 'Team UID', 'Name', ...columns.map((column) => HEADER_BY_COLUMN[column])]
|
|
136
|
+
|
|
137
|
+
const outRows: string[][] = rows.map((row, rowIndex) => {
|
|
138
|
+
const cells: string[] = [String(rowIndex + 1), row.team_uid, row.name]
|
|
139
|
+
for (const column of columns) cells.push(formatCell(row, column))
|
|
140
|
+
return cells
|
|
141
|
+
})
|
|
142
|
+
|
|
143
|
+
return { headers, rows: outRows }
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export function renderTeamsAsciiTable(
|
|
147
|
+
table: FormattedTeamsTable,
|
|
148
|
+
options: { minColWidth?: number } = {}
|
|
149
|
+
): string {
|
|
150
|
+
const { minColWidth = MIN_ASCII_COL_WIDTH } = options
|
|
151
|
+
const { headers, rows } = table
|
|
152
|
+
const columnCount = headers.length
|
|
153
|
+
|
|
154
|
+
const expandedRows: string[][][] = rows.map((row) =>
|
|
155
|
+
row.map((cell) => (cell.includes('\n') ? cell.split('\n') : [cell]))
|
|
156
|
+
)
|
|
157
|
+
|
|
158
|
+
const columnWidths = new Array<number>(columnCount).fill(0)
|
|
159
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex += 1) {
|
|
160
|
+
columnWidths[columnIndex] = Math.max(headers[columnIndex].length, minColWidth)
|
|
161
|
+
}
|
|
162
|
+
for (const row of expandedRows) {
|
|
163
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex += 1) {
|
|
164
|
+
for (const line of row[columnIndex]) {
|
|
165
|
+
columnWidths[columnIndex] = Math.max(columnWidths[columnIndex], line.length, minColWidth)
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
const padCell = (cell: string, columnIndex: number): string =>
|
|
171
|
+
cell + ' '.repeat(columnWidths[columnIndex] - cell.length)
|
|
172
|
+
const formatPhysicalRow = (cells: string[]): string =>
|
|
173
|
+
cells.map((cell, columnIndex) => padCell(cell, columnIndex)).join(' ')
|
|
174
|
+
|
|
175
|
+
const ruleRow = formatPhysicalRow(columnWidths.map((width) => '-'.repeat(width)))
|
|
176
|
+
const lines: string[] = [formatPhysicalRow(headers), ruleRow]
|
|
177
|
+
|
|
178
|
+
for (const row of expandedRows) {
|
|
179
|
+
const physicalLineCount = Math.max(...row.map((cell) => cell.length))
|
|
180
|
+
for (let lineIndex = 0; lineIndex < physicalLineCount; lineIndex += 1) {
|
|
181
|
+
const physicalCells: string[] = row.map((cell) => cell[lineIndex] ?? '')
|
|
182
|
+
lines.push(formatPhysicalRow(physicalCells))
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
return lines.join('\n')
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
function includesForColumns(columns: readonly TeamColumn[]): EnterpriseDataInclude[] {
|
|
189
|
+
const set = new Set<EnterpriseDataInclude>([EnterpriseDataInclude.Teams])
|
|
190
|
+
for (const column of columns) {
|
|
191
|
+
switch (column) {
|
|
192
|
+
case TeamColumn.Node:
|
|
193
|
+
set.add(EnterpriseDataInclude.Nodes)
|
|
194
|
+
break
|
|
195
|
+
case TeamColumn.UserCount:
|
|
196
|
+
case TeamColumn.Users:
|
|
197
|
+
set.add(EnterpriseDataInclude.TeamUsers)
|
|
198
|
+
if (column === TeamColumn.Users) set.add(EnterpriseDataInclude.Users)
|
|
199
|
+
break
|
|
200
|
+
case TeamColumn.RoleCount:
|
|
201
|
+
case TeamColumn.Roles:
|
|
202
|
+
set.add(EnterpriseDataInclude.RoleTeams)
|
|
203
|
+
if (column === TeamColumn.Roles) set.add(EnterpriseDataInclude.Roles)
|
|
204
|
+
break
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return Array.from(set)
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
function resolveColumns(input: ListTeamsOptions['columns']): TeamColumn[] {
|
|
211
|
+
if (input == null) return [...DEFAULT_TEAM_COLUMNS]
|
|
212
|
+
if (input === ALL_COLUMNS_WILDCARD) return [...SUPPORTED_TEAM_COLUMNS]
|
|
213
|
+
|
|
214
|
+
const requested = Array.isArray(input) ? input : input.split(',').map((part) => part.trim())
|
|
215
|
+
const allowed = new Set<string>(SUPPORTED_TEAM_COLUMNS)
|
|
216
|
+
const seen = new Set<TeamColumn>()
|
|
217
|
+
for (const column of requested) {
|
|
218
|
+
if (column && allowed.has(column)) seen.add(column as TeamColumn)
|
|
219
|
+
}
|
|
220
|
+
if (seen.size === 0) return [...DEFAULT_TEAM_COLUMNS]
|
|
221
|
+
return SUPPORTED_TEAM_COLUMNS.filter((column) => seen.has(column))
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function teamDisplayName(team: { name?: string; team_uid: string }): string {
|
|
225
|
+
return (team.name || team.team_uid || '').trim() || team.team_uid
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
function tokenize(text: string): string[] {
|
|
229
|
+
return text.split(TOKEN_SEPARATOR_PATTERN).filter((token) => token.length > 0)
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function rowMatchesPattern(row: ListTeamRow, pattern: string): boolean {
|
|
233
|
+
const lowered = pattern.toLowerCase()
|
|
234
|
+
const tokens: string[] = []
|
|
235
|
+
tokens.push(row.team_uid.toLowerCase())
|
|
236
|
+
tokens.push(...tokenize(row.name.toLowerCase()))
|
|
237
|
+
if (row.restricts) tokens.push(row.restricts.toLowerCase())
|
|
238
|
+
if (row.node) tokens.push(...tokenize(row.node.toLowerCase()))
|
|
239
|
+
if (row.user_count != null) tokens.push(String(row.user_count))
|
|
240
|
+
if (row.role_count != null) tokens.push(String(row.role_count))
|
|
241
|
+
for (const list of [row.users, row.roles]) {
|
|
242
|
+
if (!list) continue
|
|
243
|
+
for (const value of list) tokens.push(...tokenize(value.toLowerCase()))
|
|
244
|
+
}
|
|
245
|
+
return tokens.some((token) => token.includes(lowered))
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
function applyDecryptedNodeNames(nodes: EnterpriseNode[], decrypted: Map<number, string>): void {
|
|
249
|
+
if (decrypted.size === 0) return
|
|
250
|
+
for (const node of nodes) {
|
|
251
|
+
const display = decrypted.get(node.node_id)
|
|
252
|
+
if (display) node.displayName = display
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
function buildNodePathLookup(nodes: EnterpriseNode[]): Map<number, string> {
|
|
257
|
+
return new Map(
|
|
258
|
+
nodes.map((node) => [
|
|
259
|
+
node.node_id,
|
|
260
|
+
EnterpriseDataManager.getNodePath(nodes, node.node_id, { separator: NODE_PATH_SEPARATOR }),
|
|
261
|
+
])
|
|
262
|
+
)
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
function buildTeamUserMap(links: EnterpriseTeamUserLink[]): Map<string, Set<number>> {
|
|
266
|
+
const byTeam = new Map<string, Set<number>>()
|
|
267
|
+
for (const link of links) {
|
|
268
|
+
if (!link.team_uid) continue
|
|
269
|
+
const set = byTeam.get(link.team_uid)
|
|
270
|
+
if (set) set.add(link.enterprise_user_id)
|
|
271
|
+
else byTeam.set(link.team_uid, new Set([link.enterprise_user_id]))
|
|
272
|
+
}
|
|
273
|
+
return byTeam
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function buildRoleTeamMap(response: GetEnterpriseDataResponse): Map<string, Set<number>> {
|
|
277
|
+
const map = new Map<string, Set<number>>()
|
|
278
|
+
for (const link of response.role_teams || []) {
|
|
279
|
+
if (!link.team_uid) continue
|
|
280
|
+
const set = map.get(link.team_uid)
|
|
281
|
+
if (set) set.add(link.role_id)
|
|
282
|
+
else map.set(link.team_uid, new Set([link.role_id]))
|
|
283
|
+
}
|
|
284
|
+
return map
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
function buildUserUsernameMap(users: EnterpriseUser[]): Map<number, string> {
|
|
288
|
+
const map = new Map<number, string>()
|
|
289
|
+
for (const user of users) {
|
|
290
|
+
if (isNumber(user.enterprise_user_id ) && user.username) {
|
|
291
|
+
map.set(user.enterprise_user_id, user.username)
|
|
292
|
+
}
|
|
293
|
+
}
|
|
294
|
+
return map
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function buildRoleNameMap(roles: EnterpriseRole[], decrypted: DecryptedRoleNames): Map<number, string> {
|
|
298
|
+
const map = new Map<number, string>()
|
|
299
|
+
for (const role of roles) {
|
|
300
|
+
if (isNumber(role.role_id)) continue
|
|
301
|
+
const display = (role.displayName || decrypted.get(role.role_id) || '').trim()
|
|
302
|
+
map.set(role.role_id, display || String(role.role_id))
|
|
303
|
+
}
|
|
304
|
+
return map
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function resolveSortedNames(ids: Set<number>, nameById: Map<number, string>): string[] {
|
|
308
|
+
const result: string[] = []
|
|
309
|
+
for (const id of ids) {
|
|
310
|
+
const name = nameById.get(id)
|
|
311
|
+
if (name) result.push(name)
|
|
312
|
+
}
|
|
313
|
+
result.sort((a, b) => a.localeCompare(b, undefined, { sensitivity: 'base' }))
|
|
314
|
+
return result
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
function decorateRow(
|
|
318
|
+
row: ListTeamRow,
|
|
319
|
+
team: EnterpriseTeamRecord,
|
|
320
|
+
columns: readonly TeamColumn[],
|
|
321
|
+
context: DecorateContext
|
|
322
|
+
): void {
|
|
323
|
+
const { nodePaths, teamUsers, roleTeams, usernameById, roleNameById } = context
|
|
324
|
+
|
|
325
|
+
for (const column of columns) {
|
|
326
|
+
switch (column) {
|
|
327
|
+
case TeamColumn.Restricts:
|
|
328
|
+
row.restricts = formatTeamRestricts(team)
|
|
329
|
+
break
|
|
330
|
+
case TeamColumn.Node:
|
|
331
|
+
row.node = nodePaths.get(team.node_id) || ''
|
|
332
|
+
break
|
|
333
|
+
case TeamColumn.UserCount:
|
|
334
|
+
row.user_count = teamUsers.get(team.team_uid)?.size ?? 0
|
|
335
|
+
break
|
|
336
|
+
case TeamColumn.Users: {
|
|
337
|
+
const ids = teamUsers.get(team.team_uid)
|
|
338
|
+
row.users = ids ? resolveSortedNames(ids, usernameById) : []
|
|
339
|
+
break
|
|
340
|
+
}
|
|
341
|
+
case TeamColumn.RoleCount:
|
|
342
|
+
row.role_count = roleTeams.get(team.team_uid)?.size ?? 0
|
|
343
|
+
break
|
|
344
|
+
case TeamColumn.Roles: {
|
|
345
|
+
const ids = roleTeams.get(team.team_uid)
|
|
346
|
+
row.roles = ids ? resolveSortedNames(ids, roleNameById) : []
|
|
347
|
+
break
|
|
348
|
+
}
|
|
349
|
+
}
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
function formatListCell(values: string[] | undefined): string {
|
|
354
|
+
if (!values || values.length === 0) return ''
|
|
355
|
+
return values.join('\n')
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
function formatCell(row: ListTeamRow, column: TeamColumn): string {
|
|
359
|
+
switch (column) {
|
|
360
|
+
case TeamColumn.Restricts:
|
|
361
|
+
return row.restricts ?? ''
|
|
362
|
+
case TeamColumn.Node:
|
|
363
|
+
return row.node ?? ''
|
|
364
|
+
case TeamColumn.UserCount:
|
|
365
|
+
return row.user_count == null ? '' : String(row.user_count)
|
|
366
|
+
case TeamColumn.Users:
|
|
367
|
+
return formatListCell(row.users)
|
|
368
|
+
case TeamColumn.RoleCount:
|
|
369
|
+
return row.role_count == null ? '' : String(row.role_count)
|
|
370
|
+
case TeamColumn.Roles:
|
|
371
|
+
return formatListCell(row.roles)
|
|
372
|
+
}
|
|
373
|
+
}
|
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
import type { Auth } from '@keeper-security/keeperapi'
|
|
2
|
+
import { KeeperSdkError, ResultCodes } from '../utils'
|
|
3
|
+
import {
|
|
4
|
+
EnterpriseDataInclude,
|
|
5
|
+
EnterpriseDataManager,
|
|
6
|
+
type EnterpriseDisplayNames,
|
|
7
|
+
type EnterpriseNode,
|
|
8
|
+
type EnterpriseRoleTeamLink,
|
|
9
|
+
type EnterpriseTeamRecord,
|
|
10
|
+
type EnterpriseTeamUserLink,
|
|
11
|
+
type EnterpriseUser,
|
|
12
|
+
} from './enterpriseData'
|
|
13
|
+
|
|
14
|
+
const NODE_PATH_SEPARATOR = '\\'
|
|
15
|
+
const VIEW_TEAM_INCLUDES: EnterpriseDataInclude[] = [
|
|
16
|
+
EnterpriseDataInclude.Teams,
|
|
17
|
+
EnterpriseDataInclude.TeamUsers,
|
|
18
|
+
EnterpriseDataInclude.RoleTeams,
|
|
19
|
+
EnterpriseDataInclude.Roles,
|
|
20
|
+
EnterpriseDataInclude.Users,
|
|
21
|
+
EnterpriseDataInclude.Nodes,
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
export type TeamRoleInfo = {
|
|
25
|
+
role_id: number
|
|
26
|
+
role_name: string
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export type TeamUserInfo = {
|
|
30
|
+
enterprise_user_id: number
|
|
31
|
+
username: string
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export type TeamView = {
|
|
35
|
+
team_uid: string
|
|
36
|
+
team_name: string
|
|
37
|
+
node_id: number
|
|
38
|
+
node_name: string
|
|
39
|
+
restrict_view: boolean
|
|
40
|
+
restrict_edit: boolean
|
|
41
|
+
restrict_share: boolean
|
|
42
|
+
team_roles?: TeamRoleInfo[]
|
|
43
|
+
team_users?: TeamUserInfo[]
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type FormatTeamViewOptions = {
|
|
47
|
+
verbose?: boolean
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export type TeamViewTableRow = {
|
|
51
|
+
label: string
|
|
52
|
+
value: string | string[]
|
|
53
|
+
id?: number | number[]
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type FormattedTeamViewTable = {
|
|
57
|
+
rows: TeamViewTableRow[]
|
|
58
|
+
hasIdColumn: boolean
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export async function viewTeam(auth: Auth, identifier: string): Promise<TeamView> {
|
|
62
|
+
const enterpriseData = new EnterpriseDataManager(auth)
|
|
63
|
+
const [response, displayNames] = await Promise.all([
|
|
64
|
+
enterpriseData.getData(VIEW_TEAM_INCLUDES),
|
|
65
|
+
enterpriseData.getDisplayNames(),
|
|
66
|
+
])
|
|
67
|
+
|
|
68
|
+
const team = resolveTeam(response.teams || [], identifier)
|
|
69
|
+
const nodePath = resolveNodePath(response.nodes || [], displayNames, team.node_id)
|
|
70
|
+
const teamUsers = buildTeamUsers(response.users || [], response.team_users || [], team.team_uid)
|
|
71
|
+
const teamRoles = buildTeamRoles(response.role_teams || [], displayNames.roles, team.team_uid)
|
|
72
|
+
|
|
73
|
+
const view: TeamView = {
|
|
74
|
+
team_uid: team.team_uid,
|
|
75
|
+
team_name: team.name,
|
|
76
|
+
node_id: team.node_id,
|
|
77
|
+
node_name: nodePath,
|
|
78
|
+
restrict_view: team.restrict_view === true,
|
|
79
|
+
restrict_edit: team.restrict_edit === true,
|
|
80
|
+
restrict_share: team.restrict_share === true || team.restrict_sharing === true,
|
|
81
|
+
}
|
|
82
|
+
if (teamRoles.length > 0) view.team_roles = teamRoles
|
|
83
|
+
if (teamUsers.length > 0) view.team_users = teamUsers
|
|
84
|
+
return view
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function formatTeamView(view: TeamView, options: FormatTeamViewOptions = {}): FormattedTeamViewTable {
|
|
88
|
+
const verbose = options.verbose === true
|
|
89
|
+
const rows: TeamViewTableRow[] = [
|
|
90
|
+
{ label: 'Team UID', value: view.team_uid },
|
|
91
|
+
{ label: 'Team Name', value: view.team_name },
|
|
92
|
+
{
|
|
93
|
+
label: 'Node Name',
|
|
94
|
+
value: view.node_name,
|
|
95
|
+
id: verbose ? view.node_id : undefined,
|
|
96
|
+
},
|
|
97
|
+
{ label: 'Restrict Edit', value: boolText(view.restrict_edit) },
|
|
98
|
+
{ label: 'Restrict Share', value: boolText(view.restrict_share) },
|
|
99
|
+
{ label: 'Restrict View', value: boolText(view.restrict_view) },
|
|
100
|
+
]
|
|
101
|
+
|
|
102
|
+
if (view.team_roles && view.team_roles.length > 0) {
|
|
103
|
+
rows.push({
|
|
104
|
+
label: 'Role(s)',
|
|
105
|
+
value: view.team_roles.map((role) => role.role_name),
|
|
106
|
+
id: verbose ? view.team_roles.map((role) => role.role_id) : undefined,
|
|
107
|
+
})
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (view.team_users && view.team_users.length > 0) {
|
|
111
|
+
rows.push({
|
|
112
|
+
label: 'User(s)',
|
|
113
|
+
value: view.team_users.map((user) => user.username),
|
|
114
|
+
id: verbose ? view.team_users.map((user) => user.enterprise_user_id) : undefined,
|
|
115
|
+
})
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
return { rows, hasIdColumn: verbose }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
export function teamViewTable(table: FormattedTeamViewTable): string {
|
|
122
|
+
const labelWidth = table.rows.reduce((max, row) => Math.max(max, row.label.length), 0)
|
|
123
|
+
const expandedRows = table.rows.map((row) => ({
|
|
124
|
+
label: row.label,
|
|
125
|
+
valueLines: asLines(row.value),
|
|
126
|
+
idLines: table.hasIdColumn ? asIdLines(row.id) : [],
|
|
127
|
+
}))
|
|
128
|
+
|
|
129
|
+
const valueWidth = expandedRows.reduce(
|
|
130
|
+
(max, row) => Math.max(max, ...row.valueLines.map((line) => line.length)),
|
|
131
|
+
0
|
|
132
|
+
)
|
|
133
|
+
const idWidth = table.hasIdColumn
|
|
134
|
+
? expandedRows.reduce((max, row) => Math.max(max, ...row.idLines.map((line) => line.length)), 0)
|
|
135
|
+
: 0
|
|
136
|
+
|
|
137
|
+
const padRight = (text: string, width: number): string =>
|
|
138
|
+
text + ' '.repeat(Math.max(0, width - text.length))
|
|
139
|
+
const padLeft = (text: string, width: number): string =>
|
|
140
|
+
' '.repeat(Math.max(0, width - text.length)) + text
|
|
141
|
+
|
|
142
|
+
const lines: string[] = []
|
|
143
|
+
for (const row of expandedRows) {
|
|
144
|
+
const lineCount = Math.max(row.valueLines.length, table.hasIdColumn ? row.idLines.length : 0, 1)
|
|
145
|
+
for (let lineIndex = 0; lineIndex < lineCount; lineIndex += 1) {
|
|
146
|
+
const isFirstLine = lineIndex === 0
|
|
147
|
+
const labelCell = padLeft(isFirstLine ? row.label : '', labelWidth)
|
|
148
|
+
const valueCell = padRight(row.valueLines[lineIndex] ?? '', valueWidth)
|
|
149
|
+
const cells: string[] = [labelCell, valueCell]
|
|
150
|
+
if (table.hasIdColumn) {
|
|
151
|
+
const idCell = padRight(row.idLines[lineIndex] ?? '', idWidth)
|
|
152
|
+
cells.push(idCell)
|
|
153
|
+
}
|
|
154
|
+
lines.push(cells.join(' ').trimEnd())
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return lines.join('\n')
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function resolveTeam(teams: EnterpriseTeamRecord[], identifier: string): EnterpriseTeamRecord {
|
|
161
|
+
const trimmed = (identifier ?? '').trim()
|
|
162
|
+
if (!trimmed) {
|
|
163
|
+
throw new KeeperSdkError('Team name or UID is required.', ResultCodes.TEAM_REQUIRED)
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
const uidMatch = teams.find((team) => team.team_uid === trimmed)
|
|
167
|
+
if (uidMatch) return uidMatch
|
|
168
|
+
|
|
169
|
+
const lowered = trimmed.toLowerCase()
|
|
170
|
+
const nameMatches = teams.filter((team) => (team.name || '').trim().toLowerCase() === lowered)
|
|
171
|
+
if (nameMatches.length === 1) return nameMatches[0]
|
|
172
|
+
if (nameMatches.length > 1) {
|
|
173
|
+
throw new KeeperSdkError(
|
|
174
|
+
`Multiple teams match name "${trimmed}". Specify the team UID instead.`,
|
|
175
|
+
ResultCodes.MULTIPLE_TEAM_MATCHES
|
|
176
|
+
)
|
|
177
|
+
}
|
|
178
|
+
throw new KeeperSdkError(`Team "${trimmed}" does not exist.`, ResultCodes.TEAM_NOT_FOUND)
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function resolveNodePath(
|
|
182
|
+
nodes: EnterpriseNode[],
|
|
183
|
+
displayNames: EnterpriseDisplayNames,
|
|
184
|
+
nodeId: number
|
|
185
|
+
): string {
|
|
186
|
+
if (displayNames.nodes.size > 0) {
|
|
187
|
+
for (const node of nodes) {
|
|
188
|
+
const display = displayNames.nodes.get(node.node_id)
|
|
189
|
+
if (display) node.displayName = display
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
return EnterpriseDataManager.getNodePath(nodes, nodeId, { omitRoot: false, separator: NODE_PATH_SEPARATOR })
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function buildTeamUsers(
|
|
196
|
+
users: EnterpriseUser[],
|
|
197
|
+
teamUserLinks: EnterpriseTeamUserLink[],
|
|
198
|
+
teamUid: string
|
|
199
|
+
): TeamUserInfo[] {
|
|
200
|
+
const userById = new Map<number, EnterpriseUser>()
|
|
201
|
+
for (const user of users) userById.set(user.enterprise_user_id, user)
|
|
202
|
+
|
|
203
|
+
const memberIds = new Set<number>()
|
|
204
|
+
for (const link of teamUserLinks) {
|
|
205
|
+
if (link.team_uid === teamUid) memberIds.add(link.enterprise_user_id)
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
const result: TeamUserInfo[] = []
|
|
209
|
+
for (const id of memberIds) {
|
|
210
|
+
const user = userById.get(id)
|
|
211
|
+
if (user && user.username) result.push({ enterprise_user_id: id, username: user.username })
|
|
212
|
+
}
|
|
213
|
+
result.sort((a, b) => a.username.localeCompare(b.username, undefined, { sensitivity: 'base' }))
|
|
214
|
+
return result
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function buildTeamRoles(
|
|
218
|
+
roleTeamLinks: EnterpriseRoleTeamLink[],
|
|
219
|
+
decryptedRoleNames: Map<number, string>,
|
|
220
|
+
teamUid: string
|
|
221
|
+
): TeamRoleInfo[] {
|
|
222
|
+
const roleIds = new Set<number>()
|
|
223
|
+
for (const link of roleTeamLinks) {
|
|
224
|
+
if (link.team_uid === teamUid) roleIds.add(link.role_id)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
const result: TeamRoleInfo[] = []
|
|
228
|
+
for (const id of roleIds) {
|
|
229
|
+
result.push({ role_id: id, role_name: decryptedRoleNames.get(id) || String(id) })
|
|
230
|
+
}
|
|
231
|
+
result.sort((a, b) => a.role_name.localeCompare(b.role_name, undefined, { sensitivity: 'base' }))
|
|
232
|
+
return result
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function boolText(value: boolean): string {
|
|
236
|
+
return value ? 'True' : 'False'
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function asLines(value: string | string[]): string[] {
|
|
240
|
+
if (Array.isArray(value)) return value.length > 0 ? value : ['']
|
|
241
|
+
return [value]
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
function asIdLines(id: number | number[] | undefined): string[] {
|
|
245
|
+
if (id == null) return []
|
|
246
|
+
if (Array.isArray(id)) return id.length > 0 ? id.map(String) : ['']
|
|
247
|
+
return [String(id)]
|
|
248
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
export enum LogLevel {
|
|
2
|
+
DEBUG = 0,
|
|
3
|
+
INFO = 1,
|
|
4
|
+
WARN = 2,
|
|
5
|
+
ERROR = 3,
|
|
6
|
+
NONE = 4,
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export interface ILogger {
|
|
10
|
+
debug(...args: unknown[]): void
|
|
11
|
+
info(...args: unknown[]): void
|
|
12
|
+
warn(...args: unknown[]): void
|
|
13
|
+
error(...args: unknown[]): void
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export class ConsoleLogger implements ILogger {
|
|
17
|
+
private level: LogLevel
|
|
18
|
+
|
|
19
|
+
constructor(level: LogLevel = LogLevel.INFO) {
|
|
20
|
+
this.level = level
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
public setLevel(level: LogLevel): void {
|
|
24
|
+
this.level = level
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
public getLevel(): LogLevel {
|
|
28
|
+
return this.level
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public debug(...args: unknown[]): void {
|
|
32
|
+
if (this.level <= LogLevel.DEBUG) console.debug(...args)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public info(...args: unknown[]): void {
|
|
36
|
+
if (this.level <= LogLevel.INFO) console.log(...args)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
public warn(...args: unknown[]): void {
|
|
40
|
+
if (this.level <= LogLevel.WARN) console.warn(...args)
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
public error(...args: unknown[]): void {
|
|
44
|
+
if (this.level <= LogLevel.ERROR) console.error(...args)
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
let globalLogger: ILogger = new ConsoleLogger()
|
|
49
|
+
|
|
50
|
+
export function setLogger(newLogger: ILogger): void {
|
|
51
|
+
globalLogger = newLogger
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function getLogger(): ILogger {
|
|
55
|
+
return globalLogger
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export function resetLogger(level: LogLevel = LogLevel.INFO): ConsoleLogger {
|
|
59
|
+
const c = new ConsoleLogger(level)
|
|
60
|
+
globalLogger = c
|
|
61
|
+
return c
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export const logger: ILogger = {
|
|
65
|
+
debug: (...args) => globalLogger.debug(...args),
|
|
66
|
+
info: (...args) => globalLogger.info(...args),
|
|
67
|
+
warn: (...args) => globalLogger.warn(...args),
|
|
68
|
+
error: (...args) => globalLogger.error(...args),
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export { ConsoleLogger as Logger }
|