@postgres.ai/shared 4.0.0-pr-1042.2 → 4.0.0-pr-1043

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@postgres.ai/shared",
3
- "version": "4.0.0-pr-1042.2",
3
+ "version": "4.0.0-pr-1043",
4
4
  "main": "index.js",
5
5
  "types": "index.d.ts",
6
6
  "peerDependencies": {
@@ -5,7 +5,7 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
5
5
  * Unauthorized copying of this file, via any small is strictly prohibited
6
6
  *--------------------------------------------------------------------------
7
7
  */
8
- import { useState, useEffect } from 'react';
8
+ import { useState, useEffect, useMemo } from 'react';
9
9
  import { observer } from 'mobx-react-lite';
10
10
  import Editor from '@monaco-editor/react';
11
11
  import { Checkbox, FormControlLabel, Typography, Snackbar, makeStyles, Button, } from '@material-ui/core';
@@ -20,7 +20,7 @@ import { useForm } from './useForm';
20
20
  import { ResponseMessage } from './ResponseMessage';
21
21
  import { ConfigSectionTitle, Header, ModalTitle } from './Header';
22
22
  import { dockerImageOptions, imagePgOptions } from './configOptions';
23
- import { uniqueChipValue, customOrGenericImage, genericDockerImages, } from './utils';
23
+ import { uniqueChipValue, customOrGenericImage, createEnhancedDockerImages, } from './utils';
24
24
  import { SelectWithTooltip, InputWithChip, InputWithTooltip, } from './InputWithTooltip';
25
25
  import styles from './styles.module.scss';
26
26
  import { formatTuningParams, formatTuningParamsToObj, } from '@postgres.ai/shared/types/api/endpoints/testDbSource';
@@ -108,6 +108,25 @@ export const Configuration = observer(({ instanceId, switchActiveTab, reload, is
108
108
  });
109
109
  };
110
110
  const [{ formik, connectionData, isConnectionDataValid }] = useForm(onSubmit);
111
+ // Memoized enhanced Docker images to avoid recreation on every render
112
+ // This combines predefined images with any custom image from configuration
113
+ const enhancedDockerImages = useMemo(() => {
114
+ return createEnhancedDockerImages((configData === null || configData === void 0 ? void 0 : configData.dockerImageType) === 'Generic Postgres' ? configData === null || configData === void 0 ? void 0 : configData.dockerPath : undefined, (configData === null || configData === void 0 ? void 0 : configData.dockerImageType) === 'Generic Postgres' ? configData === null || configData === void 0 ? void 0 : configData.dockerTag : undefined);
115
+ }, [configData === null || configData === void 0 ? void 0 : configData.dockerPath, configData === null || configData === void 0 ? void 0 : configData.dockerTag, configData === null || configData === void 0 ? void 0 : configData.dockerImageType]);
116
+ // Memoized computed values from enhanced images
117
+ const dockerImageVersions = useMemo(() => {
118
+ return enhancedDockerImages
119
+ .map((image) => image.pg_major_version)
120
+ .filter((value, index, self) => self.indexOf(value) === index)
121
+ .sort((a, b) => Number(a) - Number(b));
122
+ }, [enhancedDockerImages]);
123
+ // Memoized tags and locations for performance
124
+ const dockerTags = useMemo(() => {
125
+ return enhancedDockerImages.map((image) => image.tag);
126
+ }, [enhancedDockerImages]);
127
+ const dockerLocations = useMemo(() => {
128
+ return enhancedDockerImages.map((image) => image.location);
129
+ }, [enhancedDockerImages]);
111
130
  const scrollToField = () => {
112
131
  const errorElement = document.querySelector('.Mui-error');
113
132
  if (errorElement) {
@@ -310,28 +329,21 @@ export const Configuration = observer(({ instanceId, switchActiveTab, reload, is
310
329
  };
311
330
  const handleDockerImageSelect = (e) => {
312
331
  if (e.target.value === 'Generic Postgres') {
313
- const genericImageVersions = genericDockerImages
314
- .map((image) => image.pg_major_version)
315
- .filter((value, index, self) => self.indexOf(value) === index)
316
- .sort((a, b) => Number(a) - Number(b));
317
- const currentDockerImage = genericImageVersions.slice(-1)[0];
332
+ // Use memoized enhanced list for better performance
333
+ const currentDockerImage = dockerImageVersions.slice(-1)[0];
318
334
  setDockerState({
319
335
  ...dockerState,
320
- tags: genericDockerImages
321
- .map((image) => image.tag)
322
- .filter((tag) => tag.startsWith(currentDockerImage)),
323
- locations: genericDockerImages
324
- .map((image) => image.location)
325
- .filter((location) => location === null || location === void 0 ? void 0 : location.includes(currentDockerImage)),
326
- images: genericImageVersions,
327
- data: genericDockerImages,
336
+ tags: dockerTags.filter((tag) => tag.startsWith(currentDockerImage)),
337
+ locations: dockerLocations.filter((location) => location === null || location === void 0 ? void 0 : location.includes(currentDockerImage)),
338
+ images: dockerImageVersions,
339
+ data: enhancedDockerImages,
328
340
  });
329
341
  formik.setValues({
330
342
  ...formik.values,
331
343
  dockerImage: currentDockerImage,
332
344
  dockerImageType: e.target.value,
333
- dockerTag: genericDockerImages.map((image) => image.tag)[0],
334
- dockerPath: genericDockerImages.map((image) => image.location)[0],
345
+ dockerTag: dockerTags[0],
346
+ dockerPath: dockerLocations[0],
335
347
  sharedPreloadLibraries: 'pg_stat_statements,pg_stat_kcache,pg_cron,pgaudit,anon',
336
348
  });
337
349
  }
@@ -367,13 +379,26 @@ export const Configuration = observer(({ instanceId, switchActiveTab, reload, is
367
379
  ...dockerState,
368
380
  tags: updatedDockerTags,
369
381
  });
370
- const currentLocation = (_a = dockerState.data.find((image) => image.tag === updatedDockerTags[0])) === null || _a === void 0 ? void 0 : _a.location;
371
- formik.setValues({
372
- ...formik.values,
373
- dockerTag: updatedDockerTags[0],
374
- dockerImage: e.target.value,
375
- dockerPath: currentLocation,
376
- });
382
+ // Add safety check for empty array
383
+ const firstTag = updatedDockerTags[0];
384
+ if (firstTag) {
385
+ const currentLocation = (_a = dockerState.data.find((image) => image.tag === firstTag)) === null || _a === void 0 ? void 0 : _a.location;
386
+ formik.setValues({
387
+ ...formik.values,
388
+ dockerTag: firstTag,
389
+ dockerImage: e.target.value,
390
+ dockerPath: currentLocation || '',
391
+ });
392
+ }
393
+ else {
394
+ // Fallback when no matching tags found
395
+ formik.setValues({
396
+ ...formik.values,
397
+ dockerImage: e.target.value,
398
+ dockerTag: '',
399
+ dockerPath: '',
400
+ });
401
+ }
377
402
  }
378
403
  else {
379
404
  formik.setValues({
@@ -395,22 +420,32 @@ export const Configuration = observer(({ instanceId, switchActiveTab, reload, is
395
420
  }
396
421
  if (customOrGenericImage(configData === null || configData === void 0 ? void 0 : configData.dockerImageType)) {
397
422
  if ((configData === null || configData === void 0 ? void 0 : configData.dockerImageType) === 'Generic Postgres') {
398
- const genericImageVersions = genericDockerImages
399
- .map((image) => image.pg_major_version)
400
- .filter((value, index, self) => self.indexOf(value) === index)
401
- .sort((a, b) => Number(a) - Number(b));
402
- const currentDockerImage = genericDockerImages.filter((image) => image.location === (configData === null || configData === void 0 ? void 0 : configData.dockerPath))[0] ||
403
- genericDockerImages.filter((image) => { var _a; return (_a = configData === null || configData === void 0 ? void 0 : configData.dockerPath) === null || _a === void 0 ? void 0 : _a.includes(image.pg_major_version); })[0];
404
- setDockerState({
405
- ...dockerState,
406
- tags: genericDockerImages
407
- .map((image) => image.tag)
408
- .filter((tag) => tag.startsWith(currentDockerImage.pg_major_version)),
409
- images: genericImageVersions,
410
- data: genericDockerImages,
411
- });
412
- formik.setFieldValue('dockerTag', currentDockerImage === null || currentDockerImage === void 0 ? void 0 : currentDockerImage.tag);
413
- formik.setFieldValue('dockerImage', currentDockerImage.pg_major_version);
423
+ // Use memoized enhanced list for better performance
424
+ const currentDockerImage = enhancedDockerImages.find((image) => image.location === (configData === null || configData === void 0 ? void 0 : configData.dockerPath) || image.tag === (configData === null || configData === void 0 ? void 0 : configData.dockerTag));
425
+ if (currentDockerImage) {
426
+ setDockerState({
427
+ ...dockerState,
428
+ tags: dockerTags.filter((tag) => tag.startsWith(currentDockerImage.pg_major_version)),
429
+ images: dockerImageVersions,
430
+ data: enhancedDockerImages,
431
+ });
432
+ formik.setFieldValue('dockerTag', currentDockerImage.tag);
433
+ formik.setFieldValue('dockerImage', currentDockerImage.pg_major_version);
434
+ formik.setFieldValue('dockerPath', currentDockerImage.location);
435
+ }
436
+ else {
437
+ // Fallback: shouldn't happen with enhancedDockerImages, but keep for safety
438
+ const fallbackVersion = dockerImageVersions.slice(-1)[0];
439
+ setDockerState({
440
+ ...dockerState,
441
+ tags: dockerTags.filter((tag) => tag.startsWith(fallbackVersion)),
442
+ images: dockerImageVersions,
443
+ data: enhancedDockerImages,
444
+ });
445
+ formik.setFieldValue('dockerTag', (configData === null || configData === void 0 ? void 0 : configData.dockerTag) || '');
446
+ formik.setFieldValue('dockerImage', fallbackVersion);
447
+ formik.setFieldValue('dockerPath', (configData === null || configData === void 0 ? void 0 : configData.dockerPath) || '');
448
+ }
414
449
  }
415
450
  else {
416
451
  formik.setFieldValue('dockerImage', configData === null || configData === void 0 ? void 0 : configData.dockerPath);
@@ -418,7 +453,7 @@ export const Configuration = observer(({ instanceId, switchActiveTab, reload, is
418
453
  }
419
454
  }
420
455
  }
421
- }, [config]);
456
+ }, [config, configData === null || configData === void 0 ? void 0 : configData.dockerPath, configData === null || configData === void 0 ? void 0 : configData.dockerTag, configData === null || configData === void 0 ? void 0 : configData.dockerImageType]);
422
457
  useEffect(() => {
423
458
  getEngine(instanceId).then((res) => {
424
459
  setDledition(String(res === null || res === void 0 ? void 0 : res.edition));
@@ -19,4 +19,7 @@ export declare const formatDatabases: (databases: DatabaseType | null) => string
19
19
  export declare const formatDumpCustomOptions: (options: string[] | null) => string;
20
20
  export declare const postUniqueCustomOptions: (options: string) => string[];
21
21
  export declare const customOrGenericImage: (dockerImage: string | undefined) => boolean;
22
+ export declare const createFallbackDockerImage: (dockerPath: string, dockerTag: string) => DockerImage;
23
+ export declare const createEnhancedDockerImages: (configDockerPath?: string, configDockerTag?: string) => DockerImage[];
24
+ export declare const isConfigLoadedImage: (dockerPath: string, dockerTag: string) => boolean;
22
25
  export {};
@@ -1,7 +1,10 @@
1
1
  import { dockerImageOptions } from '../configOptions';
2
2
  const seContainerRegistry = 'se-images';
3
3
  const genericImagePrefix = 'postgresai/extended-postgres';
4
- // since some tags are rc, we need to specify the exact tags to use
4
+ // Predefined list of Docker images for UI display
5
+ // This list is shown to users for convenient selection
6
+ // IMPORTANT: if user specified an image in config that's not in this list,
7
+ // it will be automatically added via createEnhancedDockerImages()
5
8
  const dockerImagesConfig = {
6
9
  '9.6': ['0.5.3', '0.5.2', '0.5.1'],
7
10
  '10': ['0.5.3', '0.5.2', '0.5.1'],
@@ -73,11 +76,23 @@ export const getImageType = (imageUrl) => {
73
76
  }
74
77
  };
75
78
  export const getImageMajorVersion = (pgImage) => {
76
- const pgImageVersion = pgImage === null || pgImage === void 0 ? void 0 : pgImage.split(':')[1];
77
- const pgServerVersion = pgImageVersion === null || pgImageVersion === void 0 ? void 0 : pgImageVersion.split('-')[0];
78
- return (pgServerVersion === null || pgServerVersion === void 0 ? void 0 : pgServerVersion.includes('.'))
79
- ? pgServerVersion === null || pgServerVersion === void 0 ? void 0 : pgServerVersion.split('.')[0]
80
- : pgServerVersion;
79
+ if (!pgImage)
80
+ return undefined;
81
+ try {
82
+ const pgImageVersion = pgImage.split(':')[1];
83
+ if (!pgImageVersion)
84
+ return undefined;
85
+ const pgServerVersion = pgImageVersion.split('-')[0];
86
+ if (!pgServerVersion)
87
+ return undefined;
88
+ return pgServerVersion.includes('.')
89
+ ? pgServerVersion.split('.')[0]
90
+ : pgServerVersion;
91
+ }
92
+ catch (error) {
93
+ // Return undefined for malformed image strings
94
+ return undefined;
95
+ }
81
96
  };
82
97
  export const formatDatabases = (databases) => {
83
98
  let formattedDatabases = '';
@@ -103,3 +118,53 @@ export const postUniqueCustomOptions = (options) => {
103
118
  return uniqueOptions;
104
119
  };
105
120
  export const customOrGenericImage = (dockerImage) => dockerImage === 'Generic Postgres' || dockerImage === 'custom';
121
+ export const createFallbackDockerImage = (dockerPath, dockerTag) => {
122
+ const majorVersion = getImageMajorVersion(dockerPath) || '16'; // Default to 16 if version can't be extracted
123
+ return {
124
+ package_group: 'postgresai',
125
+ pg_major_version: majorVersion,
126
+ tag: dockerTag || `${majorVersion}-custom`,
127
+ location: dockerPath,
128
+ };
129
+ };
130
+ // Creates enhanced list of Docker images, including image from configuration
131
+ export const createEnhancedDockerImages = (configDockerPath, configDockerTag) => {
132
+ let enhancedImages = [...genericDockerImages];
133
+ // If there's an image in config, check if we need to add it
134
+ if (configDockerPath && configDockerTag) {
135
+ const existingImage = genericDockerImages.find((image) => image.location === configDockerPath || image.tag === configDockerTag);
136
+ // If image not found in predefined list, add it
137
+ if (!existingImage) {
138
+ // Check if this is a Generic Postgres image
139
+ if (configDockerPath.includes(genericImagePrefix)) {
140
+ // For Generic Postgres images create proper structure
141
+ const majorVersion = getImageMajorVersion(configDockerPath);
142
+ if (majorVersion) {
143
+ const configImage = {
144
+ package_group: 'postgresai',
145
+ pg_major_version: majorVersion,
146
+ tag: configDockerTag,
147
+ location: configDockerPath,
148
+ };
149
+ enhancedImages.push(configImage);
150
+ }
151
+ else {
152
+ // Fallback if version extraction failed
153
+ const configImage = createFallbackDockerImage(configDockerPath, configDockerTag);
154
+ enhancedImages.push(configImage);
155
+ }
156
+ }
157
+ else {
158
+ // For custom images use fallback
159
+ const configImage = createFallbackDockerImage(configDockerPath, configDockerTag);
160
+ enhancedImages.push(configImage);
161
+ }
162
+ }
163
+ }
164
+ return enhancedImages;
165
+ };
166
+ // Checks if image is loaded from configuration (not from predefined list)
167
+ export const isConfigLoadedImage = (dockerPath, dockerTag) => {
168
+ const existingImage = genericDockerImages.find((image) => image.location === dockerPath || image.tag === dockerTag);
169
+ return !existingImage;
170
+ };
@@ -7,12 +7,15 @@ export const formatConfig = (config) => {
7
7
  debug: (_b = config.global) === null || _b === void 0 ? void 0 : _b.debug,
8
8
  dockerImage: isSeDockerImage(dockerImage)
9
9
  ? getImageMajorVersion(dockerImage)
10
- : dockerImage,
10
+ : dockerImage && getImageType(dockerImage) === 'Generic Postgres'
11
+ ? getImageMajorVersion(dockerImage) || dockerImage
12
+ : dockerImage,
11
13
  ...(dockerImage && {
12
14
  dockerImageType: getImageType(dockerImage),
13
15
  }),
14
- ...(isSeDockerImage(dockerImage) && {
15
- dockerTag: dockerImage === null || dockerImage === void 0 ? void 0 : dockerImage.split(':')[1],
16
+ // Extract dockerTag for both SE images and Generic Postgres images
17
+ ...(dockerImage && dockerImage.includes(':') && {
18
+ dockerTag: dockerImage.split(':')[1],
16
19
  }),
17
20
  dockerPath: dockerImage,
18
21
  tuningParams: formatTuningParams((_c = config.databaseConfigs) === null || _c === void 0 ? void 0 : _c.configs),