diff --git a/src/common/__tests__/version.test.ts b/src/common/__tests__/version.test.ts index d061dc7..d658978 100644 --- a/src/common/__tests__/version.test.ts +++ b/src/common/__tests__/version.test.ts @@ -1,7 +1,7 @@ import { getFileVersion } from '#/common/getFileVersion'; import { getVersion } from '#/common/getVersion'; import * as getFindFile from '#/modules/files/getFindFile'; -import * as getOutputDirectory from '#/modules/files/getOutputDirectory'; +import * as getOutputDirPath from '#/modules/files/getOutputDirPath'; import dayjs from 'dayjs'; import fs from 'fs'; import { describe, expect, test, vitest } from 'vitest'; @@ -78,7 +78,7 @@ describe('getVersion', () => { .spyOn(fs.promises, 'readFile') .mockImplementation(() => Promise.resolve(Buffer.from('1.1.1'))); const tspSpyOn04 = vitest - .spyOn(getOutputDirectory, 'getOutputDirectory') + .spyOn(getOutputDirPath, 'getOutputDirPath') .mockImplementation(() => Promise.resolve('/a/b/c')); const version = await getVersion({ version: '1.1.1' }, { versionFrom: 'file', versionPath: '/a/b/c' }); diff --git a/src/common/getVersion.ts b/src/common/getVersion.ts index d223357..15c3929 100644 --- a/src/common/getVersion.ts +++ b/src/common/getVersion.ts @@ -3,7 +3,7 @@ import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; import type { IBuildCommandOption } from '#/configs/interfaces/IBuildCommandOption'; import { getCwd } from '#/configs/modules/getCwd'; import { getFindFile } from '#/modules/files/getFindFile'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import dayjs from 'dayjs'; import fs from 'fs'; import pathe from 'pathe'; @@ -14,7 +14,7 @@ async function getVersionFilename( ) { if (option.versionPath != null) { const filename = await getFindFile( - pathe.join(await getOutputDirectory({ output: option.versionPath }, getCwd(process.env)), versionFilename), + pathe.join(await getOutputDirPath({ output: option.versionPath }, getCwd(process.env)), versionFilename), { cwd: getCwd(process.env) }, ); diff --git a/src/configs/modules/getConfigContent.ts b/src/configs/modules/getConfigContent.ts index 3e2fb11..90a7b9c 100644 --- a/src/configs/modules/getConfigContent.ts +++ b/src/configs/modules/getConfigContent.ts @@ -36,7 +36,7 @@ export async function getConfigContent() { */ const sourceGlobFiles = new Glob(['**/*.js', '**/*.cjs', '**/*.mjs', '**/*.ts', '**/*.cts', '**/*.mts'], { - absolute: true, + // absolute: true, ignore: defaultExclude, cwd: process.cwd(), onlyFiles: true, @@ -44,7 +44,7 @@ export async function getConfigContent() { const sourceFiles = getGlobFiles(sourceGlobFiles); const everyGlobFiles = new Glob(['**/*'], { - absolute: true, + // absolute: true, ignore: defaultExclude, cwd: process.cwd(), dot: true, @@ -53,7 +53,7 @@ export async function getConfigContent() { const everyFiles = getGlobFiles(everyGlobFiles); const directoryGlobDirPaths = new Glob(['**/*'], { - absolute: true, + // absolute: true, ignore: defaultExclude, cwd: process.cwd(), dot: true, @@ -214,7 +214,7 @@ export async function getConfigContent() { ]); const templateDir = await (answer.isEjectTemplate - ? ejecting({ output: getCwd(process.env), showLogo: false }) + ? ejecting({ templatePath: pathe.join(getCwd(process.env), CE_DEFAULT_VALUE.TEMPLATES_PATH), showLogo: false }) : Promise.resolve(undefined)); const renderer = container.resolve(SymbolTemplateRenderer); const file = await renderer.evaluate(CE_TEMPLATE_NAME.CONFIG_JSON, { diff --git a/src/creators/createHtml.ts b/src/creators/createHtml.ts index 776c648..9db295b 100644 --- a/src/creators/createHtml.ts +++ b/src/creators/createHtml.ts @@ -7,7 +7,7 @@ import type { getRenderData } from '#/creators/getRenderData'; import type { IErdiaDocument } from '#/creators/interfaces/IErdiaDocument'; import { container } from '#/modules/containers/container'; import { SymbolTemplateRenderer } from '#/modules/containers/keys/SymbolTemplateRenderer'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import type { TemplateRenderer } from '#/templates/TemplateRenderer'; import { CE_TEMPLATE_NAME } from '#/templates/cosnt-enum/CE_TEMPLATE_NAME'; import consola from 'consola'; @@ -65,7 +65,7 @@ export async function createHtml( option: Pick, renderData: AsyncReturnType, ) { - const outputDir = await getOutputDirectory(option, getCwd(process.env)); + const outputDir = await getOutputDirPath(option, getCwd(process.env)); consola.info(`export component: ${option.components.join(', ')}`); diff --git a/src/creators/createMarkdown.ts b/src/creators/createMarkdown.ts index e74c4b0..6ef022a 100644 --- a/src/creators/createMarkdown.ts +++ b/src/creators/createMarkdown.ts @@ -1,12 +1,13 @@ import type { IBuildCommandOption } from '#/configs/interfaces/IBuildCommandOption'; +import { getCwd } from '#/configs/modules/getCwd'; import { applyPrettier } from '#/creators/applyPretter'; import type { getRenderData } from '#/creators/getRenderData'; import type { IErdiaDocument } from '#/creators/interfaces/IErdiaDocument'; import { container } from '#/modules/containers/container'; import { SymbolTemplateRenderer } from '#/modules/containers/keys/SymbolTemplateRenderer'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import type { TemplateRenderer } from '#/templates/TemplateRenderer'; import { CE_TEMPLATE_NAME } from '#/templates/cosnt-enum/CE_TEMPLATE_NAME'; -import { getDirname } from 'my-node-fp'; import pathe from 'pathe'; import type { AsyncReturnType } from 'type-fest'; @@ -18,7 +19,7 @@ export async function createMarkdown( const rawMarkdown = await renderer.evaluate(CE_TEMPLATE_NAME.MARKDOWN_DOCUMENT, renderData); const prettiedMarkdown = await applyPrettier(rawMarkdown, 'md', option.prettierConfig); const markdownFileName = `${renderData.metadata.name}.md`; - const outputDir = await getDirname(option.output ?? process.cwd()); + const outputDir = await getOutputDirPath(option, getCwd(process.env)); return { filename: pathe.resolve(pathe.join(outputDir, markdownFileName)), diff --git a/src/databases/flushDatabase.ts b/src/databases/flushDatabase.ts index ddc78c4..e8331c4 100644 --- a/src/databases/flushDatabase.ts +++ b/src/databases/flushDatabase.ts @@ -1,7 +1,7 @@ import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; import type { IBuildCommandOption } from '#/configs/interfaces/IBuildCommandOption'; import type { TDatabaseRecord } from '#/databases/interfaces/TDatabaseRecord'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import fs from 'node:fs'; import pathe from 'pathe'; @@ -9,7 +9,7 @@ export async function flushDatabase( option: Pick, records: TDatabaseRecord[], ): Promise { - const dirname = await getOutputDirectory({ output: option.databasePath }, process.cwd()); + const dirname = await getOutputDirPath({ output: option.databasePath }, process.cwd()); const filename = pathe.join(dirname, CE_DEFAULT_VALUE.DATABASE_FILENAME); if (filename == null) { diff --git a/src/databases/openDatabase.ts b/src/databases/openDatabase.ts index 60f61ef..d016be3 100644 --- a/src/databases/openDatabase.ts +++ b/src/databases/openDatabase.ts @@ -1,7 +1,7 @@ import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; import type { IBuildCommandOption } from '#/configs/interfaces/IBuildCommandOption'; import type { TDatabaseRecord } from '#/databases/interfaces/TDatabaseRecord'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import { parse } from 'jsonc-parser'; import { isFalse } from 'my-easy-fp'; import { exists } from 'my-node-fp'; @@ -9,7 +9,7 @@ import fs from 'node:fs'; import pathe from 'pathe'; export async function openDatabase(option: Pick): Promise { - const dirname = await getOutputDirectory({ output: option.databasePath }, process.cwd()); + const dirname = await getOutputDirPath({ output: option.databasePath }, process.cwd()); const filename = pathe.join(dirname, CE_DEFAULT_VALUE.DATABASE_FILENAME); if (filename == null) { diff --git a/src/modules/commands/cleaning.ts b/src/modules/commands/cleaning.ts index 7c068b8..66691f2 100644 --- a/src/modules/commands/cleaning.ts +++ b/src/modules/commands/cleaning.ts @@ -4,7 +4,7 @@ import type { ICommonOption } from '#/configs/interfaces/ICommonOption'; import { getCwd } from '#/configs/modules/getCwd'; import { container } from '#/modules/containers/container'; import { SymbolDataSource } from '#/modules/containers/keys/SymbolDataSource'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import { getDataSource } from '#/typeorm/getDataSource'; import { showLogo } from '@maeum/cli-logo'; import { asValue } from 'awilix'; @@ -37,7 +37,7 @@ export async function cleaning(option: ICommonOption) { container.register(SymbolDataSource, asValue(dataSource)); const metadata = await getMetadata({ ...option, versionFrom: 'package.json', projectName: 'app' }); - const outputDirPath = await getOutputDirectory(option, getCwd(process.env)); + const outputDirPath = await getOutputDirPath(option, getCwd(process.env)); const filenames = [ pathe.join(outputDirPath, CE_DEFAULT_VALUE.HTML_MERMAID_FILENAME), diff --git a/src/modules/commands/ejecting.ts b/src/modules/commands/ejecting.ts index 56fdde9..9e87ab8 100644 --- a/src/modules/commands/ejecting.ts +++ b/src/modules/commands/ejecting.ts @@ -1,32 +1,36 @@ import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; import type { ICommonOption } from '#/configs/interfaces/ICommonOption'; +import type { IDocumentOption } from '#/configs/interfaces/IDocumentOption'; import { getCwd } from '#/configs/modules/getCwd'; import { container } from '#/modules/containers/container'; import { SymbolLogger } from '#/modules/containers/keys/SymbolLogger'; import { betterMkdir } from '#/modules/files/betterMkdir'; import { getGlobFiles } from '#/modules/files/getGlobFiles'; -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getTemplateDirPath } from '#/modules/files/getTemplateDirPath'; import type { Logger } from '#/modules/loggers/Logger'; import { createLogger } from '#/modules/loggers/createLogger'; import { defaultExclude } from '#/modules/scopes/defaultExclude'; -import { getTemplatePath } from '#/templates/modules/getTemplatePath'; +import { getTemplateModulePath } from '#/templates/modules/getTemplateModulePath'; import { Glob } from 'glob'; import { isError } from 'my-easy-fp'; import { getDirname, startSepRemove } from 'my-node-fp'; import fs from 'node:fs'; import pathe from 'pathe'; -export async function ejecting(option: Pick, logging?: boolean) { +export async function ejecting( + option: Pick, + logging?: boolean, +) { createLogger(logging); const logger = container.resolve(SymbolLogger); try { - const outputDirPath = await getOutputDirectory(option, getCwd(process.env)); - const originTemplateDirPath = await getTemplatePath(CE_DEFAULT_VALUE.TEMPLATES_PATH); + const templateDirPath = await getTemplateDirPath(option, getCwd(process.env)); + const originTemplateDirPath = await getTemplateModulePath(CE_DEFAULT_VALUE.TEMPLATES_PATH); const targetTemplateDirPath = - option.output == null ? pathe.join(outputDirPath, CE_DEFAULT_VALUE.TEMPLATES_PATH) : outputDirPath; + option.templatePath == null ? pathe.join(templateDirPath, CE_DEFAULT_VALUE.TEMPLATES_PATH) : templateDirPath; - logger.info('Output directory: ', targetTemplateDirPath); + logger.info('Template directory: ', targetTemplateDirPath); const originTemplateGlobPaths = new Glob(pathe.join(originTemplateDirPath, `**`, '*.eta'), { absolute: true, diff --git a/src/modules/files/__tests__/file.test.ts b/src/modules/files/__tests__/file.test.ts index fe093b2..b712207 100644 --- a/src/modules/files/__tests__/file.test.ts +++ b/src/modules/files/__tests__/file.test.ts @@ -1,4 +1,4 @@ -import { getOutputDirectory } from '#/modules/files/getOutputDirectory'; +import { getOutputDirPath } from '#/modules/files/getOutputDirPath'; import { getPuppeteerConfig } from '#/modules/getPuppeteerConfig'; import { getSlashEndRoutePath } from '#/modules/getSlashEndRoutePath'; import * as mnf from 'my-node-fp'; @@ -31,7 +31,7 @@ describe('getOutputDirectory', () => { const existsSpyOn = vitest.spyOn(mnf, 'exists').mockImplementation(() => Promise.resolve(false)); const mkdirSpyOn = vitest.spyOn(fs.promises, 'mkdir').mockImplementation(() => Promise.resolve('')); - const p = await getOutputDirectory({ output: undefined }, 'i-am-cwd'); + const p = await getOutputDirPath({ output: undefined }, 'i-am-cwd'); existsSpyOn.mockRestore(); mkdirSpyOn.mockRestore(); @@ -44,7 +44,7 @@ describe('getOutputDirectory', () => { const isDirectorySpyOn = vitest.spyOn(mnf, 'isDirectory').mockImplementation(() => Promise.resolve(false)); const mkdirSpyOn = vitest.spyOn(fs.promises, 'mkdir').mockImplementation(() => Promise.resolve('')); - const p = await getOutputDirectory({ output: undefined }, 'examples'); + const p = await getOutputDirPath({ output: undefined }, 'examples'); existsSpyOn.mockRestore(); isDirectorySpyOn.mockRestore(); @@ -58,7 +58,7 @@ describe('getOutputDirectory', () => { const isDirectorySpyOn = vitest.spyOn(mnf, 'isDirectory').mockImplementation(() => Promise.resolve(true)); const mkdirSpyOn = vitest.spyOn(fs.promises, 'mkdir').mockImplementation(() => Promise.resolve('')); - const p = await getOutputDirectory({ output: undefined }, 'examples'); + const p = await getOutputDirPath({ output: undefined }, 'examples'); existsSpyOn.mockRestore(); isDirectorySpyOn.mockRestore(); diff --git a/src/modules/files/getOutputDirectory.ts b/src/modules/files/getOutputDirPath.ts similarity index 87% rename from src/modules/files/getOutputDirectory.ts rename to src/modules/files/getOutputDirPath.ts index c0ad5a2..0b01184 100644 --- a/src/modules/files/getOutputDirectory.ts +++ b/src/modules/files/getOutputDirPath.ts @@ -4,7 +4,7 @@ import { isFalse } from 'my-easy-fp'; import { exists, getDirname, isDirectory } from 'my-node-fp'; import pathe from 'pathe'; -export async function getOutputDirectory(option: Pick, cwd: string) { +export async function getOutputDirPath(option: Pick, cwd: string) { const outputDirPath = option.output ?? cwd; const resolvedOutputDirPath = pathe.resolve(outputDirPath); diff --git a/src/modules/files/getTemplateDirPath.ts b/src/modules/files/getTemplateDirPath.ts new file mode 100644 index 0000000..1529806 --- /dev/null +++ b/src/modules/files/getTemplateDirPath.ts @@ -0,0 +1,22 @@ +import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; +import type { IDocumentOption } from '#/configs/interfaces/IDocumentOption'; +import { betterMkdir } from '#/modules/files/betterMkdir'; +import { isFalse } from 'my-easy-fp'; +import { exists, getDirname, isDirectory } from 'my-node-fp'; +import pathe from 'pathe'; + +export async function getTemplateDirPath(option: Pick, cwd: string) { + const templateDirPath = pathe.join(option.templatePath ?? pathe.join(cwd, CE_DEFAULT_VALUE.TEMPLATES_PATH)); + const resolvedTemplateDirPath = pathe.resolve(templateDirPath); + + if (isFalse(await exists(resolvedTemplateDirPath))) { + await betterMkdir(pathe.join(resolvedTemplateDirPath)); + return resolvedTemplateDirPath; + } + + if (isFalse(await isDirectory(templateDirPath))) { + return pathe.resolve(await getDirname(templateDirPath)); + } + + return pathe.resolve(templateDirPath); +} diff --git a/templates/config/json.eta b/src/templates/modules/configTemplate.ts similarity index 97% rename from templates/config/json.eta rename to src/templates/modules/configTemplate.ts index 32e2290..c0df03b 100644 --- a/templates/config/json.eta +++ b/src/templates/modules/configTemplate.ts @@ -1,3 +1,4 @@ +export const configTemplate = ` { // directory for output files "output": "<%= it.config.output %>", @@ -21,7 +22,7 @@ <% } %> // erdia entity database file path - <% if (it.config.templatePath != null) { %> + <% if (it.config.databasePath != null) { %> "database-path": "<%= it.config.databasePath %>", <% } else { %> // "database-path": "", @@ -46,7 +47,7 @@ // output format of generated documents // - html - // - markdown + // - md // - pdf // - image "format": "<%= it.config.format %>", @@ -104,3 +105,4 @@ // "image-format": "svg", <% } %> } +`; diff --git a/src/templates/modules/getTemplateModulePath.ts b/src/templates/modules/getTemplateModulePath.ts new file mode 100644 index 0000000..08fda0b --- /dev/null +++ b/src/templates/modules/getTemplateModulePath.ts @@ -0,0 +1,29 @@ +import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; +import { exists } from 'my-node-fp'; +import pathe from 'pathe'; + +export async function getTemplateModulePath(templatePathParam?: string): Promise { + const currentFilePath = pathe.resolve(__dirname); + + if (templatePathParam != null) { + const currentWithTemplatePath = pathe.resolve(pathe.join(currentFilePath, templatePathParam)); + if (await exists(currentWithTemplatePath)) { + return currentWithTemplatePath; + } + } + + const packageRootTemplatePath = pathe.resolve( + pathe.join(currentFilePath, '..', '..', '..', CE_DEFAULT_VALUE.TEMPLATES_PATH), + ); + + if (await exists(packageRootTemplatePath)) { + return packageRootTemplatePath; + } + + const distTemplatePath = pathe.resolve(pathe.join(currentFilePath, '..', '..', CE_DEFAULT_VALUE.TEMPLATES_PATH)); + if (await exists(distTemplatePath)) { + return distTemplatePath; + } + + throw new Error('cannot found template directory!'); +} diff --git a/src/templates/modules/getTemplatePath.ts b/src/templates/modules/getTemplatePath.ts index 8679926..cd50973 100644 --- a/src/templates/modules/getTemplatePath.ts +++ b/src/templates/modules/getTemplatePath.ts @@ -1,4 +1,4 @@ -import { CE_DEFAULT_VALUE } from '#/configs/const-enum/CE_DEFAULT_VALUE'; +import { getTemplateModulePath } from '#/templates/modules/getTemplateModulePath'; import { exists } from 'my-node-fp'; import pathe from 'pathe'; @@ -7,27 +7,5 @@ export async function getTemplatePath(templatePathParam?: string): Promise) { const defaultTemplatePath = await getTemplatePath(CE_DEFAULT_VALUE.TEMPLATES_PATH); - const [defaultConfig, defaultHtml, defaultMarkdown, defaultImage, defaultPdf] = await Promise.all([ - getTemplates(pathe.join(defaultTemplatePath, 'config'), {}), + const [defaultHtml, defaultMarkdown, defaultImage, defaultPdf] = await Promise.all([ getTemplates(pathe.join(defaultTemplatePath, 'html'), {}), getTemplates(pathe.join(defaultTemplatePath, 'markdown'), {}), getTemplates(pathe.join(defaultTemplatePath, 'image'), {}), @@ -15,7 +15,7 @@ export async function loadTemplates(option?: Pick([ - ...defaultConfig.map((template): [string, string] => [`config-${template.key}`, template.content]), + ['config-json', configTemplate.trim()], ...defaultHtml.map((template): [string, string] => [`html-${template.key}`, template.content]), ...defaultMarkdown.map((template): [string, string] => [`markdown-${template.key}`, template.content]), ...defaultImage.map((template): [string, string] => [`image-${template.key}`, template.content]), @@ -38,7 +38,7 @@ export async function loadTemplates(option?: Pick([ - ...defaultConfig.map((template): [string, string] => [`config-${template.key}`, template.content]), + ['config-json', configTemplate.trim()], ...templateHtml.map((template): [string, string] => [`html-${template.key}`, template.content]), ...templateMarkdown.map((template): [string, string] => [`markdown-${template.key}`, template.content]), ...templateImage.map((template): [string, string] => [`image-${template.key}`, template.content]),