Relocate templatingTask into executeTemplate
Signed-off-by: Min Kim <minkimcello@gmail.com>
This commit is contained in:
@@ -87,9 +87,6 @@ export default async () => {
|
||||
try {
|
||||
await executePluginPackageTemplate(
|
||||
{
|
||||
private: options.private,
|
||||
defaultVersion: options.baseVersion,
|
||||
license: options.license,
|
||||
isMonoRepo: await isMonoRepo(),
|
||||
createTemporaryDirectory,
|
||||
markAsModified() {
|
||||
|
||||
@@ -22,17 +22,18 @@ import {
|
||||
mockPaths,
|
||||
} from './testUtils';
|
||||
import { CreateContext } from './types';
|
||||
import { executePluginPackageTemplate } from './executeTemplate';
|
||||
import {
|
||||
executePluginPackageTemplate,
|
||||
templatingTask,
|
||||
} from './executeTemplate';
|
||||
import { createMockDirectory } from '@backstage/backend-test-utils';
|
||||
|
||||
const mockDir = createMockDirectory();
|
||||
|
||||
mockPaths({
|
||||
ownDir: mockDir.resolve('own'),
|
||||
targetRoot: mockDir.resolve('root'),
|
||||
});
|
||||
|
||||
describe('executePluginPackageTemplate', () => {
|
||||
const mockDir = createMockDirectory();
|
||||
mockPaths({
|
||||
ownDir: mockDir.resolve('own'),
|
||||
targetRoot: mockDir.resolve('root'),
|
||||
});
|
||||
afterEach(() => {
|
||||
jest.resetAllMocks();
|
||||
});
|
||||
@@ -82,7 +83,7 @@ some-package@^1.1.0:
|
||||
},
|
||||
} as CreateContext,
|
||||
{
|
||||
templateName: 'test-template',
|
||||
templateDir: 'test-template',
|
||||
targetDir: mockDir.resolve('target'),
|
||||
values: {
|
||||
id: 'testing',
|
||||
@@ -122,3 +123,47 @@ some-package@^1.1.0:
|
||||
).resolves.toBe('Hello {{id}}!');
|
||||
});
|
||||
});
|
||||
|
||||
describe('templatingTask', () => {
|
||||
const mockDir = createMockDirectory();
|
||||
|
||||
it('should template a directory with mix of regular files and templates', async () => {
|
||||
// Testing template directory
|
||||
const tmplDir = 'test-tmpl';
|
||||
|
||||
// Temporary dest dir to write the template to
|
||||
const destDir = 'test-dest';
|
||||
|
||||
// Files content
|
||||
const testFileContent = 'testing';
|
||||
const testVersionFileContent =
|
||||
"version: {{pluginVersion}} {{versionQuery 'mock-pkg'}}";
|
||||
|
||||
mockDir.setContent({
|
||||
[tmplDir]: {
|
||||
sub: {
|
||||
'version.txt.hbs': testVersionFileContent,
|
||||
},
|
||||
'test.txt': testFileContent,
|
||||
},
|
||||
[destDir]: {},
|
||||
});
|
||||
|
||||
await templatingTask(
|
||||
mockDir.resolve(tmplDir),
|
||||
mockDir.resolve(destDir),
|
||||
{
|
||||
pluginVersion: '0.0.0',
|
||||
},
|
||||
() => '^0.1.2',
|
||||
true,
|
||||
);
|
||||
|
||||
await expect(
|
||||
fs.readFile(mockDir.resolve(destDir, 'test.txt'), 'utf8'),
|
||||
).resolves.toBe(testFileContent);
|
||||
await expect(
|
||||
fs.readFile(mockDir.resolve(destDir, 'sub/version.txt'), 'utf8'),
|
||||
).resolves.toBe('version: 0.0.0 ^0.1.2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,9 +16,17 @@
|
||||
|
||||
import fs from 'fs-extra';
|
||||
import chalk from 'chalk';
|
||||
import { resolve as resolvePath, relative as relativePath } from 'path';
|
||||
import handlebars from 'handlebars';
|
||||
import recursive from 'recursive-readdir';
|
||||
import {
|
||||
basename,
|
||||
dirname,
|
||||
resolve as resolvePath,
|
||||
relative as relativePath,
|
||||
} from 'path';
|
||||
|
||||
import { paths } from '../paths';
|
||||
import { Task, templatingTask } from '../tasks';
|
||||
import { Task } from '../tasks';
|
||||
import { Lockfile } from '../versioning';
|
||||
import { createPackageVersionProvider } from '../version';
|
||||
import { CreateContext } from './types';
|
||||
@@ -31,7 +39,7 @@ export async function executePluginPackageTemplate(
|
||||
values: Record<string, unknown>;
|
||||
},
|
||||
) {
|
||||
const { targetDir, templateDir } = options;
|
||||
const { targetDir, templateDir, values } = options;
|
||||
|
||||
let lockfile: Lockfile | undefined;
|
||||
try {
|
||||
@@ -60,7 +68,7 @@ export async function executePluginPackageTemplate(
|
||||
await templatingTask(
|
||||
templateDir,
|
||||
tempDir,
|
||||
options.values,
|
||||
values,
|
||||
createPackageVersionProvider(lockfile),
|
||||
ctx.isMonoRepo,
|
||||
);
|
||||
@@ -83,3 +91,63 @@ export async function executePluginPackageTemplate(
|
||||
|
||||
ctx.markAsModified();
|
||||
}
|
||||
|
||||
export async function templatingTask(
|
||||
templateDir: string,
|
||||
destinationDir: string,
|
||||
context: any,
|
||||
versionProvider: (name: string, versionHint?: string) => string,
|
||||
isMonoRepo: boolean,
|
||||
) {
|
||||
const files = await recursive(templateDir).catch(error => {
|
||||
throw new Error(`Failed to read template directory: ${error.message}`);
|
||||
});
|
||||
|
||||
for (const file of files) {
|
||||
const destinationFile = file.replace(templateDir, destinationDir);
|
||||
await fs.ensureDir(dirname(destinationFile));
|
||||
|
||||
if (file.endsWith('.hbs')) {
|
||||
await Task.forItem('templating', basename(file), async () => {
|
||||
const destination = destinationFile.replace(/\.hbs$/, '');
|
||||
|
||||
const template = await fs.readFile(file);
|
||||
const compiled = handlebars.compile(template.toString(), {
|
||||
strict: true,
|
||||
});
|
||||
const contents = compiled(
|
||||
{ name: basename(destination), ...context },
|
||||
{
|
||||
helpers: {
|
||||
versionQuery(name: string, versionHint: string | unknown) {
|
||||
return versionProvider(
|
||||
name,
|
||||
typeof versionHint === 'string' ? versionHint : undefined,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await fs.writeFile(destination, contents).catch(error => {
|
||||
throw new Error(
|
||||
`Failed to create file: ${destination}: ${error.message}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (isMonoRepo && file.match('tsconfig.json')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await Task.forItem('copying', basename(file), async () => {
|
||||
await fs.copyFile(file, destinationFile).catch(error => {
|
||||
const destination = destinationFile;
|
||||
throw new Error(
|
||||
`Failed to copy file to ${destination} : ${error.message}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,18 +17,8 @@
|
||||
import { Answers, DistinctQuestion } from 'inquirer';
|
||||
|
||||
export interface CreateContext {
|
||||
/** The package scope to use for new packages */
|
||||
scope?: string;
|
||||
/** The NPM registry to use for new packages */
|
||||
npmRegistry?: string;
|
||||
/** Whether new packages should be marked as private */
|
||||
private: boolean;
|
||||
/** Whether we are creating something in a monorepo or not */
|
||||
isMonoRepo: boolean;
|
||||
/** The default version to use for new packages */
|
||||
defaultVersion: string;
|
||||
/** License to use for new packages */
|
||||
license: string;
|
||||
|
||||
/** Creates a temporary directory. This will always be deleted after creation is done. */
|
||||
createTemporaryDirectory(name: string): Promise<string>;
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Copyright 2020 The Backstage Authors
|
||||
*
|
||||
* 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
|
||||
*
|
||||
* http://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 fs from 'fs-extra';
|
||||
import { templatingTask } from './tasks';
|
||||
import { createMockDirectory } from '@backstage/backend-test-utils';
|
||||
|
||||
describe('templatingTask', () => {
|
||||
const mockDir = createMockDirectory();
|
||||
|
||||
it('should template a directory with mix of regular files and templates', async () => {
|
||||
// Testing template directory
|
||||
const tmplDir = 'test-tmpl';
|
||||
|
||||
// Temporary dest dir to write the template to
|
||||
const destDir = 'test-dest';
|
||||
|
||||
// Files content
|
||||
const testFileContent = 'testing';
|
||||
const testVersionFileContent =
|
||||
"version: {{pluginVersion}} {{versionQuery 'mock-pkg'}}";
|
||||
|
||||
mockDir.setContent({
|
||||
[tmplDir]: {
|
||||
sub: {
|
||||
'version.txt.hbs': testVersionFileContent,
|
||||
},
|
||||
'test.txt': testFileContent,
|
||||
},
|
||||
[destDir]: {},
|
||||
});
|
||||
|
||||
await templatingTask(
|
||||
mockDir.resolve(tmplDir),
|
||||
mockDir.resolve(destDir),
|
||||
{
|
||||
pluginVersion: '0.0.0',
|
||||
},
|
||||
() => '^0.1.2',
|
||||
true,
|
||||
);
|
||||
|
||||
await expect(
|
||||
fs.readFile(mockDir.resolve(destDir, 'test.txt'), 'utf8'),
|
||||
).resolves.toBe(testFileContent);
|
||||
await expect(
|
||||
fs.readFile(mockDir.resolve(destDir, 'sub/version.txt'), 'utf8'),
|
||||
).resolves.toBe('version: 0.0.0 ^0.1.2');
|
||||
});
|
||||
});
|
||||
@@ -15,12 +15,8 @@
|
||||
*/
|
||||
|
||||
import chalk from 'chalk';
|
||||
import fs from 'fs-extra';
|
||||
import handlebars from 'handlebars';
|
||||
import ora from 'ora';
|
||||
import { promisify } from 'util';
|
||||
import { basename, dirname } from 'path';
|
||||
import recursive from 'recursive-readdir';
|
||||
import { exec as execCb } from 'child_process';
|
||||
import { assertError } from '@backstage/errors';
|
||||
|
||||
@@ -95,63 +91,3 @@ export class Task {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function templatingTask(
|
||||
templateDir: string,
|
||||
destinationDir: string,
|
||||
context: any,
|
||||
versionProvider: (name: string, versionHint?: string) => string,
|
||||
isMonoRepo: boolean,
|
||||
) {
|
||||
const files = await recursive(templateDir).catch(error => {
|
||||
throw new Error(`Failed to read template directory: ${error.message}`);
|
||||
});
|
||||
|
||||
for (const file of files) {
|
||||
const destinationFile = file.replace(templateDir, destinationDir);
|
||||
await fs.ensureDir(dirname(destinationFile));
|
||||
|
||||
if (file.endsWith('.hbs')) {
|
||||
await Task.forItem('templating', basename(file), async () => {
|
||||
const destination = destinationFile.replace(/\.hbs$/, '');
|
||||
|
||||
const template = await fs.readFile(file);
|
||||
const compiled = handlebars.compile(template.toString(), {
|
||||
strict: true,
|
||||
});
|
||||
const contents = compiled(
|
||||
{ name: basename(destination), ...context },
|
||||
{
|
||||
helpers: {
|
||||
versionQuery(name: string, versionHint: string | unknown) {
|
||||
return versionProvider(
|
||||
name,
|
||||
typeof versionHint === 'string' ? versionHint : undefined,
|
||||
);
|
||||
},
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
await fs.writeFile(destination, contents).catch(error => {
|
||||
throw new Error(
|
||||
`Failed to create file: ${destination}: ${error.message}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
} else {
|
||||
if (isMonoRepo && file.match('tsconfig.json')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
await Task.forItem('copying', basename(file), async () => {
|
||||
await fs.copyFile(file, destinationFile).catch(error => {
|
||||
const destination = destinationFile;
|
||||
throw new Error(
|
||||
`Failed to copy file to ${destination} : ${error.message}`,
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user