@lumiflora/fsdk 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +150 -0
- package/dist/commands/add-component.d.ts +7 -0
- package/dist/commands/add-component.d.ts.map +1 -0
- package/dist/commands/add-component.js +93 -0
- package/dist/commands/add-page.d.ts +8 -0
- package/dist/commands/add-page.d.ts.map +1 -0
- package/dist/commands/add-page.js +98 -0
- package/dist/commands/add-store.d.ts +6 -0
- package/dist/commands/add-store.d.ts.map +1 -0
- package/dist/commands/add-store.js +204 -0
- package/dist/commands/completion.d.ts +8 -0
- package/dist/commands/completion.d.ts.map +1 -0
- package/dist/commands/completion.js +271 -0
- package/dist/commands/create-app.d.ts +10 -0
- package/dist/commands/create-app.d.ts.map +1 -0
- package/dist/commands/create-app.js +174 -0
- package/dist/commands/index.d.ts +9 -0
- package/dist/commands/index.d.ts.map +1 -0
- package/dist/commands/index.js +8 -0
- package/dist/commands/preview.d.ts +8 -0
- package/dist/commands/preview.d.ts.map +1 -0
- package/dist/commands/preview.js +162 -0
- package/dist/commands/sync-template.d.ts +6 -0
- package/dist/commands/sync-template.d.ts.map +1 -0
- package/dist/commands/sync-template.js +94 -0
- package/dist/commands/validate.d.ts +7 -0
- package/dist/commands/validate.d.ts.map +1 -0
- package/dist/commands/validate.js +136 -0
- package/dist/completion/completion-scripts.d.ts +4 -0
- package/dist/completion/completion-scripts.d.ts.map +1 -0
- package/dist/completion/completion-scripts.js +193 -0
- package/dist/completion/index.d.ts +2 -0
- package/dist/completion/index.d.ts.map +1 -0
- package/dist/completion/index.js +1 -0
- package/dist/core/config-loader.d.ts +91 -0
- package/dist/core/config-loader.d.ts.map +1 -0
- package/dist/core/config-loader.js +118 -0
- package/dist/core/hot-reload.d.ts +24 -0
- package/dist/core/hot-reload.d.ts.map +1 -0
- package/dist/core/hot-reload.js +97 -0
- package/dist/core/index.d.ts +5 -0
- package/dist/core/index.d.ts.map +1 -0
- package/dist/core/index.js +4 -0
- package/dist/core/plugin-system.d.ts +32 -0
- package/dist/core/plugin-system.d.ts.map +1 -0
- package/dist/core/plugin-system.js +69 -0
- package/dist/core/template-engine.d.ts +22 -0
- package/dist/core/template-engine.d.ts.map +1 -0
- package/dist/core/template-engine.js +89 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +214 -0
- package/dist/plugins/add-component-plugin.d.ts +4 -0
- package/dist/plugins/add-component-plugin.d.ts.map +1 -0
- package/dist/plugins/add-component-plugin.js +23 -0
- package/dist/plugins/add-page-plugin.d.ts +4 -0
- package/dist/plugins/add-page-plugin.d.ts.map +1 -0
- package/dist/plugins/add-page-plugin.js +23 -0
- package/dist/plugins/add-store-plugin.d.ts +4 -0
- package/dist/plugins/add-store-plugin.d.ts.map +1 -0
- package/dist/plugins/add-store-plugin.js +23 -0
- package/dist/plugins/core-plugin.d.ts +4 -0
- package/dist/plugins/core-plugin.d.ts.map +1 -0
- package/dist/plugins/core-plugin.js +22 -0
- package/dist/plugins/index.d.ts +5 -0
- package/dist/plugins/index.d.ts.map +1 -0
- package/dist/plugins/index.js +4 -0
- package/dist/utils/command-helpers.d.ts +15 -0
- package/dist/utils/command-helpers.d.ts.map +1 -0
- package/dist/utils/command-helpers.js +40 -0
- package/dist/utils/index.d.ts +5 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +4 -0
- package/dist/utils/logger.d.ts +19 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +32 -0
- package/dist/utils/path.d.ts +9 -0
- package/dist/utils/path.d.ts.map +1 -0
- package/dist/utils/path.js +66 -0
- package/dist/utils/spinner.d.ts +23 -0
- package/dist/utils/spinner.d.ts.map +1 -0
- package/dist/utils/spinner.js +61 -0
- package/package.json +37 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import fg from 'fast-glob';
|
|
4
|
+
import { logger } from '../utils/index.js';
|
|
5
|
+
import { templateEngine } from '../core/index.js';
|
|
6
|
+
export async function syncTemplate(cwd, options = {}) {
|
|
7
|
+
try {
|
|
8
|
+
const template = options.template || 'base';
|
|
9
|
+
logger.info(`Syncing template ${template}...`);
|
|
10
|
+
const templatePath = path.resolve(cwd, '.fsdk', 'template');
|
|
11
|
+
const currentTemplatePath = path.resolve(templatePath, template);
|
|
12
|
+
if (!fs.existsSync(currentTemplatePath)) {
|
|
13
|
+
logger.warning(`Template ${template} not found in .fsdk/template`);
|
|
14
|
+
logger.info('Run "fsdk create" first to initialize a template');
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
const srcDir = path.resolve(cwd, 'src');
|
|
18
|
+
if (!fs.existsSync(srcDir)) {
|
|
19
|
+
logger.error('src directory does not exist. Run "fsdk create" first.');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
const { modifiedFiles, addedFiles, removedFiles } = await compareTemplates(currentTemplatePath, srcDir);
|
|
23
|
+
if (modifiedFiles.length === 0 && addedFiles.length === 0 && removedFiles.length === 0) {
|
|
24
|
+
logger.success('Template is already up to date');
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
if (options.force) {
|
|
28
|
+
await applyTemplateSync(currentTemplatePath, srcDir, { modifiedFiles, addedFiles, removedFiles });
|
|
29
|
+
}
|
|
30
|
+
else {
|
|
31
|
+
await interactiveSync(currentTemplatePath, srcDir, { modifiedFiles, addedFiles, removedFiles });
|
|
32
|
+
}
|
|
33
|
+
templateEngine.clearCache();
|
|
34
|
+
logger.success('Template sync completed');
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
logger.error('Failed to sync template:', error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
async function compareTemplates(templateDir, srcDir) {
|
|
42
|
+
const templateFiles = await fg.glob('**/*', { cwd: templateDir, dot: true, onlyFiles: true });
|
|
43
|
+
const srcFiles = await fg.glob('**/*', { cwd: srcDir, dot: true, onlyFiles: true });
|
|
44
|
+
const templateSet = new Set(templateFiles);
|
|
45
|
+
const srcSet = new Set(srcFiles);
|
|
46
|
+
const modifiedFiles = [];
|
|
47
|
+
const addedFiles = [];
|
|
48
|
+
const removedFiles = [];
|
|
49
|
+
for (const file of srcFiles) {
|
|
50
|
+
if (templateSet.has(file)) {
|
|
51
|
+
const templateContent = await fs.readFile(path.resolve(templateDir, file), 'utf-8');
|
|
52
|
+
const srcContent = await fs.readFile(path.resolve(srcDir, file), 'utf-8');
|
|
53
|
+
if (templateContent !== srcContent) {
|
|
54
|
+
modifiedFiles.push(file);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
addedFiles.push(file);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
for (const file of templateFiles) {
|
|
62
|
+
if (!srcSet.has(file)) {
|
|
63
|
+
removedFiles.push(file);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return { modifiedFiles, addedFiles, removedFiles };
|
|
67
|
+
}
|
|
68
|
+
async function applyTemplateSync(templateDir, srcDir, changes) {
|
|
69
|
+
const { modifiedFiles, addedFiles, removedFiles } = changes;
|
|
70
|
+
for (const file of removedFiles) {
|
|
71
|
+
const filePath = path.resolve(srcDir, file);
|
|
72
|
+
await fs.remove(filePath);
|
|
73
|
+
logger.debug(`Removed: ${file}`);
|
|
74
|
+
}
|
|
75
|
+
for (const file of [...modifiedFiles, ...addedFiles]) {
|
|
76
|
+
await fs.copy(path.resolve(templateDir, file), path.resolve(srcDir, file));
|
|
77
|
+
logger.debug(`Copied: ${file}`);
|
|
78
|
+
}
|
|
79
|
+
logger.info(`Synced: ${modifiedFiles.length} modified, ${addedFiles.length} added, ${removedFiles.length} removed`);
|
|
80
|
+
}
|
|
81
|
+
async function interactiveSync(templateDir, srcDir, changes) {
|
|
82
|
+
const { modifiedFiles, addedFiles, removedFiles } = changes;
|
|
83
|
+
logger.info('Changes detected:');
|
|
84
|
+
if (modifiedFiles.length > 0) {
|
|
85
|
+
logger.info(` Modified: ${modifiedFiles.length} files`);
|
|
86
|
+
}
|
|
87
|
+
if (addedFiles.length > 0) {
|
|
88
|
+
logger.info(` Added: ${addedFiles.length} files`);
|
|
89
|
+
}
|
|
90
|
+
if (removedFiles.length > 0) {
|
|
91
|
+
logger.info(` Removed: ${removedFiles.length} files`);
|
|
92
|
+
}
|
|
93
|
+
logger.warning('Use --force to apply all changes without confirmation');
|
|
94
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"validate.d.ts","sourceRoot":"","sources":["../../src/commands/validate.ts"],"names":[],"mappings":"AAOA,MAAM,WAAW,eAAe;IAC9B,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,MAAM,CAAC,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,eAAoB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6BxF"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import fg from 'fast-glob';
|
|
5
|
+
import { logger } from '../utils/index.js';
|
|
6
|
+
import { FsdkConfigSchema } from '../core/index.js';
|
|
7
|
+
export async function validate(cwd, options = {}) {
|
|
8
|
+
const errors = [];
|
|
9
|
+
const warnings = [];
|
|
10
|
+
try {
|
|
11
|
+
if (options.config || (!options.config && !options.templates)) {
|
|
12
|
+
await validateConfig(cwd, errors, warnings);
|
|
13
|
+
}
|
|
14
|
+
if (options.templates || (!options.config && !options.templates)) {
|
|
15
|
+
await validateTemplates(cwd, errors, warnings);
|
|
16
|
+
}
|
|
17
|
+
if (errors.length > 0) {
|
|
18
|
+
logger.error('Validation failed with errors:');
|
|
19
|
+
errors.forEach((e) => logger.error(` - ${e}`));
|
|
20
|
+
process.exit(1);
|
|
21
|
+
}
|
|
22
|
+
if (warnings.length > 0) {
|
|
23
|
+
logger.warning('Validation passed with warnings:');
|
|
24
|
+
warnings.forEach((w) => logger.warning(` - ${w}`));
|
|
25
|
+
}
|
|
26
|
+
else {
|
|
27
|
+
logger.success('All validations passed!');
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
catch (error) {
|
|
31
|
+
logger.error('Validation error:', error);
|
|
32
|
+
throw error;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async function validateConfig(cwd, errors, warnings) {
|
|
36
|
+
logger.info('Validating configuration...');
|
|
37
|
+
const configFiles = [
|
|
38
|
+
'.fsdkrc.ts',
|
|
39
|
+
'.fsdkrc.js',
|
|
40
|
+
'.fsdkrc.json',
|
|
41
|
+
'.fsdkrc',
|
|
42
|
+
'fsdk.config.ts',
|
|
43
|
+
'fsdk.config.js',
|
|
44
|
+
'fsdk.config.json',
|
|
45
|
+
];
|
|
46
|
+
const foundConfig = configFiles.find((f) => fs.existsSync(path.resolve(cwd, f)));
|
|
47
|
+
if (!foundConfig) {
|
|
48
|
+
warnings.push('No .fsdkrc configuration file found, using defaults');
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
try {
|
|
52
|
+
const configPath = path.resolve(cwd, foundConfig);
|
|
53
|
+
const ext = path.extname(foundConfig).toLowerCase();
|
|
54
|
+
let config;
|
|
55
|
+
if (ext === '.ts' || ext === '.js') {
|
|
56
|
+
const module = await import(configPath);
|
|
57
|
+
config = module.default || module;
|
|
58
|
+
}
|
|
59
|
+
else {
|
|
60
|
+
const content = await fs.readFile(configPath, 'utf-8');
|
|
61
|
+
config = JSON.parse(content);
|
|
62
|
+
}
|
|
63
|
+
const result = FsdkConfigSchema.safeParse(config);
|
|
64
|
+
if (!result.success) {
|
|
65
|
+
result.error.errors.forEach((e) => {
|
|
66
|
+
errors.push(`Config validation failed: ${e.path.join('.')} - ${e.message}`);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
logger.success(`Config file ${foundConfig} is valid`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
if (error instanceof z.ZodError) {
|
|
75
|
+
error.errors.forEach((e) => {
|
|
76
|
+
errors.push(`Config validation failed: ${e.path.join('.')} - ${e.message}`);
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
errors.push(`Failed to parse config file: ${error}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
async function validateTemplates(cwd, errors, warnings) {
|
|
85
|
+
logger.info('Validating templates...');
|
|
86
|
+
const templateDir = path.resolve(cwd, '.fsdk', 'template');
|
|
87
|
+
if (!fs.existsSync(templateDir)) {
|
|
88
|
+
warnings.push('No template directory found');
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
const templateFiles = await fg.glob('**/*', { cwd: templateDir, dot: true, onlyFiles: true });
|
|
92
|
+
if (templateFiles.length === 0) {
|
|
93
|
+
warnings.push('Template directory is empty');
|
|
94
|
+
return;
|
|
95
|
+
}
|
|
96
|
+
const vueFiles = templateFiles.filter((f) => String(f).endsWith('.vue'));
|
|
97
|
+
const tsFiles = templateFiles.filter((f) => String(f).endsWith('.ts'));
|
|
98
|
+
const lessFiles = templateFiles.filter((f) => String(f).endsWith('.less'));
|
|
99
|
+
logger.debug(`Found ${vueFiles.length} Vue files, ${tsFiles.length} TS files, ${lessFiles.length} Less files`);
|
|
100
|
+
let valid = true;
|
|
101
|
+
for (const vueFile of vueFiles) {
|
|
102
|
+
const content = await fs.readFile(path.resolve(templateDir, vueFile), 'utf-8');
|
|
103
|
+
if (!validateVueFile(content)) {
|
|
104
|
+
errors.push(`Invalid Vue file: ${vueFile}`);
|
|
105
|
+
valid = false;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
for (const tsFile of tsFiles) {
|
|
109
|
+
const content = await fs.readFile(path.resolve(templateDir, tsFile), 'utf-8');
|
|
110
|
+
if (!validateTsFile(content)) {
|
|
111
|
+
errors.push(`Invalid TypeScript file: ${tsFile}`);
|
|
112
|
+
valid = false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
if (valid) {
|
|
116
|
+
logger.success(`Template validation passed (${templateFiles.length} files)`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
function validateVueFile(content) {
|
|
120
|
+
const hasTemplate = content.includes('<template>');
|
|
121
|
+
const hasScript = content.includes('<script');
|
|
122
|
+
return hasTemplate || hasScript;
|
|
123
|
+
}
|
|
124
|
+
function validateTsFile(content) {
|
|
125
|
+
const lines = content.split('\n');
|
|
126
|
+
for (const line of lines) {
|
|
127
|
+
const trimmed = line.trim();
|
|
128
|
+
if (trimmed.startsWith('//') || trimmed.startsWith('/*') || trimmed.startsWith('*')) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
if (trimmed.includes(':') && !trimmed.match(/^\s*\/\//)) {
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return content.includes('export') || content.includes('import');
|
|
136
|
+
}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export declare const BASH_COMPLETION = "#!/bin/bash\n# fsdk bash completion\n\n_fsdk_completion() {\n local cur prev opts\n COMPREPLY=()\n cur=\"${COMP_WORDS[COMP_CWORD]}\"\n prev=\"${COMP_WORDS[COMP_CWORD-1]}\"\n\n opts=\"create add-page add-component add-store sync-template validate preview completion\"\n\n case \"${prev}\" in\n create)\n opts=\"--template --package-manager --eslint --no-git --no-install\"\n ;;\n add-page)\n opts=\"--router-path --page-name\"\n ;;\n add-component)\n opts=\"--type --name --dir\"\n ;;\n add-store)\n opts=\"--type --name\"\n ;;\n sync-template)\n opts=\"--template --force\"\n ;;\n validate)\n opts=\"--config --templates --strict\"\n ;;\n preview)\n opts=\"--port --host --open --template\"\n ;;\n completion)\n opts=\"bash zsh fish\"\n ;;\n esac\n\n COMPREPLY=($(compgen -W \"${opts}\" -- \"${cur}\"))\n return 0\n}\n\ncomplete -F _fsdk_completion fsdk\n";
|
|
2
|
+
export declare const FISH_COMPLETION = "# fsdk fish completion\n\nfunction __fsdk_commands\n echo \"create\tCreate a new application\"\n echo \"add-page\t\tAdd a new page\"\n echo \"add-component\tAdd a new component\"\n echo \"add-store\tAdd a new store\"\n echo \"sync-template\tSync template files\"\n echo \"validate\t\tValidate configuration and templates\"\n echo \"preview\t\tPreview template\"\n echo \"completion\tGenerate shell completion script\"\nend\n\nfunction __fsdk_create_app_opts\n echo \"--template\tTemplate name (base|full)\"\n echo \"--package-manager\tPackage manager (npm|pnpm|yarn|bun)\"\n echo \"--eslint\tEnable ESLint\"\n echo \"--no-git\tSkip git initialization\"\n echo \"--no-install\tSkip dependency installation\"\nend\n\nfunction __fsdk_add_page_opts\n echo \"--router-path\tRouter path\"\n echo \"--page-name\tPage name\"\nend\n\nfunction __fsdk_add_component_opts\n echo \"--type\tComponent type (page|common|business)\"\n echo \"--name\tComponent name\"\n echo \"--dir\tSubdirectory\"\nend\n\nfunction __fsdk_add_store_opts\n echo \"--type\tStore type (pinia|redux)\"\n echo \"--name\tStore name\"\nend\n\nfunction __fsdk_sync_template_opts\n echo \"--template\tTemplate name\"\n echo \"--force\tForce sync\"\nend\n\nfunction __fsdk_validate_opts\n echo \"--config\tValidate config only\"\n echo \"--templates\tValidate templates only\"\n echo \"--strict\tStrict validation\"\nend\n\nfunction __fsdk_preview_opts\n echo \"--port\tPort number\"\n echo \"--host\tHost address\"\n echo \"--open\tOpen browser\"\n echo \"--template\tTemplate name\"\nend\n\nfunction __fsdk_completion_opts\n echo \"bash\tGenerate bash completion\"\n echo \"zsh\tGenerate zsh completion\"\n echo \"fish\tGenerate fish completion\"\nend\n\ncomplete -c fsdk -f -a \"(__fsdk_commands)\"\n\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from create\" -a \"(__fsdk_create_app_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from add-page\" -a \"(__fsdk_add_page_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from add-component\" -a \"(__fsdk_add_component_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from add-store\" -a \"(__fsdk_add_store_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from sync-template\" -a \"(__fsdk_sync_template_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from validate\" -a \"(__fsdk_validate_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from preview\" -a \"(__fsdk_preview_opts)\" --option\ncomplete -c fsdk -n \"not __fish_seen_subcommand_from completion\" -a \"(__fsdk_completion_opts)\" --option\n";
|
|
3
|
+
export declare const ZSH_COMPLETION = "#compdef fsdk\n\nlocal -a commands\ncommands=(\n 'create:Create a new application'\n 'add-page:Add a new page'\n 'add-component:Add a new component'\n 'add-store:Add a new store'\n 'sync-template:Sync template files'\n 'validate:Validate configuration and templates'\n 'preview:Preview template'\n 'completion:Generate shell completion script'\n)\n\n_arguments -C \\\n '1: :->command' \\\n '2: :->args' \\\n '*: :->rest'\n\ncase \"$state\" in\n command)\n _describe 'command' commands\n ;;\n args)\n case $words[1] in\n create)\n _arguments -s \\\n '--template[Template name]' \\\n '--package-manager[Package manager: npm|pnpm|yarn|bun]' \\\n '--eslint[Enable ESLint]' \\\n '--no-git[Skip git initialization]' \\\n '--no-install[Skip dependency installation]'\n ;;\n add-page)\n _arguments -s \\\n '--router-path[Router path]' \\\n '--page-name[Page name]'\n ;;\n add-component)\n _arguments -s \\\n '--type[Component type: page|common|business]' \\\n '--name[Component name]' \\\n '--dir[Subdirectory]'\n ;;\n add-store)\n _arguments -s \\\n '--type[Store type: pinia|redux]' \\\n '--name[Store name]'\n ;;\n sync-template)\n _arguments -s \\\n '--template[Template name]' \\\n '--force[Force sync]'\n ;;\n validate)\n _arguments -s \\\n '--config[Validate config only]' \\\n '--templates[Validate templates only]' \\\n '--strict[Strict validation]'\n ;;\n preview)\n _arguments -s \\\n '--port[Port number]' \\\n '--host[Host address]' \\\n '--open[Open browser]' \\\n '--template[Template name]'\n ;;\n completion)\n _arguments -s \\\n 'bash:Generate bash completion' \\\n 'zsh:Generate zsh completion' \\\n 'fish:Generate fish completion'\n ;;\n esac\n ;;\nesac\n";
|
|
4
|
+
//# sourceMappingURL=completion-scripts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"completion-scripts.d.ts","sourceRoot":"","sources":["../../src/completion/completion-scripts.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,eAAe,68BA2C3B,CAAC;AAEF,eAAO,MAAM,eAAe,umFAuE3B,CAAC;AAEF,eAAO,MAAM,cAAc,ohEA4E1B,CAAC"}
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
export const BASH_COMPLETION = `#!/bin/bash
|
|
2
|
+
# fsdk bash completion
|
|
3
|
+
|
|
4
|
+
_fsdk_completion() {
|
|
5
|
+
local cur prev opts
|
|
6
|
+
COMPREPLY=()
|
|
7
|
+
cur="\${COMP_WORDS[COMP_CWORD]}"
|
|
8
|
+
prev="\${COMP_WORDS[COMP_CWORD-1]}"
|
|
9
|
+
|
|
10
|
+
opts="create add-page add-component add-store sync-template validate preview completion"
|
|
11
|
+
|
|
12
|
+
case "\${prev}" in
|
|
13
|
+
create)
|
|
14
|
+
opts="--template --package-manager --eslint --no-git --no-install"
|
|
15
|
+
;;
|
|
16
|
+
add-page)
|
|
17
|
+
opts="--router-path --page-name"
|
|
18
|
+
;;
|
|
19
|
+
add-component)
|
|
20
|
+
opts="--type --name --dir"
|
|
21
|
+
;;
|
|
22
|
+
add-store)
|
|
23
|
+
opts="--type --name"
|
|
24
|
+
;;
|
|
25
|
+
sync-template)
|
|
26
|
+
opts="--template --force"
|
|
27
|
+
;;
|
|
28
|
+
validate)
|
|
29
|
+
opts="--config --templates --strict"
|
|
30
|
+
;;
|
|
31
|
+
preview)
|
|
32
|
+
opts="--port --host --open --template"
|
|
33
|
+
;;
|
|
34
|
+
completion)
|
|
35
|
+
opts="bash zsh fish"
|
|
36
|
+
;;
|
|
37
|
+
esac
|
|
38
|
+
|
|
39
|
+
COMPREPLY=($(compgen -W "\${opts}" -- "\${cur}"))
|
|
40
|
+
return 0
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
complete -F _fsdk_completion fsdk
|
|
44
|
+
`;
|
|
45
|
+
export const FISH_COMPLETION = `# fsdk fish completion
|
|
46
|
+
|
|
47
|
+
function __fsdk_commands
|
|
48
|
+
echo "create\tCreate a new application"
|
|
49
|
+
echo "add-page\t\tAdd a new page"
|
|
50
|
+
echo "add-component\tAdd a new component"
|
|
51
|
+
echo "add-store\tAdd a new store"
|
|
52
|
+
echo "sync-template\tSync template files"
|
|
53
|
+
echo "validate\t\tValidate configuration and templates"
|
|
54
|
+
echo "preview\t\tPreview template"
|
|
55
|
+
echo "completion\tGenerate shell completion script"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
function __fsdk_create_app_opts
|
|
59
|
+
echo "--template\tTemplate name (base|full)"
|
|
60
|
+
echo "--package-manager\tPackage manager (npm|pnpm|yarn|bun)"
|
|
61
|
+
echo "--eslint\tEnable ESLint"
|
|
62
|
+
echo "--no-git\tSkip git initialization"
|
|
63
|
+
echo "--no-install\tSkip dependency installation"
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
function __fsdk_add_page_opts
|
|
67
|
+
echo "--router-path\tRouter path"
|
|
68
|
+
echo "--page-name\tPage name"
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
function __fsdk_add_component_opts
|
|
72
|
+
echo "--type\tComponent type (page|common|business)"
|
|
73
|
+
echo "--name\tComponent name"
|
|
74
|
+
echo "--dir\tSubdirectory"
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
function __fsdk_add_store_opts
|
|
78
|
+
echo "--type\tStore type (pinia|redux)"
|
|
79
|
+
echo "--name\tStore name"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
function __fsdk_sync_template_opts
|
|
83
|
+
echo "--template\tTemplate name"
|
|
84
|
+
echo "--force\tForce sync"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
function __fsdk_validate_opts
|
|
88
|
+
echo "--config\tValidate config only"
|
|
89
|
+
echo "--templates\tValidate templates only"
|
|
90
|
+
echo "--strict\tStrict validation"
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
function __fsdk_preview_opts
|
|
94
|
+
echo "--port\tPort number"
|
|
95
|
+
echo "--host\tHost address"
|
|
96
|
+
echo "--open\tOpen browser"
|
|
97
|
+
echo "--template\tTemplate name"
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
function __fsdk_completion_opts
|
|
101
|
+
echo "bash\tGenerate bash completion"
|
|
102
|
+
echo "zsh\tGenerate zsh completion"
|
|
103
|
+
echo "fish\tGenerate fish completion"
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
complete -c fsdk -f -a "(__fsdk_commands)"
|
|
107
|
+
|
|
108
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from create" -a "(__fsdk_create_app_opts)" --option
|
|
109
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from add-page" -a "(__fsdk_add_page_opts)" --option
|
|
110
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from add-component" -a "(__fsdk_add_component_opts)" --option
|
|
111
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from add-store" -a "(__fsdk_add_store_opts)" --option
|
|
112
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from sync-template" -a "(__fsdk_sync_template_opts)" --option
|
|
113
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from validate" -a "(__fsdk_validate_opts)" --option
|
|
114
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from preview" -a "(__fsdk_preview_opts)" --option
|
|
115
|
+
complete -c fsdk -n "not __fish_seen_subcommand_from completion" -a "(__fsdk_completion_opts)" --option
|
|
116
|
+
`;
|
|
117
|
+
export const ZSH_COMPLETION = `#compdef fsdk
|
|
118
|
+
|
|
119
|
+
local -a commands
|
|
120
|
+
commands=(
|
|
121
|
+
'create:Create a new application'
|
|
122
|
+
'add-page:Add a new page'
|
|
123
|
+
'add-component:Add a new component'
|
|
124
|
+
'add-store:Add a new store'
|
|
125
|
+
'sync-template:Sync template files'
|
|
126
|
+
'validate:Validate configuration and templates'
|
|
127
|
+
'preview:Preview template'
|
|
128
|
+
'completion:Generate shell completion script'
|
|
129
|
+
)
|
|
130
|
+
|
|
131
|
+
_arguments -C \\
|
|
132
|
+
'1: :->command' \\
|
|
133
|
+
'2: :->args' \\
|
|
134
|
+
'*: :->rest'
|
|
135
|
+
|
|
136
|
+
case "$state" in
|
|
137
|
+
command)
|
|
138
|
+
_describe 'command' commands
|
|
139
|
+
;;
|
|
140
|
+
args)
|
|
141
|
+
case $words[1] in
|
|
142
|
+
create)
|
|
143
|
+
_arguments -s \\
|
|
144
|
+
'--template[Template name]' \\
|
|
145
|
+
'--package-manager[Package manager: npm|pnpm|yarn|bun]' \\
|
|
146
|
+
'--eslint[Enable ESLint]' \\
|
|
147
|
+
'--no-git[Skip git initialization]' \\
|
|
148
|
+
'--no-install[Skip dependency installation]'
|
|
149
|
+
;;
|
|
150
|
+
add-page)
|
|
151
|
+
_arguments -s \\
|
|
152
|
+
'--router-path[Router path]' \\
|
|
153
|
+
'--page-name[Page name]'
|
|
154
|
+
;;
|
|
155
|
+
add-component)
|
|
156
|
+
_arguments -s \\
|
|
157
|
+
'--type[Component type: page|common|business]' \\
|
|
158
|
+
'--name[Component name]' \\
|
|
159
|
+
'--dir[Subdirectory]'
|
|
160
|
+
;;
|
|
161
|
+
add-store)
|
|
162
|
+
_arguments -s \\
|
|
163
|
+
'--type[Store type: pinia|redux]' \\
|
|
164
|
+
'--name[Store name]'
|
|
165
|
+
;;
|
|
166
|
+
sync-template)
|
|
167
|
+
_arguments -s \\
|
|
168
|
+
'--template[Template name]' \\
|
|
169
|
+
'--force[Force sync]'
|
|
170
|
+
;;
|
|
171
|
+
validate)
|
|
172
|
+
_arguments -s \\
|
|
173
|
+
'--config[Validate config only]' \\
|
|
174
|
+
'--templates[Validate templates only]' \\
|
|
175
|
+
'--strict[Strict validation]'
|
|
176
|
+
;;
|
|
177
|
+
preview)
|
|
178
|
+
_arguments -s \\
|
|
179
|
+
'--port[Port number]' \\
|
|
180
|
+
'--host[Host address]' \\
|
|
181
|
+
'--open[Open browser]' \\
|
|
182
|
+
'--template[Template name]'
|
|
183
|
+
;;
|
|
184
|
+
completion)
|
|
185
|
+
_arguments -s \\
|
|
186
|
+
'bash:Generate bash completion' \\
|
|
187
|
+
'zsh:Generate zsh completion' \\
|
|
188
|
+
'fish:Generate fish completion'
|
|
189
|
+
;;
|
|
190
|
+
esac
|
|
191
|
+
;;
|
|
192
|
+
esac
|
|
193
|
+
`;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/completion/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { BASH_COMPLETION, ZSH_COMPLETION, FISH_COMPLETION } from './completion-scripts.js';
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const FsdkConfigSchema: z.ZodObject<{
|
|
3
|
+
template: z.ZodOptional<z.ZodString>;
|
|
4
|
+
packageManager: z.ZodOptional<z.ZodEnum<["npm", "pnpm", "yarn", "bun"]>>;
|
|
5
|
+
eslint: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
6
|
+
git: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
7
|
+
install: z.ZodDefault<z.ZodOptional<z.ZodBoolean>>;
|
|
8
|
+
router: z.ZodOptional<z.ZodObject<{
|
|
9
|
+
type: z.ZodDefault<z.ZodOptional<z.ZodEnum<["hash", "history"]>>>;
|
|
10
|
+
base: z.ZodOptional<z.ZodString>;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
type: "hash" | "history";
|
|
13
|
+
base?: string | undefined;
|
|
14
|
+
}, {
|
|
15
|
+
type?: "hash" | "history" | undefined;
|
|
16
|
+
base?: string | undefined;
|
|
17
|
+
}>>;
|
|
18
|
+
store: z.ZodOptional<z.ZodObject<{
|
|
19
|
+
type: z.ZodDefault<z.ZodOptional<z.ZodEnum<["pinia", "redux"]>>>;
|
|
20
|
+
}, "strip", z.ZodTypeAny, {
|
|
21
|
+
type: "pinia" | "redux";
|
|
22
|
+
}, {
|
|
23
|
+
type?: "pinia" | "redux" | undefined;
|
|
24
|
+
}>>;
|
|
25
|
+
aliases: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
|
|
26
|
+
transforms: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
27
|
+
name: z.ZodString;
|
|
28
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
29
|
+
}, "strip", z.ZodTypeAny, {
|
|
30
|
+
name: string;
|
|
31
|
+
options?: Record<string, unknown> | undefined;
|
|
32
|
+
}, {
|
|
33
|
+
name: string;
|
|
34
|
+
options?: Record<string, unknown> | undefined;
|
|
35
|
+
}>, "many">>;
|
|
36
|
+
}, "strip", z.ZodTypeAny, {
|
|
37
|
+
eslint: boolean;
|
|
38
|
+
git: boolean;
|
|
39
|
+
install: boolean;
|
|
40
|
+
template?: string | undefined;
|
|
41
|
+
packageManager?: "npm" | "pnpm" | "yarn" | "bun" | undefined;
|
|
42
|
+
router?: {
|
|
43
|
+
type: "hash" | "history";
|
|
44
|
+
base?: string | undefined;
|
|
45
|
+
} | undefined;
|
|
46
|
+
store?: {
|
|
47
|
+
type: "pinia" | "redux";
|
|
48
|
+
} | undefined;
|
|
49
|
+
aliases?: Record<string, string> | undefined;
|
|
50
|
+
transforms?: {
|
|
51
|
+
name: string;
|
|
52
|
+
options?: Record<string, unknown> | undefined;
|
|
53
|
+
}[] | undefined;
|
|
54
|
+
}, {
|
|
55
|
+
template?: string | undefined;
|
|
56
|
+
packageManager?: "npm" | "pnpm" | "yarn" | "bun" | undefined;
|
|
57
|
+
eslint?: boolean | undefined;
|
|
58
|
+
git?: boolean | undefined;
|
|
59
|
+
install?: boolean | undefined;
|
|
60
|
+
router?: {
|
|
61
|
+
type?: "hash" | "history" | undefined;
|
|
62
|
+
base?: string | undefined;
|
|
63
|
+
} | undefined;
|
|
64
|
+
store?: {
|
|
65
|
+
type?: "pinia" | "redux" | undefined;
|
|
66
|
+
} | undefined;
|
|
67
|
+
aliases?: Record<string, string> | undefined;
|
|
68
|
+
transforms?: {
|
|
69
|
+
name: string;
|
|
70
|
+
options?: Record<string, unknown> | undefined;
|
|
71
|
+
}[] | undefined;
|
|
72
|
+
}>;
|
|
73
|
+
export type FsdkConfig = z.infer<typeof FsdkConfigSchema>;
|
|
74
|
+
export interface PluginContext {
|
|
75
|
+
cwd: string;
|
|
76
|
+
config: FsdkConfig;
|
|
77
|
+
templatesDir: string;
|
|
78
|
+
pluginsDir: string;
|
|
79
|
+
}
|
|
80
|
+
export declare class ConfigLoader {
|
|
81
|
+
private configCache;
|
|
82
|
+
loadConfig(cwd?: string): Promise<FsdkConfig>;
|
|
83
|
+
private findConfigFile;
|
|
84
|
+
private parseConfigFile;
|
|
85
|
+
private getDefaultConfig;
|
|
86
|
+
clearCache(cwd?: string): void;
|
|
87
|
+
getDefault(): FsdkConfig;
|
|
88
|
+
createPluginContext(cwd: string, templatesDir: string, pluginsDir: string): PluginContext;
|
|
89
|
+
}
|
|
90
|
+
export declare const configLoader: ConfigLoader;
|
|
91
|
+
//# sourceMappingURL=config-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-loader.d.ts","sourceRoot":"","sources":["../../src/core/config-loader.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAKxB,eAAO,MAAM,gBAAgB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAkB3B,CAAC;AAEH,MAAM,MAAM,UAAU,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC;AAE1D,MAAM,WAAW,aAAa;IAC5B,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,UAAU,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,qBAAa,YAAY;IACvB,OAAO,CAAC,WAAW,CAAsC;IAEnD,UAAU,CAAC,GAAG,GAAE,MAAsB,GAAG,OAAO,CAAC,UAAU,CAAC;IA2BlE,OAAO,CAAC,cAAc;YAqBR,eAAe;IAiB7B,OAAO,CAAC,gBAAgB;IAYxB,UAAU,CAAC,GAAG,CAAC,EAAE,MAAM,GAAG,IAAI;IAS9B,UAAU,IAAI,UAAU;IAIxB,mBAAmB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,aAAa;CAQ1F;AAED,eAAO,MAAM,YAAY,cAAqB,CAAC"}
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
import fs from 'fs-extra';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { z } from 'zod';
|
|
4
|
+
import json5 from 'json5';
|
|
5
|
+
import { logger } from '../utils/index.js';
|
|
6
|
+
import { normalizePath } from '../utils/path.js';
|
|
7
|
+
export const FsdkConfigSchema = z.object({
|
|
8
|
+
template: z.string().optional(),
|
|
9
|
+
packageManager: z.enum(['npm', 'pnpm', 'yarn', 'bun']).optional(),
|
|
10
|
+
eslint: z.boolean().optional().default(true),
|
|
11
|
+
git: z.boolean().optional().default(true),
|
|
12
|
+
install: z.boolean().optional().default(true),
|
|
13
|
+
router: z.object({
|
|
14
|
+
type: z.enum(['hash', 'history']).optional().default('hash'),
|
|
15
|
+
base: z.string().optional(),
|
|
16
|
+
}).optional(),
|
|
17
|
+
store: z.object({
|
|
18
|
+
type: z.enum(['pinia', 'redux']).optional().default('pinia'),
|
|
19
|
+
}).optional(),
|
|
20
|
+
aliases: z.record(z.string()).optional(),
|
|
21
|
+
transforms: z.array(z.object({
|
|
22
|
+
name: z.string(),
|
|
23
|
+
options: z.record(z.unknown()).optional(),
|
|
24
|
+
})).optional(),
|
|
25
|
+
});
|
|
26
|
+
export class ConfigLoader {
|
|
27
|
+
configCache = new Map();
|
|
28
|
+
async loadConfig(cwd = process.cwd()) {
|
|
29
|
+
const cacheKey = normalizePath(cwd);
|
|
30
|
+
if (this.configCache.has(cacheKey)) {
|
|
31
|
+
return this.configCache.get(cacheKey);
|
|
32
|
+
}
|
|
33
|
+
const configPath = this.findConfigFile(cwd);
|
|
34
|
+
if (!configPath) {
|
|
35
|
+
logger.debug('No .fsdkrc.ts found, using defaults');
|
|
36
|
+
return this.getDefaultConfig();
|
|
37
|
+
}
|
|
38
|
+
try {
|
|
39
|
+
const config = await this.parseConfigFile(configPath);
|
|
40
|
+
const validated = FsdkConfigSchema.parse(config);
|
|
41
|
+
this.configCache.set(cacheKey, validated);
|
|
42
|
+
logger.success(`Loaded config from ${path.basename(configPath)}`);
|
|
43
|
+
return validated;
|
|
44
|
+
}
|
|
45
|
+
catch (error) {
|
|
46
|
+
if (error instanceof z.ZodError) {
|
|
47
|
+
logger.error('Config validation failed:', error.errors);
|
|
48
|
+
throw new Error(`Config validation failed: ${error.errors.map((e) => e.message).join(', ')}`);
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
findConfigFile(cwd) {
|
|
54
|
+
const candidates = [
|
|
55
|
+
'.fsdkrc.ts',
|
|
56
|
+
'.fsdkrc.js',
|
|
57
|
+
'.fsdkrc.json',
|
|
58
|
+
'.fsdkrc',
|
|
59
|
+
'fsdk.config.ts',
|
|
60
|
+
'fsdk.config.js',
|
|
61
|
+
'fsdk.config.json',
|
|
62
|
+
];
|
|
63
|
+
for (const candidate of candidates) {
|
|
64
|
+
const configPath = path.resolve(cwd, candidate);
|
|
65
|
+
if (fs.existsSync(configPath)) {
|
|
66
|
+
return configPath;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
async parseConfigFile(configPath) {
|
|
72
|
+
const ext = path.extname(configPath).toLowerCase();
|
|
73
|
+
switch (ext) {
|
|
74
|
+
case '.ts':
|
|
75
|
+
case '.js': {
|
|
76
|
+
const module = await import(configPath);
|
|
77
|
+
return module.default || module;
|
|
78
|
+
}
|
|
79
|
+
case '.json':
|
|
80
|
+
case '':
|
|
81
|
+
return json5.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
82
|
+
default:
|
|
83
|
+
throw new Error(`Unsupported config file format: ${ext}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
getDefaultConfig() {
|
|
87
|
+
return {
|
|
88
|
+
template: 'base',
|
|
89
|
+
packageManager: 'pnpm',
|
|
90
|
+
eslint: true,
|
|
91
|
+
git: true,
|
|
92
|
+
install: true,
|
|
93
|
+
router: { type: 'hash' },
|
|
94
|
+
store: { type: 'pinia' },
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
clearCache(cwd) {
|
|
98
|
+
if (cwd) {
|
|
99
|
+
this.configCache.delete(normalizePath(cwd));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
this.configCache.clear();
|
|
103
|
+
}
|
|
104
|
+
logger.debug('Config cache cleared');
|
|
105
|
+
}
|
|
106
|
+
getDefault() {
|
|
107
|
+
return this.getDefaultConfig();
|
|
108
|
+
}
|
|
109
|
+
createPluginContext(cwd, templatesDir, pluginsDir) {
|
|
110
|
+
return {
|
|
111
|
+
cwd,
|
|
112
|
+
config: this.getDefaultConfig(),
|
|
113
|
+
templatesDir,
|
|
114
|
+
pluginsDir,
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
export const configLoader = new ConfigLoader();
|