create-specment 0.2.9 → 0.3.0

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.
Files changed (133) hide show
  1. package/bin/commands/create.d.ts +0 -1
  2. package/bin/constants/languages.d.ts +0 -1
  3. package/bin/core/interactive-setup.d.ts +0 -1
  4. package/bin/core/interactive-setup.js +17 -10
  5. package/bin/core/interactive-setup.js.map +1 -1
  6. package/bin/core/interactive-setup.test.d.ts +0 -1
  7. package/bin/core/interactive-setup.test.js +7 -7
  8. package/bin/core/interactive-setup.test.js.map +1 -1
  9. package/bin/core/project-generator.d.ts +0 -1
  10. package/bin/core/project-generator.js +5 -8
  11. package/bin/core/project-generator.js.map +1 -1
  12. package/bin/features/index.d.ts +0 -1
  13. package/bin/features/index.js +15 -13
  14. package/bin/features/index.js.map +1 -1
  15. package/bin/generators/docusaurus-config.d.ts +0 -1
  16. package/bin/generators/docusaurus-config.js +211 -264
  17. package/bin/generators/docusaurus-config.js.map +1 -1
  18. package/bin/generators/package-json.d.ts +0 -1
  19. package/bin/generators/package-json.js +45 -91
  20. package/bin/generators/package-json.js.map +1 -1
  21. package/bin/generators/template-files.d.ts +0 -1
  22. package/bin/generators/template-files.js +563 -168
  23. package/bin/generators/template-files.js.map +1 -1
  24. package/bin/index.d.ts +0 -1
  25. package/bin/index.js.map +1 -1
  26. package/bin/templates/index.d.ts +0 -1
  27. package/bin/templates/index.js +36 -24
  28. package/bin/templates/index.js.map +1 -1
  29. package/bin/tests/integration.test.d.ts +0 -1
  30. package/bin/tests/integration.test.js +34 -34
  31. package/bin/tests/integration.test.js.map +1 -1
  32. package/bin/types/index.d.ts +1 -21
  33. package/bin/utils/config-merger.d.ts +0 -1
  34. package/bin/utils/config-merger.js +0 -1
  35. package/bin/utils/config-merger.js.map +1 -1
  36. package/bin/utils/errors.d.ts +0 -1
  37. package/bin/utils/install.d.ts +0 -1
  38. package/bin/utils/install.js +3 -3
  39. package/bin/utils/install.js.map +1 -1
  40. package/bin/utils/message-formatter.d.ts +0 -1
  41. package/bin/utils/template-processor.d.ts +0 -1
  42. package/bin/utils/template-processor.js +2 -3
  43. package/bin/utils/template-processor.js.map +1 -1
  44. package/bin/utils/template-processor.test.d.ts +0 -1
  45. package/bin/utils/template-processor.test.js +22 -22
  46. package/bin/utils/template-processor.test.js.map +1 -1
  47. package/bin/utils/version.d.ts +0 -1
  48. package/bin/utils/version.js +3 -3
  49. package/bin/utils/version.js.map +1 -1
  50. package/package.json +2 -7
  51. package/templates/docs/01-overview/_requirements-specification.mdx +1 -5
  52. package/templates/docs/01-overview/as-is.mdx +1 -1
  53. package/templates/docs/01-overview/glossary.mdx +6 -6
  54. package/templates/docs/01-overview/odsc.mdx +1 -1
  55. package/templates/docs/01-overview/to-be.mdx +6 -6
  56. package/templates/docs/02-requirements/functional/_req-template.mdx +0 -3
  57. package/templates/docs/02-requirements/functional/req-001.mdx +0 -4
  58. package/templates/docs/02-requirements/non-functional/_nfr-template.mdx +0 -3
  59. package/templates/docs/02-requirements/non-functional/nfr-001.mdx +0 -3
  60. package/templates/docs/02-requirements/non-functional/nfr-002.mdx +0 -3
  61. package/templates/docs/03-external/business-model.mdx +1 -1
  62. package/templates/docs/03-external/index.mdx +1 -1
  63. package/templates/docs/04-internal/batches/import-products.mdx +2 -6
  64. package/templates/docs/04-internal/policies/github.mdx +1 -1
  65. package/templates/docs/04-internal/rules/database.mdx +1 -1
  66. package/templates/docs/04-internal/screens/dashboard.mdx +1 -1
  67. package/templates/docs/04-internal/screens/index.mdx +1 -1
  68. package/templates/docs/04-internal/screens/login.mdx +1 -1
  69. package/templates/docs/04-internal/screens/menu.mdx +1 -1
  70. package/templates/docs/index.module.css +96 -0
  71. package/templates/docs/index.tsx +48 -0
  72. package/templates/docs/introduction/index.mdx +1 -1
  73. package/templates/docs/introduction/operational-policies/sharepoint.mdx +1 -1
  74. package/templates/package.json.template +46 -0
  75. package/templates/src/components/Highlight/index.tsx +68 -0
  76. package/templates/src/components/PriorityMatrix/index.tsx +97 -0
  77. package/templates/src/components/TBD/index.tsx +16 -0
  78. package/templates/src/css/custom.css +81 -0
  79. package/templates/src/types/requirements.ts +19 -0
  80. package/templates/static/img/business-model.drawio.svg +4 -0
  81. package/templates/static/img/gantt.drawio.svg +1152 -0
  82. package/templates/static/img/logo.svg +21 -0
  83. package/bin/commands/create.d.ts.map +0 -1
  84. package/bin/constants/languages.d.ts.map +0 -1
  85. package/bin/core/interactive-setup.d.ts.map +0 -1
  86. package/bin/core/interactive-setup.test.d.ts.map +0 -1
  87. package/bin/core/project-generator.d.ts.map +0 -1
  88. package/bin/features/index.d.ts.map +0 -1
  89. package/bin/generators/docusaurus-config.d.ts.map +0 -1
  90. package/bin/generators/package-json.d.ts.map +0 -1
  91. package/bin/generators/template-files.d.ts.map +0 -1
  92. package/bin/index.d.ts.map +0 -1
  93. package/bin/plugins/i18n-integration.d.ts +0 -25
  94. package/bin/plugins/i18n-integration.d.ts.map +0 -1
  95. package/bin/plugins/i18n-integration.js +0 -310
  96. package/bin/plugins/i18n-integration.js.map +0 -1
  97. package/bin/plugins/plantuml-integration.d.ts +0 -17
  98. package/bin/plugins/plantuml-integration.d.ts.map +0 -1
  99. package/bin/plugins/plantuml-integration.js +0 -112
  100. package/bin/plugins/plantuml-integration.js.map +0 -1
  101. package/bin/plugins/redoc-integration.d.ts +0 -25
  102. package/bin/plugins/redoc-integration.d.ts.map +0 -1
  103. package/bin/plugins/redoc-integration.js +0 -373
  104. package/bin/plugins/redoc-integration.js.map +0 -1
  105. package/bin/plugins/search-integration.d.ts +0 -20
  106. package/bin/plugins/search-integration.d.ts.map +0 -1
  107. package/bin/plugins/search-integration.js +0 -169
  108. package/bin/plugins/search-integration.js.map +0 -1
  109. package/bin/templates/index.d.ts.map +0 -1
  110. package/bin/templates/template-definitions.d.ts +0 -10
  111. package/bin/templates/template-definitions.d.ts.map +0 -1
  112. package/bin/templates/template-definitions.js +0 -517
  113. package/bin/templates/template-definitions.js.map +0 -1
  114. package/bin/tests/integration.test.d.ts.map +0 -1
  115. package/bin/types/index.d.ts.map +0 -1
  116. package/bin/utils/config-merger.d.ts.map +0 -1
  117. package/bin/utils/errors.d.ts.map +0 -1
  118. package/bin/utils/install.d.ts.map +0 -1
  119. package/bin/utils/message-formatter.d.ts.map +0 -1
  120. package/bin/utils/template-processor.d.ts.map +0 -1
  121. package/bin/utils/template-processor.test.d.ts.map +0 -1
  122. package/bin/utils/version.d.ts.map +0 -1
  123. package/templates/classic-spec/docusaurus.config.js.template +0 -106
  124. package/templates/classic-spec/package.json.template +0 -36
  125. package/templates/docs/example.drawio.svg +0 -57
  126. package/templates/external-design/docusaurus.config.js.template +0 -123
  127. package/templates/external-design/package.json.template +0 -36
  128. package/templates/internal-design/docusaurus.config.js.template +0 -123
  129. package/templates/internal-design/package.json.template +0 -36
  130. package/templates/project-analysis/docusaurus.config.js.template +0 -113
  131. package/templates/project-analysis/package.json.template +0 -36
  132. package/templates/requirements/docusaurus.config.js.template +0 -119
  133. package/templates/requirements/package.json.template +0 -36
@@ -1,9 +1,8 @@
1
- import { mkdir, writeFile, access, cp } from 'node:fs/promises';
2
- import { join, resolve, dirname } from 'node:path';
3
- import { existsSync, constants } from 'node:fs';
4
- import { fileURLToPath } from 'node:url';
1
+ import { mkdir, writeFile, access, cp } from 'fs/promises';
2
+ import { join, resolve, dirname } from 'path';
3
+ import { existsSync, constants } from 'fs';
4
+ import { fileURLToPath } from 'url';
5
5
  import { createTemplateProcessor } from '../utils/template-processor.js';
6
- import { getTemplateDefinition } from '../templates/template-definitions.js';
7
6
  // プロジェクト内のテンプレートディレクトリのパス
8
7
  const __filename = fileURLToPath(import.meta.url);
9
8
  const __dirname = dirname(__filename);
@@ -18,24 +17,19 @@ export async function copyTemplateFiles(selections, projectPath) {
18
17
  templateName: primaryTemplate.name,
19
18
  templateDisplayName: primaryTemplate.displayName,
20
19
  });
21
- // 全テンプレートのディレクトリ構造を統合
22
- const combinedStructure = combineTemplateStructures(templates);
23
20
  // ディレクトリ構造を作成
24
- await createDirectoryStructure(projectPath, combinedStructure);
25
- // 各テンプレートのファイルを生成
26
- for (const template of templates) {
27
- const templateDef = getTemplateDefinition(template.name);
28
- if (!templateDef) {
29
- console.warn(`Template definition not found for: ${template.name}`);
30
- continue;
31
- }
32
- // サンプルコンテンツを生成
33
- await generateSampleContent(projectPath, templateDef.sampleContent, processor);
21
+ await createDirectoryStructure(projectPath);
22
+ // API機能が有効な場合はOpenAPIファイルとディレクトリを生成
23
+ const hasApiFeature = selections.features.some(f => f.enabled && f.name === 'redoc');
24
+ if (hasApiFeature) {
25
+ await generateOpenAPIFiles(projectPath);
34
26
  }
35
- // 基本ファイルを生成(最初のテンプレートベース)
36
- await generateSidebarsConfig(projectPath, primaryTemplate.name, processor);
27
+ // 基本ファイルを生成(選択されたテンプレート配列を渡す)
28
+ await generateSidebarsConfig(projectPath, templates, processor);
37
29
  // 参考リポジトリから基本ファイルをコピー
38
30
  await copyFromReferenceRepo(projectPath, ['introduction']);
31
+ // ルートページファイルをコピー
32
+ await copyRootPageFiles(projectPath);
39
33
  // intro.mdもコピー
40
34
  const introSourcePath = join(TEMPLATE_DOCS_PATH, 'intro.md');
41
35
  const introTargetPath = join(projectPath, 'docs', 'intro.md');
@@ -54,38 +48,13 @@ export async function copyTemplateFiles(selections, projectPath) {
54
48
  }
55
49
  await generateCustomCSS(projectPath);
56
50
  await generateStaticFiles(projectPath, processor);
57
- }
58
- function combineTemplateStructures(templates) {
59
- const combined = {
60
- docs: new Set(),
61
- static: new Set(),
62
- src: new Set(),
63
- };
64
- for (const template of templates) {
65
- const templateDef = getTemplateDefinition(template.name);
66
- if (templateDef?.directoryStructure) {
67
- if (templateDef.directoryStructure.docs) {
68
- for (const dir of templateDef.directoryStructure.docs) {
69
- combined.docs.add(dir);
70
- }
71
- }
72
- if (templateDef.directoryStructure.static) {
73
- for (const dir of templateDef.directoryStructure.static) {
74
- combined.static.add(dir);
75
- }
76
- }
77
- if (templateDef.directoryStructure.src) {
78
- for (const dir of templateDef.directoryStructure.src) {
79
- combined.src.add(dir);
80
- }
81
- }
82
- }
51
+ await copyStaticAssets(projectPath);
52
+ await generateTBDComponent(projectPath);
53
+ // 要件定義テンプレートが選択されている場合はPriorityMatrixコンポーネントをコピー
54
+ const hasRequirementsTemplate = templates.some(template => template.name === 'requirements');
55
+ if (hasRequirementsTemplate) {
56
+ await generatePriorityMatrixComponent(projectPath);
83
57
  }
84
- return {
85
- docs: Array.from(combined.docs),
86
- static: Array.from(combined.static),
87
- src: Array.from(combined.src),
88
- };
89
58
  }
90
59
  async function validateProjectPath(projectPath) {
91
60
  const resolvedPath = resolve(projectPath);
@@ -101,128 +70,47 @@ async function validateProjectPath(projectPath) {
101
70
  throw new Error(`No write permission for directory: ${resolvedPath}`);
102
71
  }
103
72
  }
104
- async function createDirectoryStructure(projectPath, structure) {
73
+ async function createDirectoryStructure(projectPath) {
105
74
  // 基本ディレクトリを作成
106
75
  const baseDirectories = ['docs', 'src/css', 'src/components', 'static/img'];
107
76
  for (const dir of baseDirectories) {
108
77
  const dirPath = join(projectPath, dir);
109
78
  await mkdir(dirPath, { recursive: true });
110
79
  }
111
- // テンプレート固有のディレクトリを作成
112
- if (structure.docs) {
113
- for (const docDir of structure.docs) {
114
- const dirPath = join(projectPath, 'docs', docDir);
115
- await mkdir(dirPath, { recursive: true });
116
- }
117
- }
118
- if (structure.static) {
119
- for (const staticDir of structure.static) {
120
- const dirPath = join(projectPath, 'static', staticDir);
121
- await mkdir(dirPath, { recursive: true });
122
- }
123
- }
124
- if (structure.src) {
125
- for (const srcDir of structure.src) {
126
- const dirPath = join(projectPath, 'src', srcDir);
127
- await mkdir(dirPath, { recursive: true });
128
- }
129
- }
130
80
  }
131
- async function _generateTemplateFiles(projectPath, templateName, processor) {
132
- const templateDir = join(process.cwd(), 'templates', templateName);
133
- try {
134
- // package.json.templateを処理
135
- const packageJsonTemplate = join(templateDir, 'package.json.template');
136
- const processedPackageJson = await processor.processTemplateFile(packageJsonTemplate);
137
- await writeFile(join(projectPath, 'package.json'), processedPackageJson);
138
- // docusaurus.config.js.templateを処理
139
- const configTemplate = join(templateDir, 'docusaurus.config.js.template');
140
- const processedConfig = await processor.processTemplateFile(configTemplate);
141
- await writeFile(join(projectPath, 'docusaurus.config.js'), processedConfig);
142
- }
143
- catch (error) {
144
- console.error(`Error generating template files for ${templateName}:`, error);
145
- throw error;
146
- }
147
- }
148
- async function generateSampleContent(projectPath, sampleContent, processor) {
149
- for (const content of sampleContent) {
150
- const filePath = join(projectPath, content.path);
151
- // ディレクトリが存在しない場合は作成
152
- const dirPath = resolve(filePath, '..');
153
- await mkdir(dirPath, { recursive: true });
154
- // 既存のディレクトリと同名のファイルを作成しようとしている場合はエラー
155
- if (existsSync(filePath)) {
156
- const { stat } = await import('node:fs/promises');
157
- const stats = await stat(filePath);
158
- if (stats.isDirectory()) {
159
- throw new Error(`Cannot create file '${filePath}': A directory with the same name already exists`);
160
- }
161
- }
162
- if (content.template) {
163
- // テンプレート変数を置換
164
- const processedContent = processor.processTemplate(content.content);
165
- await writeFile(filePath, processedContent, 'utf8');
166
- }
167
- else {
168
- // そのまま書き込み
169
- await writeFile(filePath, content.content, 'utf8');
81
+ async function generateSidebarsConfig(projectPath, selectedTemplates, processor) {
82
+ const sidebarSections = [];
83
+ // 常に含まれるセクション
84
+ sidebarSections.push('introduction: [{ type: \'autogenerated\', dirName: \'introduction\' }]');
85
+ // 選択されたテンプレートに応じてセクションを追加
86
+ for (const template of selectedTemplates) {
87
+ switch (template.name) {
88
+ case 'project-analysis':
89
+ sidebarSections.push('overview: [{ type: \'autogenerated\', dirName: \'overview\' }]');
90
+ break;
91
+ case 'requirements':
92
+ sidebarSections.push('requirements: [{ type: \'autogenerated\', dirName: \'requirements\' }]');
93
+ break;
94
+ case 'external-design':
95
+ sidebarSections.push('external: [{ type: \'autogenerated\', dirName: \'external\' }]');
96
+ break;
97
+ case 'internal-design':
98
+ sidebarSections.push('internal: [{ type: \'autogenerated\', dirName: \'internal\' }]');
99
+ break;
100
+ case 'api-spec':
101
+ // APIテンプレートの場合は特別なセクションは追加しない(Redocで表示)
102
+ break;
170
103
  }
171
104
  }
172
- }
173
- async function generateSidebarsConfig(projectPath, templateName, processor) {
174
- const sidebarConfigs = {
175
- 'classic-spec': `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
105
+ const sidebarContent = `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
176
106
 
177
107
  // https://docusaurus.io/docs/sidebar
178
108
 
179
109
  const sidebars: SidebarsConfig = {
180
- introduction: [{ type: 'autogenerated', dirName: 'introduction' }],
110
+ ${sidebarSections.join(',\n ')},
181
111
  };
182
112
 
183
- export default sidebars;`,
184
- 'project-analysis': `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
185
-
186
- // https://docusaurus.io/docs/sidebar
187
-
188
- const sidebars: SidebarsConfig = {
189
- introduction: [{ type: 'autogenerated', dirName: 'introduction' }],
190
- businessAnalysis: [{ type: 'autogenerated', dirName: '01-overview' }],
191
- };
192
-
193
- export default sidebars;`,
194
- requirements: `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
195
-
196
- // https://docusaurus.io/docs/sidebar
197
-
198
- const sidebars: SidebarsConfig = {
199
- introduction: [{ type: 'autogenerated', dirName: 'introduction' }],
200
- requirements: [{ type: 'autogenerated', dirName: '02-requirements' }],
201
- };
202
-
203
- export default sidebars;`,
204
- 'external-design': `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
205
-
206
- // https://docusaurus.io/docs/sidebar
207
-
208
- const sidebars: SidebarsConfig = {
209
- introduction: [{ type: 'autogenerated', dirName: 'introduction' }],
210
- external: [{ type: 'autogenerated', dirName: '03-external' }],
211
- };
212
-
213
- export default sidebars;`,
214
- 'internal-design': `import type { SidebarsConfig } from '@docusaurus/plugin-content-docs';
215
-
216
- // https://docusaurus.io/docs/sidebar
217
-
218
- const sidebars: SidebarsConfig = {
219
- introduction: [{ type: 'autogenerated', dirName: 'introduction' }],
220
- internal: [{ type: 'autogenerated', dirName: '04-internal' }],
221
- };
222
-
223
- export default sidebars;`,
224
- };
225
- const sidebarContent = sidebarConfigs[templateName] || sidebarConfigs['classic-spec'];
113
+ export default sidebars;`;
226
114
  const processedContent = processor.processTemplate(sidebarContent);
227
115
  await writeFile(join(projectPath, 'sidebars.ts'), processedContent);
228
116
  }
@@ -322,6 +210,35 @@ yarn-error.log*
322
210
  `;
323
211
  await writeFile(join(projectPath, '.gitignore'), gitignoreContent, 'utf8');
324
212
  }
213
+ // ルートページファイルをコピー
214
+ async function copyRootPageFiles(projectPath) {
215
+ const srcPagesDir = join(projectPath, 'src', 'pages');
216
+ await mkdir(srcPagesDir, { recursive: true });
217
+ // index.tsxファイルをコピー(ユーザーが編集済み)
218
+ const indexSourcePath = join(TEMPLATE_DOCS_PATH, 'index.tsx');
219
+ const indexTargetPath = join(srcPagesDir, 'index.tsx');
220
+ if (existsSync(indexSourcePath)) {
221
+ try {
222
+ await cp(indexSourcePath, indexTargetPath);
223
+ console.log('Copied index.tsx to src/pages');
224
+ }
225
+ catch (error) {
226
+ console.warn(`Failed to copy index.tsx: ${error}`);
227
+ }
228
+ }
229
+ // index.module.cssファイルをコピー(参考リポジトリからコピー済み)
230
+ const cssSourcePath = join(TEMPLATE_DOCS_PATH, 'index.module.css');
231
+ const cssTargetPath = join(srcPagesDir, 'index.module.css');
232
+ if (existsSync(cssSourcePath)) {
233
+ try {
234
+ await cp(cssSourcePath, cssTargetPath);
235
+ console.log('Copied index.module.css to src/pages');
236
+ }
237
+ catch (error) {
238
+ console.warn(`Failed to copy index.module.css: ${error}`);
239
+ }
240
+ }
241
+ }
325
242
  // プロジェクト内のテンプレートから基本ディレクトリをコピー
326
243
  async function copyFromReferenceRepo(projectPath, directories) {
327
244
  const docsPath = join(projectPath, 'docs');
@@ -345,30 +262,508 @@ async function copyFromReferenceRepo(projectPath, directories) {
345
262
  // テンプレートに対応するディレクトリをコピー
346
263
  async function copyTemplateDirectory(projectPath, templateName) {
347
264
  const templateDirMap = {
348
- 'classic-spec': 'introduction',
349
- 'project-analysis': '01-overview',
350
- 'requirements': '02-requirements',
351
- 'external-design': '03-external',
352
- 'internal-design': '04-internal',
265
+ 'classic-spec': { source: 'introduction', target: 'introduction' },
266
+ 'project-analysis': { source: '01-overview', target: 'overview' },
267
+ 'requirements': { source: '02-requirements', target: 'requirements' },
268
+ 'external-design': { source: '03-external', target: 'external' },
269
+ 'internal-design': { source: '04-internal', target: 'internal' },
270
+ 'technical-spec': { source: '04-internal', target: 'internal' }, // 技術仕様書は内部設計と同じディレクトリを使用
353
271
  };
354
- const dirName = templateDirMap[templateName];
355
- if (!dirName) {
272
+ const dirMapping = templateDirMap[templateName];
273
+ if (!dirMapping) {
356
274
  console.warn(`No directory mapping found for template: ${templateName}`);
357
275
  return;
358
276
  }
359
- const sourcePath = join(TEMPLATE_DOCS_PATH, dirName);
360
- const targetPath = join(projectPath, 'docs', dirName);
277
+ const sourcePath = join(TEMPLATE_DOCS_PATH, dirMapping.source);
278
+ const targetPath = join(projectPath, 'docs', dirMapping.target);
361
279
  if (existsSync(sourcePath)) {
362
280
  try {
363
281
  await cp(sourcePath, targetPath, { recursive: true });
364
- console.log(`Copied ${dirName} directory for template: ${templateName}`);
282
+ console.log(`Copied ${dirMapping.source} directory for template: ${templateName}`);
365
283
  }
366
284
  catch (error) {
367
- console.warn(`Failed to copy ${dirName}: ${error}`);
285
+ console.warn(`Failed to copy ${dirMapping.source}: ${error}`);
368
286
  }
369
287
  }
370
288
  else {
371
289
  console.warn(`Template directory not found: ${sourcePath}`);
372
290
  }
373
291
  }
292
+ // OpenAPIファイルとディレクトリを生成
293
+ async function generateOpenAPIFiles(projectPath) {
294
+ // openapiディレクトリを作成
295
+ const openapiDir = join(projectPath, 'openapi');
296
+ await mkdir(openapiDir, { recursive: true });
297
+ // 参考リポジトリのOpenAPIファイルをコピー
298
+ const referenceOpenAPIPath = '/home/ohbayashi/projects/specment/openapi/openapi-single.yaml';
299
+ const targetOpenAPIPath = join(openapiDir, 'openapi-single.yaml');
300
+ if (existsSync(referenceOpenAPIPath)) {
301
+ try {
302
+ await cp(referenceOpenAPIPath, targetOpenAPIPath);
303
+ console.log('Copied OpenAPI specification from reference repository');
304
+ }
305
+ catch (error) {
306
+ console.warn(`Failed to copy OpenAPI file: ${error}`);
307
+ // フォールバック: サンプルOpenAPIファイルを生成
308
+ await generateSampleOpenAPIFile(targetOpenAPIPath);
309
+ }
310
+ }
311
+ else {
312
+ // 参考ファイルが見つからない場合はサンプルを生成
313
+ await generateSampleOpenAPIFile(targetOpenAPIPath);
314
+ }
315
+ }
316
+ // サンプルOpenAPIファイルを生成
317
+ async function generateSampleOpenAPIFile(filePath) {
318
+ const sampleOpenAPI = `openapi: 3.0.3
319
+ servers:
320
+ - url: //api.example.com/v1
321
+ description: プロダクションサーバー
322
+ - url: //staging-api.example.com/v1
323
+ description: ステージングサーバー
324
+ info:
325
+ description: |
326
+ これはサンプルAPIの仕様書です。
327
+
328
+ # はじめに
329
+ このAPIは **OpenAPI形式** でドキュメント化されており、RESTful APIの設計原則に従っています。
330
+
331
+ # 認証
332
+ このAPIはJWT(JSON Web Token)を使用したBearer認証を採用しています。
333
+
334
+ # レスポンス形式
335
+ すべてのAPIレスポンスはJSON形式で返されます。
336
+
337
+ version: 1.0.0
338
+ title: Sample API
339
+ contact:
340
+ name: APIサポート
341
+ email: support@example.com
342
+ license:
343
+ name: MIT
344
+ url: 'https://opensource.org/licenses/MIT'
345
+ tags:
346
+ - name: users
347
+ description: ユーザー管理
348
+ - name: auth
349
+ description: 認証・認可
350
+ paths:
351
+ /users:
352
+ get:
353
+ tags:
354
+ - users
355
+ summary: ユーザー一覧を取得
356
+ description: システムに登録されているユーザーの一覧を取得します
357
+ parameters:
358
+ - name: limit
359
+ in: query
360
+ description: 取得する件数の上限
361
+ required: false
362
+ schema:
363
+ type: integer
364
+ minimum: 1
365
+ maximum: 100
366
+ default: 20
367
+ - name: offset
368
+ in: query
369
+ description: 取得開始位置
370
+ required: false
371
+ schema:
372
+ type: integer
373
+ minimum: 0
374
+ default: 0
375
+ responses:
376
+ '200':
377
+ description: ユーザー一覧の取得に成功
378
+ content:
379
+ application/json:
380
+ schema:
381
+ type: object
382
+ properties:
383
+ users:
384
+ type: array
385
+ items:
386
+ $ref: '#/components/schemas/User'
387
+ total:
388
+ type: integer
389
+ description: 総件数
390
+ limit:
391
+ type: integer
392
+ description: 取得件数の上限
393
+ offset:
394
+ type: integer
395
+ description: 取得開始位置
396
+ '400':
397
+ description: リクエストパラメータが不正
398
+ content:
399
+ application/json:
400
+ schema:
401
+ $ref: '#/components/schemas/Error'
402
+ '500':
403
+ description: サーバーエラー
404
+ content:
405
+ application/json:
406
+ schema:
407
+ $ref: '#/components/schemas/Error'
408
+ security:
409
+ - BearerAuth: []
410
+ post:
411
+ tags:
412
+ - users
413
+ summary: 新しいユーザーを作成
414
+ description: 新しいユーザーをシステムに登録します
415
+ requestBody:
416
+ required: true
417
+ content:
418
+ application/json:
419
+ schema:
420
+ $ref: '#/components/schemas/CreateUserRequest'
421
+ responses:
422
+ '201':
423
+ description: ユーザーの作成に成功
424
+ content:
425
+ application/json:
426
+ schema:
427
+ $ref: '#/components/schemas/User'
428
+ '400':
429
+ description: リクエストボディが不正
430
+ content:
431
+ application/json:
432
+ schema:
433
+ $ref: '#/components/schemas/Error'
434
+ '409':
435
+ description: ユーザーが既に存在
436
+ content:
437
+ application/json:
438
+ schema:
439
+ $ref: '#/components/schemas/Error'
440
+ '500':
441
+ description: サーバーエラー
442
+ content:
443
+ application/json:
444
+ schema:
445
+ $ref: '#/components/schemas/Error'
446
+ security:
447
+ - BearerAuth: []
448
+
449
+ /users/{userId}:
450
+ get:
451
+ tags:
452
+ - users
453
+ summary: ユーザー詳細を取得
454
+ description: 指定されたIDのユーザー詳細情報を取得します
455
+ parameters:
456
+ - name: userId
457
+ in: path
458
+ required: true
459
+ description: ユーザーID
460
+ schema:
461
+ type: string
462
+ format: uuid
463
+ responses:
464
+ '200':
465
+ description: ユーザー詳細の取得に成功
466
+ content:
467
+ application/json:
468
+ schema:
469
+ $ref: '#/components/schemas/User'
470
+ '404':
471
+ description: ユーザーが見つからない
472
+ content:
473
+ application/json:
474
+ schema:
475
+ $ref: '#/components/schemas/Error'
476
+ '500':
477
+ description: サーバーエラー
478
+ content:
479
+ application/json:
480
+ schema:
481
+ $ref: '#/components/schemas/Error'
482
+ security:
483
+ - BearerAuth: []
484
+
485
+ /auth/login:
486
+ post:
487
+ tags:
488
+ - auth
489
+ summary: ユーザーログイン
490
+ description: ユーザー認証を行い、JWTトークンを発行します
491
+ requestBody:
492
+ required: true
493
+ content:
494
+ application/json:
495
+ schema:
496
+ type: object
497
+ required:
498
+ - email
499
+ - password
500
+ properties:
501
+ email:
502
+ type: string
503
+ format: email
504
+ description: メールアドレス
505
+ example: "user@example.com"
506
+ password:
507
+ type: string
508
+ description: パスワード
509
+ example: "password123"
510
+ responses:
511
+ '200':
512
+ description: ログイン成功
513
+ content:
514
+ application/json:
515
+ schema:
516
+ type: object
517
+ properties:
518
+ token:
519
+ type: string
520
+ description: JWTトークン
521
+ user:
522
+ $ref: '#/components/schemas/User'
523
+ '401':
524
+ description: 認証失敗
525
+ content:
526
+ application/json:
527
+ schema:
528
+ $ref: '#/components/schemas/Error'
529
+ '500':
530
+ description: サーバーエラー
531
+ content:
532
+ application/json:
533
+ schema:
534
+ $ref: '#/components/schemas/Error'
535
+
536
+ components:
537
+ schemas:
538
+ User:
539
+ type: object
540
+ required:
541
+ - id
542
+ - name
543
+ - email
544
+ - createdAt
545
+ properties:
546
+ id:
547
+ type: string
548
+ format: uuid
549
+ description: ユーザーID
550
+ example: "123e4567-e89b-12d3-a456-426614174000"
551
+ name:
552
+ type: string
553
+ description: ユーザー名
554
+ minLength: 1
555
+ maxLength: 100
556
+ example: "田中太郎"
557
+ email:
558
+ type: string
559
+ format: email
560
+ description: メールアドレス
561
+ example: "tanaka@example.com"
562
+ age:
563
+ type: integer
564
+ description: 年齢
565
+ minimum: 0
566
+ maximum: 150
567
+ example: 30
568
+ createdAt:
569
+ type: string
570
+ format: date-time
571
+ description: 作成日時
572
+ example: "2023-01-01T00:00:00Z"
573
+ updatedAt:
574
+ type: string
575
+ format: date-time
576
+ description: 更新日時
577
+ example: "2023-01-01T00:00:00Z"
578
+
579
+ CreateUserRequest:
580
+ type: object
581
+ required:
582
+ - name
583
+ - email
584
+ - password
585
+ properties:
586
+ name:
587
+ type: string
588
+ description: ユーザー名
589
+ minLength: 1
590
+ maxLength: 100
591
+ example: "田中太郎"
592
+ email:
593
+ type: string
594
+ format: email
595
+ description: メールアドレス
596
+ example: "tanaka@example.com"
597
+ age:
598
+ type: integer
599
+ description: 年齢
600
+ minimum: 0
601
+ maximum: 150
602
+ example: 30
603
+ password:
604
+ type: string
605
+ description: パスワード
606
+ minLength: 8
607
+ example: "password123"
608
+
609
+ Error:
610
+ type: object
611
+ required:
612
+ - code
613
+ - message
614
+ properties:
615
+ code:
616
+ type: string
617
+ description: エラーコード
618
+ example: "INVALID_REQUEST"
619
+ message:
620
+ type: string
621
+ description: エラーメッセージ
622
+ example: "リクエストパラメータが不正です"
623
+ details:
624
+ type: object
625
+ description: エラーの詳細情報
626
+ additionalProperties: true
627
+
628
+ securitySchemes:
629
+ BearerAuth:
630
+ type: http
631
+ scheme: bearer
632
+ bearerFormat: JWT
633
+
634
+ security:
635
+ - BearerAuth: []
636
+ `;
637
+ await writeFile(filePath, sampleOpenAPI, 'utf8');
638
+ console.log('Generated sample OpenAPI specification');
639
+ }
640
+ // 静的アセット(画像など)をコピー
641
+ async function copyStaticAssets(projectPath) {
642
+ const __filename = fileURLToPath(import.meta.url);
643
+ const __dirname = dirname(__filename);
644
+ const TEMPLATE_STATIC_PATH = resolve(__dirname, '../../templates/static');
645
+ const staticTargetPath = join(projectPath, 'static');
646
+ if (existsSync(TEMPLATE_STATIC_PATH)) {
647
+ try {
648
+ await cp(TEMPLATE_STATIC_PATH, staticTargetPath, { recursive: true });
649
+ console.log('Copied static assets from templates/static');
650
+ }
651
+ catch (error) {
652
+ console.warn(`Failed to copy static assets: ${error}`);
653
+ }
654
+ }
655
+ else {
656
+ console.warn(`Template static directory not found: ${TEMPLATE_STATIC_PATH}`);
657
+ // フォールバック: 個別にファイルをコピー
658
+ const staticImgDir = join(projectPath, 'static', 'img');
659
+ await mkdir(staticImgDir, { recursive: true });
660
+ // logo.svgファイルをコピー
661
+ const logoSourcePath = join(TEMPLATE_DOCS_PATH, 'logo.svg');
662
+ const logoTargetPath = join(staticImgDir, 'logo.svg');
663
+ if (existsSync(logoSourcePath)) {
664
+ try {
665
+ await cp(logoSourcePath, logoTargetPath);
666
+ console.log('Copied logo.svg to static/img');
667
+ }
668
+ catch (error) {
669
+ console.warn(`Failed to copy logo.svg: ${error}`);
670
+ }
671
+ }
672
+ }
673
+ }
674
+ // PriorityMatrixコンポーネントをコピー(要件定義テンプレート用)
675
+ async function generatePriorityMatrixComponent(projectPath) {
676
+ const __filename = fileURLToPath(import.meta.url);
677
+ const __dirname = dirname(__filename);
678
+ const TEMPLATE_SRC_PATH = resolve(__dirname, '../../templates/src');
679
+ // PriorityMatrixコンポーネントをコピー
680
+ const priorityMatrixSourcePath = join(TEMPLATE_SRC_PATH, 'components', 'PriorityMatrix');
681
+ const priorityMatrixTargetPath = join(projectPath, 'src', 'components', 'PriorityMatrix');
682
+ if (existsSync(priorityMatrixSourcePath)) {
683
+ try {
684
+ await cp(priorityMatrixSourcePath, priorityMatrixTargetPath, { recursive: true });
685
+ console.log('Generated PriorityMatrix component');
686
+ }
687
+ catch (error) {
688
+ console.warn(`Failed to copy PriorityMatrix component: ${error}`);
689
+ }
690
+ }
691
+ else {
692
+ console.warn(`PriorityMatrix component template not found: ${priorityMatrixSourcePath}`);
693
+ }
694
+ // 型定義ファイルをコピー(存在する場合)
695
+ const typesSourcePath = join(TEMPLATE_SRC_PATH, 'types');
696
+ const typesTargetPath = join(projectPath, 'src', 'types');
697
+ if (existsSync(typesSourcePath)) {
698
+ try {
699
+ await cp(typesSourcePath, typesTargetPath, { recursive: true });
700
+ console.log('Generated types directory');
701
+ }
702
+ catch (error) {
703
+ console.warn(`Failed to copy types directory: ${error}`);
704
+ }
705
+ }
706
+ else {
707
+ // 型定義ファイルが存在しない場合は作成
708
+ await mkdir(typesTargetPath, { recursive: true });
709
+ const requirementsTypeContent = `/**
710
+ * Requirements related type definitions
711
+ */
712
+
713
+ /**
714
+ * Priority scale from 1 to 9
715
+ * 1-3: Low priority
716
+ * 4-6: Medium priority
717
+ * 7-9: High priority
718
+ */
719
+ export type PriorityScale = 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
720
+
721
+ /**
722
+ * Requirement priority matrix
723
+ */
724
+ export interface RequirementPriority {
725
+ importance: PriorityScale;
726
+ urgency: PriorityScale;
727
+ }
728
+ `;
729
+ await writeFile(join(typesTargetPath, 'requirements.ts'), requirementsTypeContent, 'utf8');
730
+ console.log('Generated requirements.ts type definitions');
731
+ }
732
+ }
733
+ // TBDコンポーネントとその依存関係をコピー
734
+ async function generateTBDComponent(projectPath) {
735
+ const __filename = fileURLToPath(import.meta.url);
736
+ const __dirname = dirname(__filename);
737
+ const TEMPLATE_SRC_PATH = resolve(__dirname, '../../templates/src');
738
+ // TBDコンポーネントをコピー
739
+ const tbdSourcePath = join(TEMPLATE_SRC_PATH, 'components', 'TBD');
740
+ const tbdTargetPath = join(projectPath, 'src', 'components', 'TBD');
741
+ if (existsSync(tbdSourcePath)) {
742
+ try {
743
+ await cp(tbdSourcePath, tbdTargetPath, { recursive: true });
744
+ console.log('Generated TBD component');
745
+ }
746
+ catch (error) {
747
+ console.warn(`Failed to copy TBD component: ${error}`);
748
+ }
749
+ }
750
+ else {
751
+ console.warn(`TBD component template not found: ${tbdSourcePath}`);
752
+ }
753
+ // Highlightコンポーネントもコピー(TBDが依存しているため)
754
+ const highlightSourcePath = join(TEMPLATE_SRC_PATH, 'components', 'Highlight');
755
+ const highlightTargetPath = join(projectPath, 'src', 'components', 'Highlight');
756
+ if (existsSync(highlightSourcePath)) {
757
+ try {
758
+ await cp(highlightSourcePath, highlightTargetPath, { recursive: true });
759
+ console.log('Generated Highlight component');
760
+ }
761
+ catch (error) {
762
+ console.warn(`Failed to copy Highlight component: ${error}`);
763
+ }
764
+ }
765
+ else {
766
+ console.warn(`Highlight component template not found: ${highlightSourcePath}`);
767
+ }
768
+ }
374
769
  //# sourceMappingURL=template-files.js.map