feat: добавить программный API для использования как библиотеки
- создан src/index.ts с реэкспортом 14 чистых функций и типов - перенесён findNearestTemplatesDir из completion.ts в templateUtils.ts - обновлён package.json: main → dist/index.js, добавлено поле types - добавлен declaration: true в tsconfig.json для генерации .d.ts - документирован API в README.md и README_RU.md - версия поднята до 0.2.0
This commit is contained in:
24
README.md
24
README.md
@@ -117,3 +117,27 @@ export const {{name.pascalCase}} = () => {
|
||||
| `--overwrite` | Overwrite existing files |
|
||||
| `--skip-update` | Skip CLI update check |
|
||||
| `--<variable> <value>` | Custom template variable |
|
||||
|
||||
## Programmatic API
|
||||
|
||||
The package can be used as a library:
|
||||
|
||||
```typescript
|
||||
import { buildPlan, writePlan, collectTemplateVariables } from '@gromlab/create';
|
||||
```
|
||||
|
||||
| Function | Description |
|
||||
|---|---|
|
||||
| `renderTemplate(input, vars)` | Substitutes variables and modifiers in a string |
|
||||
| `collectTemplateVariables(templateDir)` | Collects all variable names from a template |
|
||||
| `listTemplateNames(templatesDir)` | Lists available templates (subdirectories) |
|
||||
| `findNearestTemplatesDir(startDir)` | Walks up the directory tree looking for `.templates` |
|
||||
| `readDirRecursive(dir)` | Recursive list of all files in a directory |
|
||||
| `resolveTemplateContext(templatesDir, name, vars)` | Validates template and variables |
|
||||
| `buildPlan(templateDir, outDir, vars, files)` | Builds generation plan (source → target) |
|
||||
| `writePlan(plan, vars, overwrite)` | Writes files to disk according to the plan |
|
||||
| `getCollisions(plan)` | Lists plan files that already exist on disk |
|
||||
| `getExistingDirs(outDir, dirs)` | Checks which directories already exist |
|
||||
| `getTopLevelDirs(outDir, plan)` | Top-level directories from the plan |
|
||||
| `getRoots(outDir, plan)` | Root paths for summary output |
|
||||
| `CASE_MODIFIERS` | Case modifier functions dictionary |
|
||||
|
||||
24
README_RU.md
24
README_RU.md
@@ -117,3 +117,27 @@ export const {{name.pascalCase}} = () => {
|
||||
| `--overwrite` | Перезаписать существующие файлы |
|
||||
| `--skip-update` | Не проверять обновления CLI |
|
||||
| `--<переменная> <значение>` | Произвольная переменная шаблона |
|
||||
|
||||
## Программный API
|
||||
|
||||
Пакет можно использовать как библиотеку:
|
||||
|
||||
```typescript
|
||||
import { buildPlan, writePlan, collectTemplateVariables } from '@gromlab/create';
|
||||
```
|
||||
|
||||
| Функция | Назначение |
|
||||
|---|---|
|
||||
| `renderTemplate(input, vars)` | Подставляет переменные и модификаторы в строку |
|
||||
| `collectTemplateVariables(templateDir)` | Собирает все имена переменных из шаблона |
|
||||
| `listTemplateNames(templatesDir)` | Список доступных шаблонов (подпапки) |
|
||||
| `findNearestTemplatesDir(startDir)` | Ищет `.templates` вверх по дереву каталогов |
|
||||
| `readDirRecursive(dir)` | Рекурсивный список всех файлов в каталоге |
|
||||
| `resolveTemplateContext(templatesDir, name, vars)` | Валидация шаблона и переменных |
|
||||
| `buildPlan(templateDir, outDir, vars, files)` | Построение плана генерации (source → target) |
|
||||
| `writePlan(plan, vars, overwrite)` | Запись файлов на диск по плану |
|
||||
| `getCollisions(plan)` | Список файлов из плана, которые уже существуют |
|
||||
| `getExistingDirs(outDir, dirs)` | Проверка существующих директорий |
|
||||
| `getTopLevelDirs(outDir, plan)` | Директории верхнего уровня из плана |
|
||||
| `getRoots(outDir, plan)` | Корневые пути для итогового вывода |
|
||||
| `CASE_MODIFIERS` | Словарь модификаторов регистра |
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@gromlab/create",
|
||||
"version": "0.1.7",
|
||||
"version": "0.2.0",
|
||||
"description": "Template-based file generator CLI",
|
||||
"author": "Gromov Sergei",
|
||||
"license": "MIT",
|
||||
@@ -27,7 +27,8 @@
|
||||
"gromlab-create": "dist/cli.js",
|
||||
"create": "dist/cli.js"
|
||||
},
|
||||
"main": "dist/cli.js",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
|
||||
@@ -1,30 +1,12 @@
|
||||
import * as fs from 'fs';
|
||||
import * as path from 'path';
|
||||
import { collectTemplateVariables, listTemplateNames } from './templateUtils';
|
||||
import { collectTemplateVariables, listTemplateNames, findNearestTemplatesDir } from './templateUtils';
|
||||
import { detectRunMode } from './runtime';
|
||||
|
||||
const BIN_NAMES = ['gromlab-create', 'create'];
|
||||
const COMPLETION_BLOCK_START = '# gromlab-create completion start';
|
||||
const COMPLETION_BLOCK_END = '# gromlab-create completion end';
|
||||
|
||||
function findNearestTemplatesDir(startDir: string): string | undefined {
|
||||
let current = path.resolve(startDir);
|
||||
while (true) {
|
||||
const candidate = path.join(current, '.templates');
|
||||
try {
|
||||
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
||||
return candidate;
|
||||
}
|
||||
} catch {
|
||||
// ignore errors and keep walking up
|
||||
}
|
||||
const parent = path.dirname(current);
|
||||
if (parent === current) break;
|
||||
current = parent;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function listTemplates(cwd: string): string[] {
|
||||
const dir = findNearestTemplatesDir(cwd);
|
||||
try {
|
||||
|
||||
21
src/index.ts
Normal file
21
src/index.ts
Normal file
@@ -0,0 +1,21 @@
|
||||
// Программный API для @gromlab/create
|
||||
// CLI точка входа остаётся в cli.ts (bin)
|
||||
|
||||
// Генерация
|
||||
export { buildPlan, writePlan, getCollisions, getExistingDirs, getTopLevelDirs, getRoots } from './plan';
|
||||
|
||||
// Шаблоны
|
||||
export {
|
||||
renderTemplate,
|
||||
collectTemplateVariables,
|
||||
readDirRecursive,
|
||||
listTemplateNames,
|
||||
findNearestTemplatesDir,
|
||||
CASE_MODIFIERS,
|
||||
} from './templateUtils';
|
||||
|
||||
// Валидация
|
||||
export { resolveTemplateContext, normalizeArgs } from './validation';
|
||||
|
||||
// Типы
|
||||
export type { PlanItem, TemplateContext, ValidationError, ParsedArgs } from './types';
|
||||
@@ -70,3 +70,21 @@ export function listTemplateNames(templatesDir: string): string[] {
|
||||
const entries = fs.readdirSync(templatesDir, { withFileTypes: true });
|
||||
return entries.filter((entry) => entry.isDirectory()).map((entry) => entry.name).sort();
|
||||
}
|
||||
|
||||
export function findNearestTemplatesDir(startDir: string): string | undefined {
|
||||
let current = path.resolve(startDir);
|
||||
while (true) {
|
||||
const candidate = path.join(current, '.templates');
|
||||
try {
|
||||
if (fs.existsSync(candidate) && fs.statSync(candidate).isDirectory()) {
|
||||
return candidate;
|
||||
}
|
||||
} catch {
|
||||
// ignore errors and keep walking up
|
||||
}
|
||||
const parent = path.dirname(current);
|
||||
if (parent === current) break;
|
||||
current = parent;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"declaration": true,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"skipLibCheck": true
|
||||
|
||||
Reference in New Issue
Block a user