@postgres.ai/shared 3.5.1-pr-1027.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/.gitlab-ci.yml +60 -0
- package/components/AlertSnackbar/index.tsx +23 -0
- package/components/AlertSnackbar/useAlertSnackbar.tsx +65 -0
- package/components/Button/index.tsx +79 -0
- package/components/Button2/index.tsx +43 -0
- package/components/Button2/styles.module.scss +82 -0
- package/components/DestroyCloneModal/index.tsx +56 -0
- package/components/DestroyCloneRestrictionModal/index.tsx +50 -0
- package/components/ErrorStub/index.tsx +83 -0
- package/components/FormattedText/index.tsx +44 -0
- package/components/FormattedText/styles.module.scss +34 -0
- package/components/GatewayLink/index.tsx +33 -0
- package/components/HorizontalScrollContainer/index.tsx +131 -0
- package/components/HorizontalScrollContainer/types.ts +12 -0
- package/components/HorizontalScrollContainer/utils.ts +16 -0
- package/components/ImportantText/index.tsx +29 -0
- package/components/Link2/index.tsx +31 -0
- package/components/Link2/styles.module.scss +12 -0
- package/components/MenuButton/index.tsx +80 -0
- package/components/MenuButton/styles.module.scss +42 -0
- package/components/Modal/index.tsx +93 -0
- package/components/PageSpinner/index.tsx +18 -0
- package/components/PageSpinner/styles.module.scss +13 -0
- package/components/ResetCloneModal/index.tsx +154 -0
- package/components/SectionTitle/index.tsx +74 -0
- package/components/Select/index.tsx +42 -0
- package/components/SimpleModalControls/index.tsx +56 -0
- package/components/Spinner/icon.tsx +29 -0
- package/components/Spinner/index.tsx +16 -0
- package/components/Spinner/styles.module.scss +33 -0
- package/components/Status/index.tsx +61 -0
- package/components/Status/styles.module.scss +45 -0
- package/components/StubContainer/index.tsx +41 -0
- package/components/StubSpinner/index.tsx +49 -0
- package/components/StubSpinnerFlex/index.tsx +20 -0
- package/components/StubSpinnerFlex/styles.module.scss +20 -0
- package/components/SyntaxHighlight/index.tsx +107 -0
- package/components/Table/RowMenu/index.tsx +111 -0
- package/components/Table/index.tsx +140 -0
- package/components/Text/index.tsx +28 -0
- package/components/TextField/index.tsx +117 -0
- package/components/Tooltip/index.tsx +52 -0
- package/config/index.ts +32 -0
- package/config/links.ts +6 -0
- package/craco.config.js +80 -0
- package/helpers/getEntropy.ts +232 -0
- package/helpers/localStorage.ts +15 -0
- package/helpers/request.ts +47 -0
- package/hooks/useWindowDimensions.ts +16 -0
- package/icons/ArrowDropDown/index.tsx +29 -0
- package/icons/Circle/index.tsx +27 -0
- package/icons/External/index.tsx +14 -0
- package/icons/Info/index.tsx +12 -0
- package/icons/Renewable/index.tsx +65 -0
- package/icons/Shield/index.tsx +33 -0
- package/icons/Warning/index.tsx +29 -0
- package/meta.json +1 -0
- package/package.json +55 -0
- package/pages/Clone/Status/index.tsx +73 -0
- package/pages/Clone/context.ts +22 -0
- package/pages/Clone/index.tsx +634 -0
- package/pages/Clone/stores/Main.ts +206 -0
- package/pages/Clone/useCreatedStores.ts +11 -0
- package/pages/Configuration/Header/index.tsx +84 -0
- package/pages/Configuration/InputWithTooltip/index.tsx +240 -0
- package/pages/Configuration/ResponseMessage/index.tsx +71 -0
- package/pages/Configuration/configOptions.ts +60 -0
- package/pages/Configuration/index.tsx +1184 -0
- package/pages/Configuration/styles.module.scss +122 -0
- package/pages/Configuration/tooltipText.tsx +157 -0
- package/pages/Configuration/useForm.ts +108 -0
- package/pages/Configuration/utils/index.ts +153 -0
- package/pages/CreateClone/index.tsx +311 -0
- package/pages/CreateClone/stores/Main.ts +107 -0
- package/pages/CreateClone/styles.module.scss +71 -0
- package/pages/CreateClone/useCreatedStores.ts +11 -0
- package/pages/CreateClone/useForm.ts +36 -0
- package/pages/Instance/Clones/Header/Item/index.tsx +15 -0
- package/pages/Instance/Clones/Header/Item/styles.module.scss +17 -0
- package/pages/Instance/Clones/Header/index.tsx +74 -0
- package/pages/Instance/Clones/Header/styles.module.scss +11 -0
- package/pages/Instance/Clones/index.tsx +135 -0
- package/pages/Instance/ClonesModal/index.tsx +71 -0
- package/pages/Instance/ClonesModal/utils.ts +21 -0
- package/pages/Instance/InactiveInstance/index.tsx +165 -0
- package/pages/Instance/InactiveInstance/utils.ts +9 -0
- package/pages/Instance/Info/Connection/ConnectModal/Content/index.tsx +176 -0
- package/pages/Instance/Info/Connection/ConnectModal/Content/utils.ts +24 -0
- package/pages/Instance/Info/Connection/ConnectModal/index.tsx +36 -0
- package/pages/Instance/Info/Connection/index.tsx +81 -0
- package/pages/Instance/Info/Details/index.tsx +20 -0
- package/pages/Instance/Info/Disks/Disk/ActionsMenu/index.tsx +100 -0
- package/pages/Instance/Info/Disks/Disk/Marker/index.tsx +26 -0
- package/pages/Instance/Info/Disks/Disk/ProgressBar/PointerIcon.tsx +20 -0
- package/pages/Instance/Info/Disks/Disk/ProgressBar/index.tsx +73 -0
- package/pages/Instance/Info/Disks/Disk/Status/index.tsx +75 -0
- package/pages/Instance/Info/Disks/Disk/index.tsx +168 -0
- package/pages/Instance/Info/Disks/index.tsx +65 -0
- package/pages/Instance/Info/Icons/index.tsx +39 -0
- package/pages/Instance/Info/Retrieval/RefreshFailedAlert/index.tsx +32 -0
- package/pages/Instance/Info/Retrieval/RefreshFailedAlert/styles.module.scss +33 -0
- package/pages/Instance/Info/Retrieval/RetrievalModal/index.tsx +49 -0
- package/pages/Instance/Info/Retrieval/RetrievalModal/styles.module.scss +6 -0
- package/pages/Instance/Info/Retrieval/RetrievalTable/index.tsx +53 -0
- package/pages/Instance/Info/Retrieval/RetrievalTable/styles.module.scss +29 -0
- package/pages/Instance/Info/Retrieval/index.tsx +95 -0
- package/pages/Instance/Info/Retrieval/utils.ts +10 -0
- package/pages/Instance/Info/Snapshots/Calendar/Day/index.tsx +125 -0
- package/pages/Instance/Info/Snapshots/Calendar/index.tsx +133 -0
- package/pages/Instance/Info/Snapshots/Calendar/utils.ts +74 -0
- package/pages/Instance/Info/Snapshots/TimeLine/Day/index.tsx +79 -0
- package/pages/Instance/Info/Snapshots/TimeLine/index.tsx +57 -0
- package/pages/Instance/Info/Snapshots/index.tsx +97 -0
- package/pages/Instance/Info/Snapshots/utils.ts +18 -0
- package/pages/Instance/Info/Status/InstanceResponseModal/index.tsx +32 -0
- package/pages/Instance/Info/Status/InstanceResponseModal/styles.module.scss +3 -0
- package/pages/Instance/Info/Status/index.tsx +85 -0
- package/pages/Instance/Info/Status/styles.module.scss +12 -0
- package/pages/Instance/Info/Status/utils.ts +24 -0
- package/pages/Instance/Info/components/Property/index.tsx +32 -0
- package/pages/Instance/Info/components/Property/styles.module.scss +21 -0
- package/pages/Instance/Info/components/Section/index.tsx +50 -0
- package/pages/Instance/Info/components/ValueStatus/index.tsx +51 -0
- package/pages/Instance/Info/index.tsx +129 -0
- package/pages/Instance/SnapshotsModal/index.tsx +169 -0
- package/pages/Instance/SnapshotsModal/utils.ts +17 -0
- package/pages/Instance/Tabs/index.tsx +98 -0
- package/pages/Instance/components/ClonesList/ConnectionModal/index.tsx +196 -0
- package/pages/Instance/components/ClonesList/MenuCell/index.tsx +98 -0
- package/pages/Instance/components/ClonesList/MenuCell/utils.ts +21 -0
- package/pages/Instance/components/ClonesList/index.tsx +189 -0
- package/pages/Instance/components/ClonesList/styles.module.scss +32 -0
- package/pages/Instance/components/ErrorStub/index.tsx +77 -0
- package/pages/Instance/components/ModalReloadButton/index.tsx +43 -0
- package/pages/Instance/components/Tags/Tag/index.tsx +60 -0
- package/pages/Instance/components/Tags/index.tsx +42 -0
- package/pages/Instance/context.ts +39 -0
- package/pages/Instance/index.tsx +235 -0
- package/pages/Instance/stores/ClonesModal.ts +35 -0
- package/pages/Instance/stores/Main.ts +335 -0
- package/pages/Instance/stores/SnapshotsModal.ts +35 -0
- package/pages/Instance/styles.scss +40 -0
- package/pages/Instance/useCreatedStores.ts +14 -0
- package/pages/Logs/Icons/PlusIcon.tsx +8 -0
- package/pages/Logs/constants/index.ts +7 -0
- package/pages/Logs/hooks/useWsScroll.tsx +44 -0
- package/pages/Logs/index.tsx +267 -0
- package/pages/Logs/utils/index.ts +20 -0
- package/pages/Logs/wsLogs.ts +110 -0
- package/pages/Logs/wsSnackbar.ts +27 -0
- package/postgres.ai-shared-3.5.0.tgz +0 -0
- package/react-app-env.d.ts +71 -0
- package/scripts/copy-assets.js +30 -0
- package/scripts/pack.js +70 -0
- package/stores/Snapshots.ts +54 -0
- package/styles/colors.ts +67 -0
- package/styles/global.scss +29 -0
- package/styles/icons.tsx +1917 -0
- package/styles/mixins.scss +30 -0
- package/styles/styles.ts +87 -0
- package/styles/theme.ts +53 -0
- package/styles/vars.scss +43 -0
- package/styles/vars.ts +40 -0
- package/tsconfig.build.json +37 -0
- package/tsconfig.json +30 -0
- package/types/api/endpoints/createClone.ts +10 -0
- package/types/api/endpoints/destroyClone.ts +7 -0
- package/types/api/endpoints/getClone.ts +6 -0
- package/types/api/endpoints/getConfig.ts +6 -0
- package/types/api/endpoints/getEngine.ts +13 -0
- package/types/api/endpoints/getFullConfig.ts +4 -0
- package/types/api/endpoints/getInstance.ts +6 -0
- package/types/api/endpoints/getInstanceRetrieval.ts +6 -0
- package/types/api/endpoints/getSeImages.ts +22 -0
- package/types/api/endpoints/getSnapshots.ts +6 -0
- package/types/api/endpoints/getWSToken.ts +6 -0
- package/types/api/endpoints/initWS.ts +1 -0
- package/types/api/endpoints/refreshInstance.ts +4 -0
- package/types/api/endpoints/resetClone.ts +8 -0
- package/types/api/endpoints/testDbSource.ts +48 -0
- package/types/api/endpoints/updateClone.ts +10 -0
- package/types/api/endpoints/updateConfig.ts +6 -0
- package/types/api/entities/clone.ts +42 -0
- package/types/api/entities/config.ts +114 -0
- package/types/api/entities/dbSource.ts +13 -0
- package/types/api/entities/instance.ts +67 -0
- package/types/api/entities/instanceRetrieval.ts +46 -0
- package/types/api/entities/instanceState.ts +102 -0
- package/types/api/entities/pool.ts +27 -0
- package/types/api/entities/snapshot.ts +18 -0
- package/types/api/entities/wsToken.ts +7 -0
- package/types/byte-size/index.d.ts +22 -0
- package/utils/api.ts +30 -0
- package/utils/clone.ts +31 -0
- package/utils/connection.ts +38 -0
- package/utils/date.ts +87 -0
- package/utils/instance.ts +10 -0
- package/utils/numbers.ts +11 -0
- package/utils/react.ts +10 -0
- package/utils/snapshot.ts +4 -0
- package/utils/strings.ts +11 -0
- package/utils/units.ts +23 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import {
|
|
2
|
+
InstanceStateDto,
|
|
3
|
+
formatInstanceStateDto,
|
|
4
|
+
} from '@postgres.ai/shared/types/api/entities/instanceState'
|
|
5
|
+
|
|
6
|
+
type CoreInstanceDto = {
|
|
7
|
+
id: number
|
|
8
|
+
state: InstanceStateDto
|
|
9
|
+
plan: string
|
|
10
|
+
selfassigned_instance_id: string
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type CeInstanceDto = CoreInstanceDto & {}
|
|
14
|
+
|
|
15
|
+
type PlatformInstanceDto = CoreInstanceDto & {
|
|
16
|
+
created_at: string
|
|
17
|
+
telemetry_last_reported_at?: string
|
|
18
|
+
created_formatted: string
|
|
19
|
+
iid: number | null
|
|
20
|
+
is_active: true
|
|
21
|
+
org_id: number
|
|
22
|
+
project_alias: string
|
|
23
|
+
project_id: number
|
|
24
|
+
project_name: string
|
|
25
|
+
ssh_server_url: string | null
|
|
26
|
+
url: string
|
|
27
|
+
use_tunnel: boolean
|
|
28
|
+
verify_token: string
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export type InstanceDto = CeInstanceDto | PlatformInstanceDto
|
|
32
|
+
|
|
33
|
+
export const formatInstanceDto = (dto: InstanceDto) => {
|
|
34
|
+
const coreMapped = {
|
|
35
|
+
id: dto.id.toString(),
|
|
36
|
+
state: formatInstanceStateDto(dto.state),
|
|
37
|
+
dto,
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const platformMapped =
|
|
41
|
+
'created_at' in dto
|
|
42
|
+
? {
|
|
43
|
+
createdAt: new Date(dto.created_at),
|
|
44
|
+
...(dto.telemetry_last_reported_at && {
|
|
45
|
+
telemetryLastReportedAt: new Date(dto.telemetry_last_reported_at),
|
|
46
|
+
}),
|
|
47
|
+
createdFormatted: `${dto.created_formatted} UTC`,
|
|
48
|
+
iid: dto.iid,
|
|
49
|
+
isActive: dto.is_active,
|
|
50
|
+
orgId: dto.org_id.toString(),
|
|
51
|
+
projectAlias: dto.project_alias,
|
|
52
|
+
projectId: dto.project_id.toString(),
|
|
53
|
+
projectName: dto.project_name,
|
|
54
|
+
sshServerUrl: dto.ssh_server_url,
|
|
55
|
+
useTunnel: dto.use_tunnel,
|
|
56
|
+
verifyToken: dto.verify_token,
|
|
57
|
+
url: dto.url,
|
|
58
|
+
}
|
|
59
|
+
: null
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
...coreMapped,
|
|
63
|
+
...platformMapped,
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export type Instance = ReturnType<typeof formatInstanceDto>
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export interface ActivityType {
|
|
2
|
+
user?: string
|
|
3
|
+
query?: string
|
|
4
|
+
duration?: number | string
|
|
5
|
+
waitEventType?: string
|
|
6
|
+
waitEvent?: string
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export type InstanceRetrieval = {
|
|
10
|
+
mode: string
|
|
11
|
+
alerts: Object | null
|
|
12
|
+
lastRefresh: string | null
|
|
13
|
+
nextRefresh: string | null
|
|
14
|
+
status: string
|
|
15
|
+
currentJob?: string
|
|
16
|
+
activity: {
|
|
17
|
+
source: ActivityType[]
|
|
18
|
+
target: ActivityType[]
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const replaceSinglequote = (string?: string) => string?.replace(/'/g, '')
|
|
23
|
+
|
|
24
|
+
const formatActivity = (activity: ActivityType[]) =>
|
|
25
|
+
activity?.map((item) => {
|
|
26
|
+
return {
|
|
27
|
+
user: replaceSinglequote(item.user),
|
|
28
|
+
query: replaceSinglequote(item.query),
|
|
29
|
+
duration: replaceSinglequote(`${item.duration}ms`),
|
|
30
|
+
'wait type/event': replaceSinglequote(
|
|
31
|
+
`${item.waitEventType}/${item.waitEvent}`,
|
|
32
|
+
),
|
|
33
|
+
}
|
|
34
|
+
})
|
|
35
|
+
|
|
36
|
+
export const formatInstanceRetrieval = (retrieval: InstanceRetrieval) => {
|
|
37
|
+
return {
|
|
38
|
+
...retrieval,
|
|
39
|
+
activity: {
|
|
40
|
+
source: formatActivity(retrieval.activity?.source),
|
|
41
|
+
target: formatActivity(retrieval.activity?.target),
|
|
42
|
+
},
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type InstanceRetrievalType = ReturnType<typeof formatInstanceRetrieval>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import {
|
|
2
|
+
CloneDto,
|
|
3
|
+
formatCloneDto,
|
|
4
|
+
} from '@postgres.ai/shared/types/api/entities/clone'
|
|
5
|
+
import {
|
|
6
|
+
formatPoolDto,
|
|
7
|
+
PoolDto,
|
|
8
|
+
} from '@postgres.ai/shared/types/api/entities/pool'
|
|
9
|
+
|
|
10
|
+
export type InstanceStateDto = {
|
|
11
|
+
cloning: {
|
|
12
|
+
clones: CloneDto[]
|
|
13
|
+
expectedCloningTime: number
|
|
14
|
+
numClones?: number
|
|
15
|
+
}
|
|
16
|
+
status: {
|
|
17
|
+
code: 'OK' | 'WARNING' | 'NO_RESPONSE'
|
|
18
|
+
message: string
|
|
19
|
+
}
|
|
20
|
+
// Fallback for capability with old API.
|
|
21
|
+
clones?: CloneDto[]
|
|
22
|
+
// Fallback for capability with old API.
|
|
23
|
+
expectedCloningTime?: number
|
|
24
|
+
// Fallback for capability with old API.
|
|
25
|
+
pools?: PoolDto[]
|
|
26
|
+
// Fallback for capability with old API.
|
|
27
|
+
retrieving?: {
|
|
28
|
+
lastRefresh: string | null
|
|
29
|
+
nextRefresh: string | null
|
|
30
|
+
mode: string
|
|
31
|
+
status: 'finished' | 'failed' | 'refreshing' | 'pending'
|
|
32
|
+
alerts?: {
|
|
33
|
+
refresh_failed?: {
|
|
34
|
+
level: 'error'
|
|
35
|
+
message: string
|
|
36
|
+
lastSeen: string
|
|
37
|
+
count: number
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
// Fallback for capability with old API.
|
|
42
|
+
fileSystem?: {
|
|
43
|
+
free: number
|
|
44
|
+
size: number
|
|
45
|
+
used: number
|
|
46
|
+
}
|
|
47
|
+
engine?: {
|
|
48
|
+
version: string
|
|
49
|
+
startedAt: string
|
|
50
|
+
edition?: string
|
|
51
|
+
disableConfigModification?: boolean
|
|
52
|
+
}
|
|
53
|
+
dataSize?: number
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export const formatInstanceStateDto = (dto: InstanceStateDto) => {
|
|
57
|
+
if (!dto) return null
|
|
58
|
+
|
|
59
|
+
const pools = dto.pools?.map(formatPoolDto) ?? null
|
|
60
|
+
const clones =
|
|
61
|
+
dto?.clones?.map(formatCloneDto) ?? dto.cloning?.clones?.map(formatCloneDto)
|
|
62
|
+
const expectedCloningTime =
|
|
63
|
+
dto?.expectedCloningTime ?? dto.cloning?.expectedCloningTime
|
|
64
|
+
|
|
65
|
+
return {
|
|
66
|
+
...dto,
|
|
67
|
+
engine: {
|
|
68
|
+
version: dto.engine?.version ?? null,
|
|
69
|
+
startedAt: dto.engine?.startedAt && new Date(dto.engine?.startedAt),
|
|
70
|
+
disableConfigModification: false,
|
|
71
|
+
},
|
|
72
|
+
retrieving: dto.retrieving && {
|
|
73
|
+
lastRefresh: dto.retrieving.lastRefresh
|
|
74
|
+
? new Date(dto.retrieving.lastRefresh)
|
|
75
|
+
: null,
|
|
76
|
+
nextRefresh: dto.retrieving.nextRefresh
|
|
77
|
+
? new Date(dto.retrieving.nextRefresh)
|
|
78
|
+
: null,
|
|
79
|
+
mode: dto.retrieving.mode,
|
|
80
|
+
status: dto.retrieving.status,
|
|
81
|
+
alerts: dto.retrieving.alerts && {
|
|
82
|
+
refreshFailed: dto.retrieving.alerts.refresh_failed && {
|
|
83
|
+
level: dto.retrieving.alerts.refresh_failed.level,
|
|
84
|
+
message: dto.retrieving.alerts.refresh_failed.message,
|
|
85
|
+
lastSeen: new Date(dto.retrieving.alerts.refresh_failed.lastSeen),
|
|
86
|
+
count: dto.retrieving.alerts.refresh_failed.count,
|
|
87
|
+
},
|
|
88
|
+
},
|
|
89
|
+
},
|
|
90
|
+
cloning: {
|
|
91
|
+
clones: clones,
|
|
92
|
+
expectedCloningTime: expectedCloningTime,
|
|
93
|
+
},
|
|
94
|
+
pools,
|
|
95
|
+
dataSize:
|
|
96
|
+
dto.dataSize ??
|
|
97
|
+
pools?.reduce((sum, pool) => pool.fileSystem.dataSize + sum, 0) ??
|
|
98
|
+
null,
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
export type InstanceState = ReturnType<typeof formatInstanceStateDto>
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export type PoolDto = {
|
|
9
|
+
cloneList: string[]
|
|
10
|
+
fileSystem: {
|
|
11
|
+
compressRatio: number
|
|
12
|
+
dataSize: number
|
|
13
|
+
free: number
|
|
14
|
+
mode: string
|
|
15
|
+
size: number
|
|
16
|
+
used: number
|
|
17
|
+
usedByClones: number
|
|
18
|
+
usedBySnapshots: number
|
|
19
|
+
}
|
|
20
|
+
mode: string
|
|
21
|
+
name: string
|
|
22
|
+
status: 'active' | 'empty' | 'refreshing'
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const formatPoolDto = (dto: PoolDto) => dto
|
|
26
|
+
|
|
27
|
+
export type Pool = ReturnType<typeof formatPoolDto>
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { parseDate } from '@postgres.ai/shared/utils/date'
|
|
2
|
+
|
|
3
|
+
export type SnapshotDto = {
|
|
4
|
+
createdAt: string
|
|
5
|
+
dataStateAt: string
|
|
6
|
+
id: string
|
|
7
|
+
pool: string
|
|
8
|
+
physicalSize: number
|
|
9
|
+
logicalSize: number
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export const formatSnapshotDto = (dto: SnapshotDto) => ({
|
|
13
|
+
...dto,
|
|
14
|
+
createdAtDate: parseDate(dto.createdAt),
|
|
15
|
+
dataStateAtDate: parseDate(dto.dataStateAt)
|
|
16
|
+
})
|
|
17
|
+
|
|
18
|
+
export type Snapshot = ReturnType<typeof formatSnapshotDto>
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
type Options = {
|
|
9
|
+
precision: number
|
|
10
|
+
units: 'metric' | 'iec' | 'metric_octet' | 'iec_octet'
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
type Result = {
|
|
14
|
+
value: string
|
|
15
|
+
unit: string
|
|
16
|
+
long: string
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
declare module 'byte-size' {
|
|
20
|
+
declare const byteSize: (bytes: number, options?: Options) => Result
|
|
21
|
+
export default byteSize
|
|
22
|
+
}
|
package/utils/api.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const getTextFromUnknownApiError = async (error: Response) => {
|
|
9
|
+
const log = (text: string) => console.error('Unknown API error', text)
|
|
10
|
+
|
|
11
|
+
try {
|
|
12
|
+
const result = await error.json()
|
|
13
|
+
log(result)
|
|
14
|
+
return JSON.stringify(result)
|
|
15
|
+
} catch (e) {
|
|
16
|
+
// not a json
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
try {
|
|
20
|
+
const result = await error.text()
|
|
21
|
+
log(result)
|
|
22
|
+
return result
|
|
23
|
+
} catch (e) {
|
|
24
|
+
// not a text
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const result = `${error.status} ${error.statusText}`
|
|
28
|
+
log(result)
|
|
29
|
+
return result
|
|
30
|
+
}
|
package/utils/clone.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Clone } from '@postgres.ai/shared/types/api/entities/clone'
|
|
9
|
+
import { capitalize } from '@postgres.ai/shared/utils/strings'
|
|
10
|
+
|
|
11
|
+
const STATUS_CODE_TO_TYPE = {
|
|
12
|
+
OK: 'ok' as const,
|
|
13
|
+
CREATING: 'waiting' as const,
|
|
14
|
+
DELETING: 'waiting' as const,
|
|
15
|
+
RESETTING: 'waiting' as const,
|
|
16
|
+
FATAL: 'error' as const,
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type StatusCode = keyof typeof STATUS_CODE_TO_TYPE
|
|
20
|
+
|
|
21
|
+
export const getCloneStatusType = (statusCode: StatusCode) =>
|
|
22
|
+
STATUS_CODE_TO_TYPE[statusCode] ?? 'unknown'
|
|
23
|
+
|
|
24
|
+
export const getCloneStatusText = (statusCode: StatusCode) => {
|
|
25
|
+
if (statusCode === 'OK') return statusCode
|
|
26
|
+
|
|
27
|
+
return capitalize(statusCode)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export const checkIsCloneStable = (clone: Clone) =>
|
|
31
|
+
clone.status.code === 'OK' || clone.status.code === 'FATAL'
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { Instance } from '@postgres.ai/shared/types/api/entities/instance'
|
|
9
|
+
import { Clone } from '@postgres.ai/shared/types/api/entities/clone'
|
|
10
|
+
|
|
11
|
+
const isEmptyDbData = (clone: Clone) => {
|
|
12
|
+
const { host, port, username } = clone.db
|
|
13
|
+
|
|
14
|
+
// 'host', 'port' or 'username' can be empty string.
|
|
15
|
+
return !host || !port || !username
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export const getSshPortForwardingCommand = (
|
|
19
|
+
instance: Instance,
|
|
20
|
+
clone: Clone,
|
|
21
|
+
) => {
|
|
22
|
+
if (!instance.sshServerUrl) return null
|
|
23
|
+
if (isEmptyDbData(clone)) return null
|
|
24
|
+
|
|
25
|
+
return `ssh -NTML ${clone.db.port}:localhost:${clone.db.port} ${instance.sshServerUrl} -i ~/.ssh/id_rsa`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export const getPsqlConnectionStr = (clone: Clone) => {
|
|
29
|
+
if (isEmptyDbData(clone)) return null
|
|
30
|
+
|
|
31
|
+
return `"host=${clone.db.host} port=${clone.db.port} user=${clone.db.username} dbname=DBNAME"`
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
export const getJdbcConnectionStr = (clone: Clone) => {
|
|
35
|
+
if (isEmptyDbData(clone)) return null
|
|
36
|
+
|
|
37
|
+
return `jdbc:postgresql://${clone.db.host}:${clone.db.port}/DBNAME?user=${clone.db.username}&password=DBPASSWORD`
|
|
38
|
+
}
|
package/utils/date.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import {
|
|
9
|
+
parse,
|
|
10
|
+
startOfDay,
|
|
11
|
+
isSameDay,
|
|
12
|
+
startOfMonth,
|
|
13
|
+
startOfWeek,
|
|
14
|
+
endOfMonth,
|
|
15
|
+
endOfWeek,
|
|
16
|
+
differenceInDays,
|
|
17
|
+
addDays,
|
|
18
|
+
addMonths,
|
|
19
|
+
isSameMonth,
|
|
20
|
+
format,
|
|
21
|
+
formatDistanceToNowStrict,
|
|
22
|
+
} from 'date-fns'
|
|
23
|
+
|
|
24
|
+
// parseDate parses date of both format: '2006-01-02 15:04:05 UTC' and `2006-01-02T15:04:05Z` (RFC3339).
|
|
25
|
+
export const parseDate = (dateStr: string) =>
|
|
26
|
+
parse(
|
|
27
|
+
dateStr.replace(' UTC', 'Z').replace('T', ' '),
|
|
28
|
+
'yyyy-MM-dd HH:mm:ssX',
|
|
29
|
+
new Date(),
|
|
30
|
+
)
|
|
31
|
+
|
|
32
|
+
// UTCf - UTC formatted, but not actually UTC.
|
|
33
|
+
// date-fns using this approach because browser don't have an opportunity to switch single date
|
|
34
|
+
// object in different timezones.
|
|
35
|
+
// Example: 15:00:00 <some date> Moscow Standard Time -> 12:00:00 <same date> Moscow Standard Time.
|
|
36
|
+
// In example above just ignore real timezone "Moscow Standard Time" and imagine that it is UTC.
|
|
37
|
+
const toUTCf = (date: Date) =>
|
|
38
|
+
new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000)
|
|
39
|
+
|
|
40
|
+
const toLocal = (date: Date) =>
|
|
41
|
+
new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000)
|
|
42
|
+
|
|
43
|
+
const inUTC =
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
<T extends (date: Date, ...otherArgs: any[]) => Date>(func: T) =>
|
|
48
|
+
(date: Date, ...otherArgs: unknown[]) =>
|
|
49
|
+
toLocal(func(toUTCf(date), ...otherArgs))
|
|
50
|
+
|
|
51
|
+
export const startOfMonthUTC = inUTC(startOfMonth)
|
|
52
|
+
|
|
53
|
+
export const startOfWeekUTC = inUTC(startOfWeek)
|
|
54
|
+
|
|
55
|
+
export const endOfMonthUTC = inUTC(endOfMonth)
|
|
56
|
+
|
|
57
|
+
export const endOfWeekUTC = inUTC(endOfWeek)
|
|
58
|
+
|
|
59
|
+
export const startOfDayUTC = inUTC(startOfDay)
|
|
60
|
+
|
|
61
|
+
export const addDaysUTC = inUTC(addDays)
|
|
62
|
+
|
|
63
|
+
export const addMonthsUTC = inUTC(addMonths)
|
|
64
|
+
|
|
65
|
+
export const differenceInDaysUTC = (date1: Date, date2: Date) =>
|
|
66
|
+
differenceInDays(toUTCf(date1), toUTCf(date2))
|
|
67
|
+
|
|
68
|
+
export const isSameMonthUTC = (date1: Date, date2: Date) =>
|
|
69
|
+
isSameMonth(toUTCf(date1), toUTCf(date2))
|
|
70
|
+
|
|
71
|
+
export const formatUTC = (date: Date, formatStr: string) =>
|
|
72
|
+
format(toUTCf(date), formatStr)
|
|
73
|
+
|
|
74
|
+
export const isSameDayUTC = (date1: Date, date2: Date) =>
|
|
75
|
+
isSameDay(toUTCf(date1), toUTCf(date2))
|
|
76
|
+
|
|
77
|
+
// Std date utils.
|
|
78
|
+
export const formatDistanceStd = (date: Date) =>
|
|
79
|
+
formatDistanceToNowStrict(date, { addSuffix: true })
|
|
80
|
+
|
|
81
|
+
export const formatDateStd = (
|
|
82
|
+
date: Date,
|
|
83
|
+
options?: { withDistance?: boolean },
|
|
84
|
+
) =>
|
|
85
|
+
`${formatUTC(date, 'yyyy-MM-dd HH:mm:ss')} UTC ${
|
|
86
|
+
options?.withDistance ? `(${formatDistanceStd(date)})` : ''
|
|
87
|
+
}`
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export const parseEngineVersion = (str: string) => {
|
|
2
|
+
const [versionStr] = str.split('-')
|
|
3
|
+
const [major, minor, patch] = versionStr.split('.')
|
|
4
|
+
if (!major || !minor || !patch) return null
|
|
5
|
+
return {
|
|
6
|
+
major: Number(major),
|
|
7
|
+
minor: Number(minor),
|
|
8
|
+
patch: Number(patch),
|
|
9
|
+
}
|
|
10
|
+
}
|
package/utils/numbers.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const round = (value: number, precision = 0) => {
|
|
9
|
+
const multiplier = 10 ** precision
|
|
10
|
+
return Math.round(value * multiplier) / multiplier
|
|
11
|
+
}
|
package/utils/react.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useContext, createContext } from 'react'
|
|
2
|
+
|
|
3
|
+
export const createStrictContext = <Value>() => {
|
|
4
|
+
const Context = createContext<Value>(undefined as unknown as Value)
|
|
5
|
+
|
|
6
|
+
return {
|
|
7
|
+
useStrictContext: () => useContext(Context),
|
|
8
|
+
Provider: Context.Provider,
|
|
9
|
+
}
|
|
10
|
+
}
|
package/utils/strings.ts
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export const capitalize = (value: string) => {
|
|
9
|
+
const [firstChar, ...otherChars] = value.split('')
|
|
10
|
+
return `${firstChar.toUpperCase()}${otherChars.join('').toLowerCase()}`
|
|
11
|
+
}
|
package/utils/units.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/*--------------------------------------------------------------------------
|
|
2
|
+
* Copyright (c) 2019-2021, Postgres.ai, Nikolay Samokhvalov nik@postgres.ai
|
|
3
|
+
* All Rights Reserved. Proprietary and confidential.
|
|
4
|
+
* Unauthorized copying of this file, via any medium is strictly prohibited
|
|
5
|
+
*--------------------------------------------------------------------------
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import byteSize from 'byte-size'
|
|
9
|
+
|
|
10
|
+
type Options = {
|
|
11
|
+
precision?: number
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const formatBytesIEC = (bytes: number, options?: Options) => {
|
|
15
|
+
const { precision = 3 } = options ?? {}
|
|
16
|
+
|
|
17
|
+
const result = byteSize(bytes, {
|
|
18
|
+
precision,
|
|
19
|
+
units: 'iec',
|
|
20
|
+
})
|
|
21
|
+
|
|
22
|
+
return `${result.value} ${result.unit}`
|
|
23
|
+
}
|