Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't convert blob types in jdl #27328

Merged
merged 9 commits into from
Sep 19, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions generators/base-application/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import {
import type { TaskTypes as DefaultTaskTypes } from '../../lib/types/application/tasks.js';
import type { ApplicationType } from '../../lib/types/application/application.js';
import type { Entity } from '../../lib/types/application/entity.js';
import type { Entity as BaseEntity } from '../../lib/types/base/entity.js';
import type { GenericTaskGroup } from '../../lib/types/base/tasks.js';
import type { ApplicationConfiguration } from '../../lib/types/application/yo-rc.js';
import type SharedData from '../base/shared-data.js';
Expand Down Expand Up @@ -188,16 +187,16 @@ export default class BaseApplicationGenerator<
/**
* get sorted list of entities according to changelog date (i.e. the order in which they were added)
*/
getExistingEntities(): { name: string; definition: BaseEntity }[] {
getExistingEntities(): { name: string; definition: E }[] {
function isBefore(e1, e2) {
return (e1.definition.annotations?.changelogDate ?? 0) - (e2.definition.annotations?.changelogDate ?? 0);
}

const configDir = this.getEntitiesConfigPath();

const entities: { name: string; definition: BaseEntity }[] = [];
const entities: { name: string; definition: E }[] = [];
for (const entityName of [...new Set(((this.jhipsterConfig.entities as string[]) || []).concat(getEntitiesFromDir(configDir)))]) {
const definition: BaseEntity = this.getEntityConfig(entityName)?.getAll() as BaseEntity;
const definition: E = this.getEntityConfig(entityName)?.getAll() as unknown as E;
if (definition) {
entities.push({ name: entityName, definition });
}
Expand Down
36 changes: 21 additions & 15 deletions generators/base-application/support/prepare-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import { getTypescriptType, prepareField as prepareClientFieldForTemplates } fro
import { prepareField as prepareServerFieldForTemplates } from '../../server/support/index.js';
import { mutateData } from '../../../lib/utils/object.js';
import type CoreGenerator from '../../base-core/generator.js';
import { fieldIsEnum } from './field-utils.js';
import type { Field } from '../../../lib/types/application/field.js';
import type { Entity } from '../../../lib/types/application/entity.js';
import { fieldTypeValues, isFieldEnumType } from '../../../lib/application/field-types.js';
import { prepareProperty } from './prepare-property.js';

const { BlobTypes, CommonDBTypes, RelationalOnlyDBTypes } = fieldTypes;
Expand Down Expand Up @@ -164,9 +166,9 @@ function generateFakeDataForField(this: CoreGenerator, field, faker, changelogDa
data = data.substr(0, data.length - 3);
}
}
} else if (field.fieldType === BYTES && field.fieldTypeBlobContent !== TEXT) {
} else if (field.fieldTypeBinary && field.fieldTypeBlobContent !== TEXT) {
data = '../fake-data/blob/hipster.png';
} else if (field.fieldType === BYTES && field.fieldTypeBlobContent === TEXT) {
} else if (field.fieldTypeBinary && field.fieldTypeBlobContent === TEXT) {
data = '../fake-data/blob/hipster.txt';
} else if (field.fieldType === STRING) {
data = field.id ? faker.string.uuid() : faker.helpers.fake(fakeStringTemplateForFieldName(field.columnName));
Expand Down Expand Up @@ -268,7 +270,7 @@ export default function prepareField(entityWithConfig, field, generator) {
return field;
}

function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {
function prepareCommonFieldForTemplates(entityWithConfig: Entity, field: Field, generator) {
mutateData(field, {
__override__: false,
path: [field.fieldName],
Expand All @@ -288,10 +290,14 @@ function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {
});
const fieldType = field.fieldType;

field.fieldIsEnum = !field.id && fieldIsEnum(fieldType);
if (field.fieldIsEnum) {
const fieldIsEnum = isFieldEnumType(field);
field.fieldIsEnum = fieldIsEnum;
if (fieldIsEnum) {
if (fieldTypeValues.includes(fieldType)) {
throw new Error(`Field type '${fieldType}' is a reserved keyword and can't be used as an enum name.`);
}
field.enumFileName = kebabCase(field.fieldType);
field.enumValues = getEnumValuesWithCustomValues(field.fieldValues);
field.enumValues = getEnumValuesWithCustomValues(field.fieldValues!);
}

field.fieldWithContentType = (fieldType === BYTES || fieldType === BYTE_BUFFER) && field.fieldTypeBlobContent !== TEXT;
Expand All @@ -301,18 +307,18 @@ function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {

field.fieldValidate = Array.isArray(field.fieldValidateRules) && field.fieldValidateRules.length >= 1;
defaults(field, {
nullable: !(field.fieldValidate === true && field.fieldValidateRules.includes(REQUIRED)),
nullable: !(field.fieldValidate === true && field.fieldValidateRules!.includes(REQUIRED)),
});
field.unique = field.fieldValidate === true && field.fieldValidateRules.includes(UNIQUE);
if (field.fieldValidate === true && field.fieldValidateRules.includes(MAXLENGTH)) {
field.unique = field.fieldValidate === true && field.fieldValidateRules!.includes(UNIQUE);
if (field.fieldValidate === true && field.fieldValidateRules!.includes(MAXLENGTH)) {
field.maxlength = field.fieldValidateRulesMaxlength || 255;
}

const faker = entityWithConfig.faker;
field.createRandexp = () => {
// check if regex is valid. If not, issue warning and we skip fake data generation.
try {
new RegExp(field.fieldValidateRulesPattern);
new RegExp(field.fieldValidateRulesPattern!);
} catch {
generator.log.warn(`${field.fieldName} pattern is not valid: ${field.fieldValidateRulesPattern}. Skipping generating fake data. `);
return undefined;
Expand All @@ -329,9 +335,9 @@ function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {
field.generateFakeData = (type = 'csv') => {
let data = generateFakeDataForField.call(generator, field, faker, entityWithConfig.changelogDateForRecent, type);
// manage uniqueness
if ((field.fieldValidate === true && field.fieldValidateRules.includes(UNIQUE)) || field.id) {
if ((field.fieldValidate === true && field.fieldValidateRules!.includes(UNIQUE)) || field.id) {
let i = 0;
while (field.uniqueValue.indexOf(data) !== -1) {
while (field.uniqueValue!.indexOf(data) !== -1) {
if (i++ === 5) {
data = undefined;
break;
Expand All @@ -341,7 +347,7 @@ function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {
if (data === undefined) {
generator.log.warn(`Error generating a unique value field ${field.fieldName} and type ${field.fieldType}`);
} else {
field.uniqueValue.push(data);
field.uniqueValue!.push(data);
}
}
if (data === undefined) {
Expand All @@ -361,7 +367,7 @@ function prepareCommonFieldForTemplates(entityWithConfig, field, generator) {
* @param {String} [enumValues] - an enum's values.
* @return {Array<String>} the formatted enum's values.
*/
export function getEnumValuesWithCustomValues(enumValues) {
export function getEnumValuesWithCustomValues(enumValues: string): { name: string; value: string }[] {
if (!enumValues || enumValues === '') {
throw new Error('Enumeration values must be passed to get the formatted values.');
}
Expand Down
4 changes: 3 additions & 1 deletion generators/base-application/support/prepare-property.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,10 @@
*/
import { snakeCase, upperFirst } from 'lodash-es';
import { mutateData } from '../../../lib/utils/object.js';
import type { Field } from '../../../lib/types/application/field.js';
import type { Relationship } from '../../../lib/types/application/relationship.js';

export const prepareProperty = (property: any) => {
export const prepareProperty = (property: Field | Relationship) => {
mutateData(property, {
__override__: false,
propertyNameCapitalized: ({ propertyName }) => upperFirst(propertyName),
Expand Down
16 changes: 16 additions & 0 deletions generators/bootstrap-application-base/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import { lookupCommandsConfigs } from '../../lib/command/lookup-commands-configs
import { loadCommandConfigsIntoApplication, loadCommandConfigsKeysIntoTemplatesContext } from '../../lib/command/load.js';
import { getConfigWithDefaults } from '../../lib/jhipster/default-application-options.js';
import { removeFieldsWithNullishValues } from '../base/support/index.js';
import { convertFieldBlobType, getBlobContentType, isFieldBinaryType, isFieldBlobType } from '../../lib/application/field-types.js';
import { createAuthorityEntity, createUserEntity, createUserManagementEntity } from './utils.js';
import { exportJDLTransform, importJDLTransform } from './support/index.js';

Expand Down Expand Up @@ -224,6 +225,11 @@ export default class BootstrapApplicationBase extends BaseApplicationGenerator {
configureEntity({ entityStorage, entityConfig }) {
entityStorage.defaults({ fields: [], relationships: [], annotations: {} });

for (const field of entityConfig.fields!.filter(field => field.fieldType === 'byte[]')) {
convertFieldBlobType(field);
entityStorage.save();
}

if (entityConfig.changelogDate) {
entityConfig.annotations.changelogDate = entityConfig.changelogDate;
delete entityConfig.changelogDate;
Expand Down Expand Up @@ -343,6 +349,16 @@ export default class BootstrapApplicationBase extends BaseApplicationGenerator {
this.validateResult(loadEntitiesOtherSide(entities, { application }));

for (const entity of entities) {
for (const field of entity.fields) {
if (isFieldBinaryType(field)) {
field.fieldTypeBlobContent ??= getBlobContentType(field.fieldType);
if (application.databaseTypeCassandra || entity.databaseType === 'cassandra') {
field.fieldType = 'ByteBuffer';
} else if (isFieldBlobType(field)) {
field.fieldType = 'byte[]' as any;
}
}
}
for (const relationship of entity.relationships) {
if (relationship.ownerSide === undefined) {
// ownerSide backward compatibility
Expand Down
2 changes: 1 addition & 1 deletion generators/client/support/template-utils.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe('generator - client - support - template-utils', () => {
describe('generateTestEntityId', () => {
describe('when called with int', () => {
it('return 123', () => {
expect(generateTestEntityId('int')).to.equal(123);
expect(generateTestEntityId('Integer')).to.equal(123);
});
});
describe('when called with String', () => {
Expand Down
5 changes: 3 additions & 2 deletions generators/client/support/template-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import path from 'path';

import { clientFrameworkTypes, fieldTypes } from '../../../lib/jhipster/index.js';
import type { PrimaryKey } from '../../../lib/types/application/entity.js';
import type { FieldType } from '../../../lib/application/field-types.js';
import { getEntryIfTypeOrTypeAttribute } from './types-utils.js';

const { STRING: TYPE_STRING, UUID: TYPE_UUID } = fieldTypes.CommonDBTypes;
Expand Down Expand Up @@ -100,7 +101,7 @@ export const generateEntityClientEnumImports = (fields, clientFramework) => {
* @param {boolean} [wrapped=true] - wrapped values for required types.
*/

export const generateTestEntityId = (primaryKey: string | PrimaryKey, index: string | number = 0, wrapped = true) => {
export const generateTestEntityId = (primaryKey: FieldType | PrimaryKey, index: string | number = 0, wrapped = true) => {
primaryKey = getEntryIfTypeOrTypeAttribute(primaryKey);
let value;
if (primaryKey === TYPE_STRING) {
Expand All @@ -110,7 +111,7 @@ export const generateTestEntityId = (primaryKey: string | PrimaryKey, index: str
} else {
value = index === 0 ? 123 : 456;
}
if (wrapped && [TYPE_UUID, TYPE_STRING].includes(primaryKey)) {
if (wrapped && [TYPE_UUID, TYPE_STRING].includes(primaryKey as any)) {
return `'${value}'`;
}
return value;
Expand Down
5 changes: 3 additions & 2 deletions generators/client/support/types-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import type { FieldType } from '../../../lib/application/field-types.js';
import { fieldTypes } from '../../../lib/jhipster/index.js';
import type { PrimaryKey } from '../../../lib/types/application/entity.js';
import { fieldIsEnum } from '../../base-application/support/index.js';
Expand All @@ -37,7 +38,7 @@ const {
* @param key
* @returns {*}
*/
export const getEntryIfTypeOrTypeAttribute = (key: string | PrimaryKey) => {
export const getEntryIfTypeOrTypeAttribute = (key: FieldType | PrimaryKey): FieldType => {
if (typeof key === 'object') {
return key.type;
}
Expand All @@ -50,7 +51,7 @@ export const getEntryIfTypeOrTypeAttribute = (key: string | PrimaryKey) => {
* @param {string | object} primaryKey - primary key definition
* @returns {string} primary key type in Typescript
*/
const getTypescriptKeyType = primaryKey => {
const getTypescriptKeyType = (primaryKey: FieldType | PrimaryKey) => {
if ([TYPE_INTEGER, TYPE_LONG, TYPE_FLOAT, TYPE_DOUBLE, TYPE_BIG_DECIMAL].includes(getEntryIfTypeOrTypeAttribute(primaryKey))) {
return 'number';
}
Expand Down
12 changes: 10 additions & 2 deletions generators/info/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import type { JHipsterGeneratorFeatures, JHipsterGeneratorOptions } from '../bas
import { YO_RC_FILE } from '../generator-constants.js';
import { applicationsLookup } from '../workspaces/support/applications-lookup.js';
import type { Entity } from '../../lib/types/base/entity.js';
import { convertFieldBlobType } from '../../lib/application/field-types.js';
import { replaceSensitiveConfig } from './support/utils.js';

const isInfoCommand = commandName => commandName === 'info' || undefined;
Expand Down Expand Up @@ -142,8 +143,15 @@ export default class InfoGenerator extends BaseApplicationGenerator {
let jdlObject;
const entities = new Map<string, Entity>();
try {
this.getExistingEntities().forEach(entity => {
entities.set(entity.name, entity.definition);
this.getExistingEntities().forEach(({ name, definition: entity }) => {
if (entity.fields) {
for (const field of entity.fields) {
if (field.fieldType === 'byte[]') {
convertFieldBlobType(field);
}
}
}
entities.set(name, entity);
});
jdlObject = JSONToJDLEntityConverter.convertEntitiesToJDL(entities);
JSONToJDLOptionConverter.convertServerOptionsToJDL({ 'generator-jhipster': this.config.getAll() }, jdlObject);
Expand Down
36 changes: 22 additions & 14 deletions generators/server/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -82,13 +82,13 @@ const { SUPPORTED_VALIDATION_RULES } = validations;
const { isReservedTableName } = reservedKeywords;
const { ANGULAR, REACT, VUE } = clientFrameworkTypes;
const { GRADLE, MAVEN } = buildToolTypes;
const { CASSANDRA, SQL, NO: NO_DATABASE } = databaseTypes;
const { SQL, NO: NO_DATABASE } = databaseTypes;
const { GATEWAY } = applicationTypes;

const { NO: NO_SEARCH_ENGINE } = searchEngineTypes;
const { CommonDBTypes, RelationalOnlyDBTypes } = fieldTypes;
const { INSTANT } = CommonDBTypes;
const { BYTES, BYTE_BUFFER } = RelationalOnlyDBTypes;
const { BYTE_BUFFER } = RelationalOnlyDBTypes;
const { PaginationTypes, ServiceTypes } = entityOptions;
const {
Validations: { MAX, MIN, MAXLENGTH, MINLENGTH, MAXBYTES, MINBYTES, PATTERN },
Expand Down Expand Up @@ -333,28 +333,16 @@ export default class JHipsterServerGenerator extends BaseApplicationGenerator {
},

configureFields({ application, entityConfig, entityName }) {
const databaseType = entityConfig.databaseType ?? application.databaseType;
// Validate entity json field content
const fields = entityConfig.fields;
fields!.forEach(field => {
// Migration from JodaTime to Java Time
if (field.fieldType === 'DateTime' || field.fieldType === 'Date') {
field.fieldType = INSTANT;
}
if (field.fieldType === BYTES && databaseType === CASSANDRA) {
field.fieldType = BYTE_BUFFER;
}

this._validateField(entityName, field);

if (field.fieldType === BYTE_BUFFER) {
this.log.warn(
`Cannot use validation in .jhipster/${entityName}.json for field ${stringifyApplicationData(field)}
Hibernate JPA 2 Metamodel does not work with Bean Validation 2 for LOB fields, so LOB validation is disabled`,
);
field.fieldValidate = false;
field.fieldValidateRules = [];
}
if (entityConfig.pagination && entityConfig.pagination !== NO_PAGINATION && isReservedPaginationWords(field.fieldName)) {
throw new Error(
`Field name '${field.fieldName}' found in ${entityConfig.name} is a reserved keyword, as it is used by Spring for pagination in the URL.`,
Expand Down Expand Up @@ -403,6 +391,26 @@ Hibernate JPA 2 Metamodel does not work with Bean Validation 2 for LOB fields, s
return this.delegateTasksToBlueprint(() => this.configuringEachEntity);
}

get loadingEntities() {
return this.asLoadingEntitiesTaskGroup({
loadEntityConfig({ entitiesToLoad }) {
for (const { entityName, entityBootstrap } of entitiesToLoad) {
for (const field of entityBootstrap.fields) {
if (field.fieldType === BYTE_BUFFER) {
this.log.warn(`Cannot use validation in .jhipster/${entityName}.json for field ${stringifyApplicationData(field)}`);
field.fieldValidate = false;
field.fieldValidateRules = [];
}
}
}
},
});
}

get [BaseApplicationGenerator.LOADING_ENTITIES]() {
return this.delegateTasksToBlueprint(() => this.loadingEntities);
}

get preparingEachEntity() {
return this.asPreparingEachEntityTaskGroup({
prepareEntity({ entity }) {
Expand Down
3 changes: 2 additions & 1 deletion generators/server/support/build-specification-mapper.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { FieldType } from '../../../lib/application/field-types.js';
import { fieldTypes } from '../../../lib/jhipster/index.js';

const {
Expand All @@ -17,7 +18,7 @@ const {
* Return the method name which converts the filter to specification
* @param {string} fieldType
*/
export const getSpecificationBuildForType = (fieldType: string) => {
export const getSpecificationBuildForType = (fieldType: FieldType) => {
if (
[
TYPE_INTEGER,
Expand Down
3 changes: 2 additions & 1 deletion generators/spring-boot/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ import {
websocketTypes,
} from '../../lib/jhipster/index.js';
import { getPomVersionProperties, parseMavenPom } from '../maven/support/index.js';
import type { FieldType } from '../../lib/application/field-types.js';
import { writeFiles as writeEntityFiles } from './entity-files.js';
import cleanupTask from './cleanup.js';
import { serverFiles } from './files.js';
Expand Down Expand Up @@ -346,7 +347,7 @@ public void set${javaBeanCase(propertyName)}(${propertyType} ${propertyName}) {
get preparingEachEntityField() {
return this.asPreparingEachEntityFieldTaskGroup({
prepareEntity({ field }) {
field.fieldJavaBuildSpecification = getSpecificationBuildForType(field.fieldType);
field.fieldJavaBuildSpecification = getSpecificationBuildForType(field.fieldType as FieldType);

field.filterableField = ![TYPE_BYTES, TYPE_BYTE_BUFFER].includes(field.fieldType) && !field.transient;
if (field.filterableField) {
Expand Down
Loading
Loading