@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.
Files changed (202) hide show
  1. package/.gitlab-ci.yml +60 -0
  2. package/components/AlertSnackbar/index.tsx +23 -0
  3. package/components/AlertSnackbar/useAlertSnackbar.tsx +65 -0
  4. package/components/Button/index.tsx +79 -0
  5. package/components/Button2/index.tsx +43 -0
  6. package/components/Button2/styles.module.scss +82 -0
  7. package/components/DestroyCloneModal/index.tsx +56 -0
  8. package/components/DestroyCloneRestrictionModal/index.tsx +50 -0
  9. package/components/ErrorStub/index.tsx +83 -0
  10. package/components/FormattedText/index.tsx +44 -0
  11. package/components/FormattedText/styles.module.scss +34 -0
  12. package/components/GatewayLink/index.tsx +33 -0
  13. package/components/HorizontalScrollContainer/index.tsx +131 -0
  14. package/components/HorizontalScrollContainer/types.ts +12 -0
  15. package/components/HorizontalScrollContainer/utils.ts +16 -0
  16. package/components/ImportantText/index.tsx +29 -0
  17. package/components/Link2/index.tsx +31 -0
  18. package/components/Link2/styles.module.scss +12 -0
  19. package/components/MenuButton/index.tsx +80 -0
  20. package/components/MenuButton/styles.module.scss +42 -0
  21. package/components/Modal/index.tsx +93 -0
  22. package/components/PageSpinner/index.tsx +18 -0
  23. package/components/PageSpinner/styles.module.scss +13 -0
  24. package/components/ResetCloneModal/index.tsx +154 -0
  25. package/components/SectionTitle/index.tsx +74 -0
  26. package/components/Select/index.tsx +42 -0
  27. package/components/SimpleModalControls/index.tsx +56 -0
  28. package/components/Spinner/icon.tsx +29 -0
  29. package/components/Spinner/index.tsx +16 -0
  30. package/components/Spinner/styles.module.scss +33 -0
  31. package/components/Status/index.tsx +61 -0
  32. package/components/Status/styles.module.scss +45 -0
  33. package/components/StubContainer/index.tsx +41 -0
  34. package/components/StubSpinner/index.tsx +49 -0
  35. package/components/StubSpinnerFlex/index.tsx +20 -0
  36. package/components/StubSpinnerFlex/styles.module.scss +20 -0
  37. package/components/SyntaxHighlight/index.tsx +107 -0
  38. package/components/Table/RowMenu/index.tsx +111 -0
  39. package/components/Table/index.tsx +140 -0
  40. package/components/Text/index.tsx +28 -0
  41. package/components/TextField/index.tsx +117 -0
  42. package/components/Tooltip/index.tsx +52 -0
  43. package/config/index.ts +32 -0
  44. package/config/links.ts +6 -0
  45. package/craco.config.js +80 -0
  46. package/helpers/getEntropy.ts +232 -0
  47. package/helpers/localStorage.ts +15 -0
  48. package/helpers/request.ts +47 -0
  49. package/hooks/useWindowDimensions.ts +16 -0
  50. package/icons/ArrowDropDown/index.tsx +29 -0
  51. package/icons/Circle/index.tsx +27 -0
  52. package/icons/External/index.tsx +14 -0
  53. package/icons/Info/index.tsx +12 -0
  54. package/icons/Renewable/index.tsx +65 -0
  55. package/icons/Shield/index.tsx +33 -0
  56. package/icons/Warning/index.tsx +29 -0
  57. package/meta.json +1 -0
  58. package/package.json +55 -0
  59. package/pages/Clone/Status/index.tsx +73 -0
  60. package/pages/Clone/context.ts +22 -0
  61. package/pages/Clone/index.tsx +634 -0
  62. package/pages/Clone/stores/Main.ts +206 -0
  63. package/pages/Clone/useCreatedStores.ts +11 -0
  64. package/pages/Configuration/Header/index.tsx +84 -0
  65. package/pages/Configuration/InputWithTooltip/index.tsx +240 -0
  66. package/pages/Configuration/ResponseMessage/index.tsx +71 -0
  67. package/pages/Configuration/configOptions.ts +60 -0
  68. package/pages/Configuration/index.tsx +1184 -0
  69. package/pages/Configuration/styles.module.scss +122 -0
  70. package/pages/Configuration/tooltipText.tsx +157 -0
  71. package/pages/Configuration/useForm.ts +108 -0
  72. package/pages/Configuration/utils/index.ts +153 -0
  73. package/pages/CreateClone/index.tsx +311 -0
  74. package/pages/CreateClone/stores/Main.ts +107 -0
  75. package/pages/CreateClone/styles.module.scss +71 -0
  76. package/pages/CreateClone/useCreatedStores.ts +11 -0
  77. package/pages/CreateClone/useForm.ts +36 -0
  78. package/pages/Instance/Clones/Header/Item/index.tsx +15 -0
  79. package/pages/Instance/Clones/Header/Item/styles.module.scss +17 -0
  80. package/pages/Instance/Clones/Header/index.tsx +74 -0
  81. package/pages/Instance/Clones/Header/styles.module.scss +11 -0
  82. package/pages/Instance/Clones/index.tsx +135 -0
  83. package/pages/Instance/ClonesModal/index.tsx +71 -0
  84. package/pages/Instance/ClonesModal/utils.ts +21 -0
  85. package/pages/Instance/InactiveInstance/index.tsx +165 -0
  86. package/pages/Instance/InactiveInstance/utils.ts +9 -0
  87. package/pages/Instance/Info/Connection/ConnectModal/Content/index.tsx +176 -0
  88. package/pages/Instance/Info/Connection/ConnectModal/Content/utils.ts +24 -0
  89. package/pages/Instance/Info/Connection/ConnectModal/index.tsx +36 -0
  90. package/pages/Instance/Info/Connection/index.tsx +81 -0
  91. package/pages/Instance/Info/Details/index.tsx +20 -0
  92. package/pages/Instance/Info/Disks/Disk/ActionsMenu/index.tsx +100 -0
  93. package/pages/Instance/Info/Disks/Disk/Marker/index.tsx +26 -0
  94. package/pages/Instance/Info/Disks/Disk/ProgressBar/PointerIcon.tsx +20 -0
  95. package/pages/Instance/Info/Disks/Disk/ProgressBar/index.tsx +73 -0
  96. package/pages/Instance/Info/Disks/Disk/Status/index.tsx +75 -0
  97. package/pages/Instance/Info/Disks/Disk/index.tsx +168 -0
  98. package/pages/Instance/Info/Disks/index.tsx +65 -0
  99. package/pages/Instance/Info/Icons/index.tsx +39 -0
  100. package/pages/Instance/Info/Retrieval/RefreshFailedAlert/index.tsx +32 -0
  101. package/pages/Instance/Info/Retrieval/RefreshFailedAlert/styles.module.scss +33 -0
  102. package/pages/Instance/Info/Retrieval/RetrievalModal/index.tsx +49 -0
  103. package/pages/Instance/Info/Retrieval/RetrievalModal/styles.module.scss +6 -0
  104. package/pages/Instance/Info/Retrieval/RetrievalTable/index.tsx +53 -0
  105. package/pages/Instance/Info/Retrieval/RetrievalTable/styles.module.scss +29 -0
  106. package/pages/Instance/Info/Retrieval/index.tsx +95 -0
  107. package/pages/Instance/Info/Retrieval/utils.ts +10 -0
  108. package/pages/Instance/Info/Snapshots/Calendar/Day/index.tsx +125 -0
  109. package/pages/Instance/Info/Snapshots/Calendar/index.tsx +133 -0
  110. package/pages/Instance/Info/Snapshots/Calendar/utils.ts +74 -0
  111. package/pages/Instance/Info/Snapshots/TimeLine/Day/index.tsx +79 -0
  112. package/pages/Instance/Info/Snapshots/TimeLine/index.tsx +57 -0
  113. package/pages/Instance/Info/Snapshots/index.tsx +97 -0
  114. package/pages/Instance/Info/Snapshots/utils.ts +18 -0
  115. package/pages/Instance/Info/Status/InstanceResponseModal/index.tsx +32 -0
  116. package/pages/Instance/Info/Status/InstanceResponseModal/styles.module.scss +3 -0
  117. package/pages/Instance/Info/Status/index.tsx +85 -0
  118. package/pages/Instance/Info/Status/styles.module.scss +12 -0
  119. package/pages/Instance/Info/Status/utils.ts +24 -0
  120. package/pages/Instance/Info/components/Property/index.tsx +32 -0
  121. package/pages/Instance/Info/components/Property/styles.module.scss +21 -0
  122. package/pages/Instance/Info/components/Section/index.tsx +50 -0
  123. package/pages/Instance/Info/components/ValueStatus/index.tsx +51 -0
  124. package/pages/Instance/Info/index.tsx +129 -0
  125. package/pages/Instance/SnapshotsModal/index.tsx +169 -0
  126. package/pages/Instance/SnapshotsModal/utils.ts +17 -0
  127. package/pages/Instance/Tabs/index.tsx +98 -0
  128. package/pages/Instance/components/ClonesList/ConnectionModal/index.tsx +196 -0
  129. package/pages/Instance/components/ClonesList/MenuCell/index.tsx +98 -0
  130. package/pages/Instance/components/ClonesList/MenuCell/utils.ts +21 -0
  131. package/pages/Instance/components/ClonesList/index.tsx +189 -0
  132. package/pages/Instance/components/ClonesList/styles.module.scss +32 -0
  133. package/pages/Instance/components/ErrorStub/index.tsx +77 -0
  134. package/pages/Instance/components/ModalReloadButton/index.tsx +43 -0
  135. package/pages/Instance/components/Tags/Tag/index.tsx +60 -0
  136. package/pages/Instance/components/Tags/index.tsx +42 -0
  137. package/pages/Instance/context.ts +39 -0
  138. package/pages/Instance/index.tsx +235 -0
  139. package/pages/Instance/stores/ClonesModal.ts +35 -0
  140. package/pages/Instance/stores/Main.ts +335 -0
  141. package/pages/Instance/stores/SnapshotsModal.ts +35 -0
  142. package/pages/Instance/styles.scss +40 -0
  143. package/pages/Instance/useCreatedStores.ts +14 -0
  144. package/pages/Logs/Icons/PlusIcon.tsx +8 -0
  145. package/pages/Logs/constants/index.ts +7 -0
  146. package/pages/Logs/hooks/useWsScroll.tsx +44 -0
  147. package/pages/Logs/index.tsx +267 -0
  148. package/pages/Logs/utils/index.ts +20 -0
  149. package/pages/Logs/wsLogs.ts +110 -0
  150. package/pages/Logs/wsSnackbar.ts +27 -0
  151. package/postgres.ai-shared-3.5.0.tgz +0 -0
  152. package/react-app-env.d.ts +71 -0
  153. package/scripts/copy-assets.js +30 -0
  154. package/scripts/pack.js +70 -0
  155. package/stores/Snapshots.ts +54 -0
  156. package/styles/colors.ts +67 -0
  157. package/styles/global.scss +29 -0
  158. package/styles/icons.tsx +1917 -0
  159. package/styles/mixins.scss +30 -0
  160. package/styles/styles.ts +87 -0
  161. package/styles/theme.ts +53 -0
  162. package/styles/vars.scss +43 -0
  163. package/styles/vars.ts +40 -0
  164. package/tsconfig.build.json +37 -0
  165. package/tsconfig.json +30 -0
  166. package/types/api/endpoints/createClone.ts +10 -0
  167. package/types/api/endpoints/destroyClone.ts +7 -0
  168. package/types/api/endpoints/getClone.ts +6 -0
  169. package/types/api/endpoints/getConfig.ts +6 -0
  170. package/types/api/endpoints/getEngine.ts +13 -0
  171. package/types/api/endpoints/getFullConfig.ts +4 -0
  172. package/types/api/endpoints/getInstance.ts +6 -0
  173. package/types/api/endpoints/getInstanceRetrieval.ts +6 -0
  174. package/types/api/endpoints/getSeImages.ts +22 -0
  175. package/types/api/endpoints/getSnapshots.ts +6 -0
  176. package/types/api/endpoints/getWSToken.ts +6 -0
  177. package/types/api/endpoints/initWS.ts +1 -0
  178. package/types/api/endpoints/refreshInstance.ts +4 -0
  179. package/types/api/endpoints/resetClone.ts +8 -0
  180. package/types/api/endpoints/testDbSource.ts +48 -0
  181. package/types/api/endpoints/updateClone.ts +10 -0
  182. package/types/api/endpoints/updateConfig.ts +6 -0
  183. package/types/api/entities/clone.ts +42 -0
  184. package/types/api/entities/config.ts +114 -0
  185. package/types/api/entities/dbSource.ts +13 -0
  186. package/types/api/entities/instance.ts +67 -0
  187. package/types/api/entities/instanceRetrieval.ts +46 -0
  188. package/types/api/entities/instanceState.ts +102 -0
  189. package/types/api/entities/pool.ts +27 -0
  190. package/types/api/entities/snapshot.ts +18 -0
  191. package/types/api/entities/wsToken.ts +7 -0
  192. package/types/byte-size/index.d.ts +22 -0
  193. package/utils/api.ts +30 -0
  194. package/utils/clone.ts +31 -0
  195. package/utils/connection.ts +38 -0
  196. package/utils/date.ts +87 -0
  197. package/utils/instance.ts +10 -0
  198. package/utils/numbers.ts +11 -0
  199. package/utils/react.ts +10 -0
  200. package/utils/snapshot.ts +4 -0
  201. package/utils/strings.ts +11 -0
  202. package/utils/units.ts +23 -0
@@ -0,0 +1,13 @@
1
+ export type dbSource = {
2
+ host: string
3
+ port: string
4
+ dbname: string
5
+ username: string
6
+ password: string
7
+ db_list?: string[]
8
+ }
9
+
10
+ export type TestSourceDTO = {
11
+ message: string
12
+ status: string
13
+ }
@@ -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,7 @@
1
+ export type WSTokenDTO = {
2
+ token: string
3
+ }
4
+
5
+ export const formatWSTokenDto = (dto: WSTokenDTO) => dto
6
+
7
+ export type WSToken = ReturnType<typeof formatWSTokenDto>
@@ -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
+ }
@@ -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
+ }
@@ -0,0 +1,4 @@
1
+ import { Snapshot } from '@postgres.ai/shared/types/api/entities/snapshot'
2
+
3
+ export const compareSnapshotsDesc = (a: Snapshot, b: Snapshot) =>
4
+ b.dataStateAtDate.getTime() - a.dataStateAtDate.getTime()
@@ -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
+ }