Skip to content

Commit

Permalink
editFile api
Browse files Browse the repository at this point in the history
  • Loading branch information
mshima committed Jun 16, 2022
1 parent e8ecdb4 commit c74a09e
Show file tree
Hide file tree
Showing 5 changed files with 132 additions and 15 deletions.
45 changes: 32 additions & 13 deletions generators/generator-base.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ const {
},
} = require('../lib/constants/priorities.cjs');
const { insertContentIntoApplicationProperties } = require('./server/needles.cjs');
const { joinCallbacks } = require('../lib/support/base.cjs');

const JHIPSTER_CONFIG_DIR = constants.JHIPSTER_CONFIG_DIR;
const MODULES_HOOK_FILE = `${JHIPSTER_CONFIG_DIR}/modules/jhi-hooks.json`;
Expand Down Expand Up @@ -110,9 +111,14 @@ const isWin32 = os.platform() === 'win32';
* @param {JHipsterBaseGenerator} this
* @param {string} content
* @param {string} filePath
* @returns {string} new content
* @returns {CascatedEditFileCallback} callback for cascated edit
*/

/**
* @callback CascatedEditFileCallback
* @param {...EditFileCallback} callbacks
* @returns {CascatedEditFileCallback} callback for cascated edit
*/
/**
* This is the Generator base class.
* This provides all the public API methods exposed via the module system.
Expand Down Expand Up @@ -3439,27 +3445,40 @@ templates: ${JSON.stringify(existingTemplates, null, 2)}`;
* Edit file content
* @param {string} file
* @param {...EditFileCallback} transformCallbacks
* @returns {CascatedEditFileCallback}
*/
editFile(file, ...transformCallbacks) {
let filePath = this.destinationPath(file);
if (!this.env.sharedFs.existsInMemory(filePath) && this.env.sharedFs.existsInMemory(`${filePath}.jhi`)) {
filePath = `${filePath}.jhi`;
}
let content = this.readDestination(filePath);
if (isWin32 && content.match(/\r\n/)) {
transformCallbacks = [content => content.replace(/\r\n/g, '\n')].concat(transformCallbacks, content =>
content.replace(/\n/g, '\r\n')
);
}

let content;

const writeCallback = (...callbacks) => {
try {
content = joinCallbacks(...callbacks)(content, filePath);
this.writeDestination(filePath, content);
} catch (error) {
throw new Error(`Error editing file ${filePath}: ${error.message} at ${error.stack}`);
}
return writeCallback;
};

try {
for (const cb of transformCallbacks) {
content = cb.call(this, content, filePath);
content = this.readDestination(filePath);
if (transformCallbacks.length === 0) {
return writeCallback;
}
} catch (error) {
throw new Error(`Error editing file ${filePath}: ${error.message} at ${error.stack}`);
} catch (_error) {
if (transformCallbacks.length === 0) {
throw new Error(`File ${filePath} doesn't exist`);
}
// allow to edit non existing files
content = '';
}
this.writeDestination(filePath, content);
return content;

return writeCallback(...transformCallbacks);
}
}

Expand Down
2 changes: 1 addition & 1 deletion generators/server/needles.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ const { createBaseNeedle } = require('../../lib/support/needles.cjs');
* );
* @param {import('../generator-base.js')} [generator]
* @param {ApplicationPropertiesNeedles} needles
* @returns {string | import('../../generators/generator-base.js').EditFileCallback}
* @returns {import('../../generators/generator-base.js').CascatedEditFileCallback | import('../../generators/generator-base.js').EditFileCallback}
*/
const insertContentIntoApplicationProperties = (generator, needles) => {
if (!needles) {
Expand Down
43 changes: 43 additions & 0 deletions lib/support/base.cjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/**
* Copyright 2013-2022 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const { platform } = require('os');

const isWin32 = platform() === 'win32';

/**
* Converts multiples EditFileCallback callbacks into one.
*
* @param {...import('../../generators/generator-base.js').EditFileCallback} callbacks
* @returns {import('../../generators/generator-base.js').EditFileCallback}
*/
const joinCallbacks = (...callbacks) => {
return (content, filePath) => {
if (isWin32 && content.match(/\r\n/)) {
callbacks = [content => content.replace(/\r\n/g, '\n')].concat(callbacks, content => content.replace(/\n/g, '\r\n'));
}
for (const callback of callbacks) {
content = callback(content, filePath);
}
return content;
};
};

module.exports = {
joinCallbacks,
};
55 changes: 55 additions & 0 deletions lib/support/base.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
/**
* Copyright 2013-2022 the original author or authors from the JHipster project.
*
* This file is part of the JHipster project, see https://www.jhipster.tech/
* for more information.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { expect } from 'expect';
import jest from 'jest-mock';

import { joinCallbacks } from './base.cjs';

describe('base support', () => {
describe('joinCallbacks', () => {
it('should return a function', () => {
expect(typeof joinCallbacks()).toBe('function');
});

it('without callbacks, should return the original content', () => {
expect(joinCallbacks()('original')).toBe('original');
});

it('with a callback, should return the callback return', () => {
const mock = jest.fn().mockReturnValue('return1');
const callback = joinCallbacks(mock);

expect(callback('original', 'file')).toBe('return1');

expect(mock.mock.calls[0][0]).toBe('original');
expect(mock.mock.calls[0][1]).toBe('file');
});

it('with two callbacks, should forward last callback and return the last callback return', () => {
const mock1 = jest.fn().mockReturnValue('return1');
const mock2 = jest.fn().mockReturnValue('return2');
const callback = joinCallbacks(mock1, mock2);

expect(callback('original', 'file')).toBe('return2');

expect(mock2.mock.calls[0][0]).toBe('return1');
expect(mock2.mock.calls[0][1]).toBe('file');
});
});
});
2 changes: 1 addition & 1 deletion lib/support/needles.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ const createNeedleCallback = ({ needle, contentToAdd, optional = false, ignoreWh
* @param {string} [options.filePath] path to file
* @param {string} [options.needlesPrefix] common needle prefix
* @param {boolean} [options.optional=false] throw error if needle was not found
* @returns {string | import('../../generators/generator-base.js').EditFileCallback}
* @returns {import('../../generators/generator-base.js').CascatedEditFileCallback | import('../../generators/generator-base.js').EditFileCallback}
*/
const createBaseNeedle = (options, needles) => {
if (!needles) {
Expand Down

0 comments on commit c74a09e

Please sign in to comment.