@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,63 @@
|
|
|
1
|
+
export const SdkDefaults = {
|
|
2
|
+
CLIENT_VERSION: 'c17.0.0',
|
|
3
|
+
DEVICE_NAME: 'JavaScript Keeper SDK',
|
|
4
|
+
CONFIG_DIR: '.keeper',
|
|
5
|
+
LOG_FORMAT: '!',
|
|
6
|
+
} as const
|
|
7
|
+
|
|
8
|
+
export const AuthDefaults = {
|
|
9
|
+
MAX_LOGIN_ATTEMPTS: 5,
|
|
10
|
+
APPROVAL_TIMEOUT_MS: 60_000,
|
|
11
|
+
CODE_VALIDATION_DELAY_MS: 2_000,
|
|
12
|
+
} as const
|
|
13
|
+
|
|
14
|
+
export enum AuthErrorCode {
|
|
15
|
+
InvalidCredentials = 'invalid_credentials',
|
|
16
|
+
MissingUsername = 'missing_username',
|
|
17
|
+
MissingPassword = 'missing_password',
|
|
18
|
+
MaxAttemptsExceeded = 'max_attempts_exceeded',
|
|
19
|
+
UserCancelled = 'user_cancelled',
|
|
20
|
+
Unsupported2FAChannel = 'unsupported_2fa_channel',
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export enum SessionErrorCode {
|
|
24
|
+
NotLoggedIn = 'not_logged_in',
|
|
25
|
+
DeviceNotRegistered = 'device_not_registered',
|
|
26
|
+
NoPreviousLogin = 'no_previous_login',
|
|
27
|
+
NoCloneCode = 'no_clone_code',
|
|
28
|
+
PersistentLoginFailed = 'persistent_login_failed',
|
|
29
|
+
SessionTokenExpired = 'session_token_expired',
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export enum TeamErrorCode {
|
|
33
|
+
TeamRequired = 'team_required',
|
|
34
|
+
TeamNotFound = 'team_not_found',
|
|
35
|
+
MultipleTeamMatches = 'multiple_team_matches',
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export const ResultCodes = {
|
|
39
|
+
INVALID_CREDENTIALS: AuthErrorCode.InvalidCredentials,
|
|
40
|
+
MISSING_USERNAME: AuthErrorCode.MissingUsername,
|
|
41
|
+
MISSING_PASSWORD: AuthErrorCode.MissingPassword,
|
|
42
|
+
MAX_ATTEMPTS_EXCEEDED: AuthErrorCode.MaxAttemptsExceeded,
|
|
43
|
+
USER_CANCELLED: AuthErrorCode.UserCancelled,
|
|
44
|
+
UNSUPPORTED_2FA_CHANNEL: AuthErrorCode.Unsupported2FAChannel,
|
|
45
|
+
NOT_LOGGED_IN: SessionErrorCode.NotLoggedIn,
|
|
46
|
+
DEVICE_NOT_REGISTERED: SessionErrorCode.DeviceNotRegistered,
|
|
47
|
+
NO_PREVIOUS_LOGIN: SessionErrorCode.NoPreviousLogin,
|
|
48
|
+
NO_CLONE_CODE: SessionErrorCode.NoCloneCode,
|
|
49
|
+
PERSISTENT_LOGIN_FAILED: SessionErrorCode.PersistentLoginFailed,
|
|
50
|
+
SESSION_TOKEN_EXPIRED: SessionErrorCode.SessionTokenExpired,
|
|
51
|
+
TEAM_REQUIRED: TeamErrorCode.TeamRequired,
|
|
52
|
+
TEAM_NOT_FOUND: TeamErrorCode.TeamNotFound,
|
|
53
|
+
MULTIPLE_TEAM_MATCHES: TeamErrorCode.MultipleTeamMatches,
|
|
54
|
+
} as const
|
|
55
|
+
|
|
56
|
+
export const KEEPER_PUBLIC_HOSTS: Record<string, string> = {
|
|
57
|
+
US: 'keepersecurity.com',
|
|
58
|
+
EU: 'keepersecurity.eu',
|
|
59
|
+
AU: 'keepersecurity.com.au',
|
|
60
|
+
CA: 'keepersecurity.ca',
|
|
61
|
+
JP: 'keepersecurity.jp',
|
|
62
|
+
GOV: 'govcloud.keepersecurity.us',
|
|
63
|
+
}
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import type { KeeperError } from '@keeper-security/keeperapi'
|
|
2
|
+
|
|
3
|
+
function parseJsonObjectIfPresent(s: string): Record<string, unknown> | null {
|
|
4
|
+
const t = s.trim()
|
|
5
|
+
if (t.length === 0 || (t[0] !== '{' && t[0] !== '[')) return null
|
|
6
|
+
try {
|
|
7
|
+
const parsed: unknown = JSON.parse(s)
|
|
8
|
+
if (typeof parsed === 'object' && parsed !== null && !Array.isArray(parsed)) {
|
|
9
|
+
return parsed as Record<string, unknown>
|
|
10
|
+
}
|
|
11
|
+
} catch {
|
|
12
|
+
/* not JSON */
|
|
13
|
+
}
|
|
14
|
+
return null
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isKeeperError(err: unknown): err is KeeperError {
|
|
18
|
+
return (
|
|
19
|
+
err != null &&
|
|
20
|
+
typeof err === 'object' &&
|
|
21
|
+
!(err instanceof Error) &&
|
|
22
|
+
('result_code' in err || 'error' in err || 'response_code' in err)
|
|
23
|
+
)
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export function extractResultCode(err: unknown): string | undefined {
|
|
27
|
+
if (isKeeperError(err)) {
|
|
28
|
+
return err.result_code || err.error
|
|
29
|
+
}
|
|
30
|
+
if (err instanceof Error) {
|
|
31
|
+
const msg = err.message
|
|
32
|
+
if (msg.length > 0 && (msg[0] === '{' || msg[0] === '[')) {
|
|
33
|
+
try {
|
|
34
|
+
const parsed = JSON.parse(msg)
|
|
35
|
+
return parsed.result_code || parsed.error
|
|
36
|
+
} catch {}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (typeof err === 'string') {
|
|
40
|
+
const parsed = parseJsonObjectIfPresent(err)
|
|
41
|
+
if (parsed) {
|
|
42
|
+
if (typeof parsed.result_code === 'string') return parsed.result_code
|
|
43
|
+
if (typeof parsed.error === 'string') return parsed.error
|
|
44
|
+
}
|
|
45
|
+
return err
|
|
46
|
+
}
|
|
47
|
+
if (typeof err === 'object' && err !== null) {
|
|
48
|
+
const obj = err as Record<string, unknown>
|
|
49
|
+
if (typeof obj.result_code === 'string') return obj.result_code
|
|
50
|
+
if (typeof obj.error === 'string') return obj.error
|
|
51
|
+
}
|
|
52
|
+
return undefined
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export function extractErrorMessage(err: unknown): string {
|
|
56
|
+
if (isKeeperError(err)) {
|
|
57
|
+
return err.message || err.result_code || err.error || 'Unknown Keeper error'
|
|
58
|
+
}
|
|
59
|
+
if (err instanceof Error) {
|
|
60
|
+
const parsed = parseJsonObjectIfPresent(err.message)
|
|
61
|
+
if (parsed) {
|
|
62
|
+
if (typeof parsed.message === 'string') return parsed.message
|
|
63
|
+
if (typeof parsed.result_code === 'string') return parsed.result_code
|
|
64
|
+
if (typeof parsed.error === 'string') return parsed.error
|
|
65
|
+
}
|
|
66
|
+
return err.message
|
|
67
|
+
}
|
|
68
|
+
if (typeof err === 'string') {
|
|
69
|
+
const parsed = parseJsonObjectIfPresent(err)
|
|
70
|
+
if (parsed) {
|
|
71
|
+
if (typeof parsed.message === 'string') return parsed.message
|
|
72
|
+
if (typeof parsed.result_code === 'string') return parsed.result_code
|
|
73
|
+
if (typeof parsed.error === 'string') return parsed.error
|
|
74
|
+
}
|
|
75
|
+
return err
|
|
76
|
+
}
|
|
77
|
+
if (typeof err === 'object' && err !== null) {
|
|
78
|
+
const obj = err as Record<string, unknown>
|
|
79
|
+
if (typeof obj.message === 'string') return obj.message
|
|
80
|
+
if (typeof obj.result_code === 'string') return obj.result_code
|
|
81
|
+
}
|
|
82
|
+
return String(err)
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export class KeeperSdkError extends Error {
|
|
86
|
+
readonly resultCode?: string
|
|
87
|
+
readonly keeperError?: KeeperError
|
|
88
|
+
|
|
89
|
+
constructor(message: string, resultCode?: string, keeperError?: KeeperError) {
|
|
90
|
+
super(message)
|
|
91
|
+
this.name = 'KeeperSdkError'
|
|
92
|
+
this.resultCode = resultCode
|
|
93
|
+
this.keeperError = keeperError
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
static from(err: unknown): KeeperSdkError {
|
|
97
|
+
if (err instanceof KeeperSdkError) return err
|
|
98
|
+
if (isKeeperError(err)) {
|
|
99
|
+
return new KeeperSdkError(
|
|
100
|
+
err.message || err.result_code || err.error || 'Unknown Keeper error',
|
|
101
|
+
err.result_code || err.error,
|
|
102
|
+
err
|
|
103
|
+
)
|
|
104
|
+
}
|
|
105
|
+
if (err instanceof Error) return new KeeperSdkError(err.message)
|
|
106
|
+
return new KeeperSdkError(extractErrorMessage(err))
|
|
107
|
+
}
|
|
108
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export function isBoolean(value: unknown): value is boolean {
|
|
2
|
+
return typeof value === 'boolean'
|
|
3
|
+
}
|
|
4
|
+
|
|
5
|
+
export function isString(value: unknown): value is string {
|
|
6
|
+
return typeof value === 'string'
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export function isNonEmptyString(value: unknown): value is string {
|
|
10
|
+
return typeof value === 'string' && value.trim().length > 0
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function isNumber(value: unknown): value is number {
|
|
14
|
+
return typeof value === 'number' && Number.isFinite(value)
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export function isObject(value: unknown): value is Record<string, unknown> {
|
|
18
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value)
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/** True if at least one of the values is a boolean (true or false). */
|
|
22
|
+
export function anyIsBoolean(...values: unknown[]): boolean {
|
|
23
|
+
return values.some(isBoolean)
|
|
24
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SdkDefaults,
|
|
3
|
+
AuthDefaults,
|
|
4
|
+
ResultCodes,
|
|
5
|
+
AuthErrorCode,
|
|
6
|
+
SessionErrorCode,
|
|
7
|
+
TeamErrorCode,
|
|
8
|
+
KEEPER_PUBLIC_HOSTS,
|
|
9
|
+
} from './constants'
|
|
10
|
+
export { Logger, ConsoleLogger, LogLevel, logger, setLogger, getLogger, resetLogger } from './Logger'
|
|
11
|
+
export type { ILogger } from './Logger'
|
|
12
|
+
export { KeeperSdkError, isKeeperError, extractErrorMessage, extractResultCode } from './errors'
|
|
13
|
+
export type { Nullable, Optional, DeepPartial, Immutable } from './types'
|
|
14
|
+
export { isBoolean, isString, isNonEmptyString, isNumber, isObject, anyIsBoolean } from './guards'
|
|
15
|
+
export {
|
|
16
|
+
EMAIL_PATTERN,
|
|
17
|
+
EMAIL_LIST_SEPARATOR_PATTERN,
|
|
18
|
+
TOKEN_SEPARATOR_PATTERN,
|
|
19
|
+
REGEX_ESCAPE_PATTERN,
|
|
20
|
+
isValidEmail,
|
|
21
|
+
escapeRegExp,
|
|
22
|
+
} from './patterns'
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export const EMAIL_PATTERN = /^[^\s@]+@[^\s@.]+\.[^\s@]+$/
|
|
2
|
+
|
|
3
|
+
/** Splits user-entered email lists on whitespace, commas, and semicolons. */
|
|
4
|
+
export const EMAIL_LIST_SEPARATOR_PATTERN = /[\s,;]+/
|
|
5
|
+
|
|
6
|
+
/** Splits free-form text into search tokens on whitespace and common punctuation. */
|
|
7
|
+
export const TOKEN_SEPARATOR_PATTERN = /[\s\-_.,;:!?@#$%^&*()[\]{}|\\/<>]+/
|
|
8
|
+
|
|
9
|
+
/** Characters that must be escaped when embedding user input into a RegExp. */
|
|
10
|
+
export const REGEX_ESCAPE_PATTERN = /[.+^${}()|[\]\\]/g
|
|
11
|
+
|
|
12
|
+
const MAX_EMAIL_LENGTH = 254
|
|
13
|
+
|
|
14
|
+
export function isValidEmail(value: string): boolean {
|
|
15
|
+
return value.length <= MAX_EMAIL_LENGTH && EMAIL_PATTERN.test(value)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function escapeRegExp(value: string): string {
|
|
19
|
+
return value.replace(REGEX_ESCAPE_PATTERN, '\\$&')
|
|
20
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/** A value of type T or null. Use this for caches and computed-but-empty results. */
|
|
2
|
+
export type Nullable<T> = T | null
|
|
3
|
+
|
|
4
|
+
/** A value of type T or undefined. Use this for "not provided" inputs. */
|
|
5
|
+
export type Optional<T> = T | undefined
|
|
6
|
+
|
|
7
|
+
/** Recursively makes every property optional. */
|
|
8
|
+
export type DeepPartial<T> = T extends object ? { [K in keyof T]?: DeepPartial<T[K]> } : T
|
|
9
|
+
|
|
10
|
+
/** Helper to mark properties as readonly. */
|
|
11
|
+
export type Immutable<T> = { readonly [K in keyof T]: T[K] }
|