Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
{ "fieldName": "active", "fieldType": "Boolean" },
{ "fieldName": "accountType", "fieldType": "BankAccountType", "fieldValues": "CHECKING,SAVINGS,LOAN" },
{ "fieldName": "attachment", "fieldType": "byte[]", "fieldTypeBlobContent": "any" },
{ "fieldName": "description", "fieldType": "byte[]", "fieldTypeBlobContent": "text" }
{ "fieldName": "description", "fieldType": "byte[]", "fieldTypeBlobContent": "text" },
{ "fieldName": "metadata", "fieldType": "byte[]", "fieldTypeBlobContent": "json" }
],
"fluentMethods": true,
"jpaMetamodelFiltering": true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,8 @@
{ "fieldName": "active", "fieldType": "Boolean" },
{ "fieldName": "accountType", "fieldType": "BankAccountType", "fieldValues": "CHECKING,SAVINGS,LOAN" },
{ "fieldName": "attachment", "fieldType": "byte[]", "fieldTypeBlobContent": "any" },
{ "fieldName": "description", "fieldType": "byte[]", "fieldTypeBlobContent": "text" }
{ "fieldName": "description", "fieldType": "byte[]", "fieldTypeBlobContent": "text" },
{ "fieldName": "metadata", "fieldType": "byte[]", "fieldTypeBlobContent": "json" }
],
"fluentMethods": true,
"jpaMetamodelFiltering": true,
Expand Down
25 changes: 25 additions & 0 deletions generators/angular/generator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { before, describe, expect, it } from 'esmocha';
import { basename } from 'node:path';

import { clientFrameworkTypes } from '../../lib/jhipster/index.ts';
import type { Entity } from '../../lib/jhipster/types/entity.ts';
import {
buildClientSamples,
defaultHelpers as helpers,
Expand All @@ -18,6 +19,11 @@ const generator = basename(import.meta.dirname);

const { ANGULAR: clientFramework } = clientFrameworkTypes;
const commonConfig = { clientFramework, nativeLanguage: 'en', languages: ['fr' as const, 'en' as const] };
const jsonBlobEntity = {
name: 'JsonBlob',
changelogDate: '20220129025419',
fields: [{ fieldName: 'payload', fieldType: 'byte[]', fieldTypeBlobContent: 'json' }],
} satisfies Entity;

const testSamples = buildClientSamples(commonConfig);

Expand Down Expand Up @@ -231,4 +237,23 @@ describe(`generator - ${clientFramework}`, () => {
expect(runResult.getSnapshot('**/entities/admin/user-management/**')).toMatchSnapshot();
});
});

describe('json blob content type', () => {
before(async () => {
await helpers
.runJHipster(generator)
.withJHipsterConfig({ ...commonConfig, applicationType: 'monolith', authenticationType: 'jwt' }, [jsonBlobEntity])
.withSharedApplication({ gatewayServicesApiAvailable: false })
.withSharedApplication({ getWebappTranslation: () => 'translations' })
.withMockedSource()
.withMockedGenerators(['jhipster:common', 'jhipster:client:i18n']);
});

it('should render json blobs as textarea inputs', () => {
const updateFile = `${CLIENT_MAIN_SRC_DIR}app/entities/json-blob/update/json-blob-update.html`;
runResult.assertFileContent(updateFile, 'name="payload" id="field_payload" data-cy="payload"');
runResult.assertFileContent(updateFile, '<textarea class="form-control" name="payload"');
runResult.assertNoFileContent(updateFile, 'id="file_payload"');
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ exports[`generator - app:bootstrap with default config should prepare EntityA 1`
"autoGenerateByService": false,
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"columnName": "id",
"entity": Any<Object>,
Expand Down Expand Up @@ -184,6 +185,7 @@ exports[`generator - app:bootstrap with default config should prepare EntityA 1`
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"columnName": "name",
"entity": Any<Object>,
Expand Down Expand Up @@ -266,6 +268,7 @@ exports[`generator - app:bootstrap with default config should prepare EntityA 1`
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"columnName": "details",
"entity": Any<Object>,
Expand Down Expand Up @@ -568,6 +571,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
"autoGenerateByService": false,
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "id",
Expand Down Expand Up @@ -667,6 +671,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "login",
Expand Down Expand Up @@ -766,6 +771,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "first_name",
Expand Down Expand Up @@ -855,6 +861,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "last_name",
Expand Down Expand Up @@ -944,6 +951,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "email",
Expand Down Expand Up @@ -1038,6 +1046,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "lang_key",
Expand Down Expand Up @@ -1126,6 +1135,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "image_url",
Expand Down Expand Up @@ -1215,6 +1225,7 @@ exports[`generator - app:bootstrap with default config should prepare User 1`] =
"autoGenerate": true,
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"builtIn": true,
"columnName": "activated",
Expand Down Expand Up @@ -1509,6 +1520,7 @@ exports[`generator - app:bootstrap with skipUserManagement should prepare Entity
"autoGenerateByService": false,
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"columnName": "id",
"entity": Any<Object>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ exports[`mutation object test expects mutateField to match snapshot 1`] = `
{
"blobContentTypeAny": false,
"blobContentTypeImage": false,
"blobContentTypeJson": false,
"blobContentTypeText": false,
"fieldIsEnum": true,
"fieldNameCapitalized": "FieldName",
Expand Down
4 changes: 3 additions & 1 deletion generators/base-application/entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ import { pluralize } from '../../lib/utils/string-utils.ts';
import { isFieldEnumType } from './internal/types/field-types.ts';
import type { FakerWithRandexp } from './support/faker.ts';

const { IMAGE, ANY, TEXT, JSON } = BlobTypes;

type Property = {
propertyName: string;

Expand Down Expand Up @@ -120,7 +122,7 @@ export const mutateField = {
fieldIsEnum: data => isFieldEnumType(data),
...buildMutateDataForProperty('fieldType', Object.values(fieldTypesValues), { anyData: true }),
fieldTypeBytes: ({ fieldTypeByte }) => fieldTypeByte,
...buildMutateDataForProperty('fieldTypeBlobContent', Object.values(BlobTypes), { prefix: 'blobContentType' }),
...buildMutateDataForProperty('fieldTypeBlobContent', [IMAGE, ANY, TEXT, JSON], { prefix: 'blobContentType', anyData: true }),

path: ({ fieldName }) => [fieldName],
propertyName: ({ fieldName }) => fieldName,
Expand Down
4 changes: 4 additions & 0 deletions generators/base-application/internal/types/field-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,10 @@ export function convertFieldBlobType<const F extends BaseApplicationField = Base
field.fieldTypeBlobContent = undefined;
break;
}
case 'json': {
field.fieldType = 'TextBlob';
break;
}
default: {
// Unknown type is not supported.
// Fallback to ByteBuffer for cassandra databases.
Expand Down
10 changes: 7 additions & 3 deletions generators/base-application/support/prepare-entity.ts
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ const { CASSANDRA, COUCHBASE, NEO4J, SQL, MONGODB } = databaseTypes;
const { INSTANT, ZONED_DATE_TIME, DURATION, LOCAL_DATE, BIG_DECIMAL, LOCAL_TIME } = fieldTypes.CommonDBTypes;

const { BYTES, BYTE_BUFFER } = fieldTypes.RelationalOnlyDBTypes;
const { IMAGE, TEXT } = fieldTypes.BlobTypes;
const { IMAGE, TEXT, JSON } = fieldTypes.BlobTypes;

const BASE_TEMPLATE_DATA = {
primaryKey: undefined,
Expand Down Expand Up @@ -446,8 +446,12 @@ export function preparePostEntityCommonDerivedProperties(entity: BaseApplication
const blobFields = fields.filter(({ fieldType }) => ([BYTES, BYTE_BUFFER] as string[]).includes(fieldType));
const blobFieldsContentType = sortedUniq(blobFields.map(({ fieldTypeBlobContent }) => fieldTypeBlobContent));
entity.anyFieldHasImageContentType = blobFieldsContentType.includes(IMAGE);
entity.anyFieldHasFileBasedContentType = blobFieldsContentType.some(fieldTypeBlobContent => fieldTypeBlobContent !== TEXT);
entity.anyFieldHasTextContentType = blobFieldsContentType.includes(TEXT);
entity.anyFieldHasFileBasedContentType = blobFieldsContentType.some(
fieldTypeBlobContent => fieldTypeBlobContent !== TEXT && fieldTypeBlobContent !== JSON,
);
entity.anyFieldHasTextContentType = blobFieldsContentType.some(
fieldTypeBlobContent => fieldTypeBlobContent === TEXT || fieldTypeBlobContent === JSON,
);
}

preparePostEntityCommonDerivedPropertiesNotTyped(entity as EntityAll);
Expand Down
25 changes: 25 additions & 0 deletions generators/base-application/support/prepare-field.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import { beforeEach, describe, expect, it } from 'esmocha';
import { getConfigWithDefaults } from '../../../lib/jhipster/default-application-options.ts';
import BaseGenerator from '../../base/index.ts';
import { formatDateForChangelog } from '../../base/support/index.ts';
import { convertFieldBlobType } from '../internal/types/field-types.ts';

import prepareEntityForTemplates, { loadRequiredConfigIntoEntity } from './prepare-entity.ts';
import { getEnumValuesWithCustomValues, prepareCommonFieldForTemplates } from './prepare-field.ts';
Expand All @@ -47,6 +48,30 @@ describe('generator - base-application - support - prepareField', () => {
expect(field.path).toEqual(['name']);
});
});

describe('when fieldTypeBlobContent is json', () => {
it('should convert byte[] into TextBlob and keep json marker', () => {
const field: any = { fieldType: 'byte[]', fieldTypeBlobContent: 'json' };

convertFieldBlobType(field);

expect(field).toMatchObject({
fieldType: 'TextBlob',
fieldTypeBlobContent: 'json',
});
});

it('should treat json-clob as text-like blob data', () => {
const preparedField = prepareCommonFieldForTemplates(
defaultEntity,
{ fieldName: 'payload', fieldType: 'TextBlob', fieldTypeBlobContent: 'json' } as any,
defaultGenerator as any,
);

expect(preparedField.blobContentTypeText).toBe(true);
expect(preparedField.fieldWithContentType).toBe(false);
});
});
});

describe('getEnumValuesWithCustomValues', () => {
Expand Down
10 changes: 6 additions & 4 deletions generators/base-application/support/prepare-field.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ const {
Validations: { MINLENGTH, MAXLENGTH, PATTERN, REQUIRED, UNIQUE },
} = validations;

const { TEXT } = BlobTypes;
const { TEXT, JSON } = BlobTypes;
const { BOOLEAN, BIG_DECIMAL, DOUBLE, DURATION, FLOAT, INSTANT, INTEGER, LOCAL_DATE, LONG, STRING, UUID, ZONED_DATE_TIME, LOCAL_TIME } =
CommonDBTypes;
const { BYTES, BYTE_BUFFER } = RelationalOnlyDBTypes;
Expand Down Expand Up @@ -217,9 +217,9 @@ function generateFakeDataForField(
data = data.slice(0, -3);
}
}
} else if (field.fieldTypeBinary && field.fieldTypeBlobContent !== TEXT) {
} else if (field.fieldTypeBinary && ![TEXT, JSON].includes(field.fieldTypeBlobContent as any)) {
data = '../fake-data/blob/hipster.png';
} else if (field.fieldTypeBinary && field.fieldTypeBlobContent === TEXT) {
} else if (field.fieldTypeBinary && [TEXT, JSON].includes(field.fieldTypeBlobContent as any)) {
data = '../fake-data/blob/hipster.txt';
} else if (field.fieldType === STRING) {
data = field.id ? faker.string.uuid() : faker.helpers.fake(fakeStringTemplateForFieldName((field as DatabaseProperty).columnName!));
Expand Down Expand Up @@ -288,6 +288,7 @@ export function prepareCommonFieldForTemplates(
generator: CoreGenerator,
): BaseApplicationField {
mutateData(field, mutateField);
field.blobContentTypeText = field.blobContentTypeText || field.fieldTypeBlobContent === JSON;

defaults(field, {
entity: entityWithConfig,
Expand All @@ -302,7 +303,8 @@ export function prepareCommonFieldForTemplates(
field.enumValues = getEnumValuesWithCustomValues(field.fieldValues!);
}

field.fieldWithContentType = (fieldType === BYTES || fieldType === BYTE_BUFFER) && field.fieldTypeBlobContent !== TEXT;
field.fieldWithContentType =
(fieldType === BYTES || fieldType === BYTE_BUFFER) && ![TEXT, JSON].includes(field.fieldTypeBlobContent as any);
if (field.fieldWithContentType) {
field.contentTypeFieldName = `${field.fieldName}ContentType`;
}
Expand Down
Loading
Loading