@c-time/frelio-cli 0.1.0 → 1.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.
@@ -33,6 +33,7 @@ export declare function generateStorageFunction(): string;
33
33
  export declare function generateViteConfig(): string;
34
34
  export declare function generatePackageJson(config: ProjectConfig): string;
35
35
  export declare function generateTsConfig(): string;
36
+ export declare function generateTsConfigNode(): string;
36
37
  /**
37
38
  * ファイルを書き込む(ディレクトリがなければ作成)
38
39
  */
@@ -133,25 +133,121 @@ export const onRequest: PagesFunction<Env> = async (context) => {
133
133
  `;
134
134
  }
135
135
  export function generateViteConfig() {
136
- return `import { defineConfig } from 'vite'
136
+ return `import { defineConfig, type Plugin } from 'vite'
137
137
  import { resolve } from 'path'
138
+ import { spawn, type ChildProcess } from 'child_process'
138
139
 
139
140
  const templateAssets = resolve(__dirname, 'frelio-data/site/templates/assets')
141
+ const entries = resolve(templateAssets, 'entries')
142
+
143
+ /** dev server 起動時にコンテンツ変更監視を自動開始する Vite プラグイン */
144
+ function contentWatcherPlugin(): Plugin {
145
+ let watcher: ChildProcess | null = null
146
+ return {
147
+ name: 'content-watcher',
148
+ apply: 'serve',
149
+ configureServer(server) {
150
+ watcher = spawn('npx', ['tsx', 'scripts/watch-content.ts'], {
151
+ cwd: resolve(__dirname),
152
+ stdio: 'inherit',
153
+ shell: true,
154
+ })
155
+ watcher.on('error', (err) => {
156
+ console.error('[content-watcher] Failed to start:', err.message)
157
+ })
158
+ server.httpServer?.on('close', () => {
159
+ watcher?.kill()
160
+ })
161
+ },
162
+ buildEnd() {
163
+ watcher?.kill()
164
+ watcher = null
165
+ },
166
+ }
167
+ }
168
+
169
+ /** ビルド時に CSS を対応する JS チャンクのパスに合わせて styles/ 配下へ配置する */
170
+ function cssRelocatePlugin(): Plugin {
171
+ return {
172
+ name: 'css-relocate',
173
+ apply: 'build',
174
+ enforce: 'post',
175
+ generateBundle(_, bundle) {
176
+ const renames: Array<{ chunkName: string; oldCss: string; newCss: string }> = []
177
+
178
+ for (const chunk of Object.values(bundle)) {
179
+ if (chunk.type !== 'chunk' || !chunk.isEntry) continue
180
+ const meta = (chunk as any).viteMetadata as
181
+ | { importedCss?: Set<string> }
182
+ | undefined
183
+ if (!meta?.importedCss?.size) continue
184
+
185
+ const newCss = chunk.name.replace('/scripts/', '/styles/') + '.css'
186
+ for (const oldCss of meta.importedCss) {
187
+ if (oldCss !== newCss) {
188
+ renames.push({ chunkName: chunk.name, oldCss, newCss })
189
+ }
190
+ }
191
+ }
192
+
193
+ for (const { oldCss, newCss } of renames) {
194
+ const asset = bundle[oldCss]
195
+ if (!asset) continue
196
+ delete bundle[oldCss]
197
+ asset.fileName = newCss
198
+ bundle[newCss] = asset
199
+ }
200
+
201
+ for (const chunk of Object.values(bundle)) {
202
+ if (chunk.type !== 'chunk' || !chunk.isEntry) continue
203
+ const meta = (chunk as any).viteMetadata as
204
+ | { importedCss?: Set<string> }
205
+ | undefined
206
+ if (!meta?.importedCss) continue
207
+ for (const { oldCss, newCss } of renames) {
208
+ if (meta.importedCss.has(oldCss)) {
209
+ meta.importedCss.delete(oldCss)
210
+ meta.importedCss.add(newCss)
211
+ }
212
+ }
213
+ }
214
+ },
215
+ }
216
+ }
140
217
 
141
218
  export default defineConfig(({ command }) => ({
142
219
  root: 'frelio-data/site/templates',
143
220
  publicDir: command === 'serve' ? resolve(__dirname, 'public') : false,
221
+ plugins: [contentWatcherPlugin(), cssRelocatePlugin()],
222
+ resolve: {
223
+ alias: {
224
+ '@features': resolve(templateAssets, 'ts/features'),
225
+ },
226
+ },
227
+ css: {
228
+ preprocessorOptions: {
229
+ scss: {
230
+ api: 'modern-compiler',
231
+ loadPaths: [resolve(templateAssets, 'scss')],
232
+ },
233
+ },
234
+ },
144
235
  build: {
145
236
  outDir: resolve(__dirname, 'public'),
146
237
  emptyOutDir: false,
238
+ cssCodeSplit: true,
147
239
  rollupOptions: {
148
240
  input: {
149
- style: resolve(templateAssets, 'scss/style.scss'),
150
- index: resolve(templateAssets, 'ts/index.ts'),
241
+ 'common/scripts/index': resolve(entries, 'common/scripts/index.ts'),
242
+ 'home/scripts/index': resolve(entries, 'home/scripts/index.ts'),
243
+ 'about/scripts/index': resolve(entries, 'about/scripts/index.ts'),
244
+ 'contact/scripts/index': resolve(entries, 'contact/scripts/index.ts'),
245
+ 'news/scripts/index': resolve(entries, 'news/scripts/index.ts'),
246
+ 'news/detail/scripts/index': resolve(entries, 'news/detail/scripts/index.ts'),
151
247
  },
152
248
  output: {
153
- entryFileNames: 'assets/[name].js',
154
- assetFileNames: 'assets/[name].[ext]',
249
+ entryFileNames: '[name].js',
250
+ assetFileNames: '[name].[ext]',
155
251
  },
156
252
  },
157
253
  },
@@ -170,11 +266,31 @@ export function generatePackageJson(config) {
170
266
  dev: 'vite',
171
267
  build: 'vite build',
172
268
  preview: 'vite preview',
269
+ 'generate:dep-map': 'tsx scripts/generate-dependency-map.ts',
270
+ generate: 'tsx scripts/generate-data-json.ts',
271
+ 'generate:full': 'tsx scripts/generate-data-json.ts --full-rebuild',
272
+ 'generate:dry-run': 'tsx scripts/generate-data-json.ts --dry-run',
273
+ 'generate:html': 'tsx scripts/generate-html.ts',
274
+ 'generate:html:dry-run': 'tsx scripts/generate-html.ts --dry-run',
275
+ 'generate:sitemap': 'tsx scripts/generate-sitemap.ts',
276
+ 'generate:sitemap:full': 'tsx scripts/generate-sitemap.ts --full-rebuild',
277
+ 'watch:content': 'tsx scripts/watch-content.ts',
278
+ 'rebuild:indexes': 'tsx scripts/rebuild-indexes.ts',
279
+ 'rebuild:indexes:dry-run': 'tsx scripts/rebuild-indexes.ts --dry-run',
173
280
  },
174
281
  devDependencies: {
175
- vite: '^6.0.0',
282
+ '@c-time/frelio-content-ops': '^0.1.0',
283
+ '@c-time/frelio-data-json-generator': '*',
284
+ '@c-time/frelio-data-json-recipe': '^1.2.0',
285
+ '@c-time/frelio-data-json-recipe-to-dependency-map': '*',
286
+ '@c-time/frelio-dependency-map': '*',
287
+ '@c-time/frelio-gentl': '*',
288
+ '@c-time/frelio-types': '^0.1.0',
176
289
  sass: '^1.80.0',
290
+ tsx: '^4.0.0',
177
291
  typescript: '^5.7.0',
292
+ vite: '^6.0.0',
293
+ zod: '^3.25.0',
178
294
  },
179
295
  }, null, 2);
180
296
  }
@@ -183,13 +299,29 @@ export function generateTsConfig() {
183
299
  compilerOptions: {
184
300
  target: 'ES2022',
185
301
  module: 'ESNext',
186
- moduleResolution: 'Bundler',
187
- lib: ['ES2022', 'DOM', 'DOM.Iterable'],
302
+ moduleResolution: 'bundler',
188
303
  strict: true,
304
+ esModuleInterop: true,
189
305
  skipLibCheck: true,
306
+ resolveJsonModule: true,
307
+ outDir: 'dist',
308
+ },
309
+ include: ['frelio-data/site/templates/assets/ts/**/*.ts', 'vite.config.ts'],
310
+ }, null, 2);
311
+ }
312
+ export function generateTsConfigNode() {
313
+ return JSON.stringify({
314
+ compilerOptions: {
315
+ target: 'ES2022',
316
+ module: 'NodeNext',
317
+ moduleResolution: 'NodeNext',
318
+ strict: true,
190
319
  esModuleInterop: true,
320
+ skipLibCheck: true,
321
+ resolveJsonModule: true,
322
+ outDir: 'dist',
191
323
  },
192
- include: ['frelio-data/site/templates/assets/ts'],
324
+ include: ['scripts/**/*.ts'],
193
325
  }, null, 2);
194
326
  }
195
327
  /**
@@ -0,0 +1,8 @@
1
+ /**
2
+ * CLI パラメータのバリデーション関数
3
+ * prompts の validate コールバックと非対話モードの両方で使用
4
+ */
5
+ export declare function validateContentRepo(v: string): true | string;
6
+ export declare function validateR2PublicUrl(v: string): true | string;
7
+ export declare function validateStagingName(v: string): true | string;
8
+ export declare function validateRequired(v: string, label: string): true | string;
@@ -0,0 +1,22 @@
1
+ /**
2
+ * CLI パラメータのバリデーション関数
3
+ * prompts の validate コールバックと非対話モードの両方で使用
4
+ */
5
+ export function validateContentRepo(v) {
6
+ return v.includes('/') || 'owner/repo 形式で入力してください';
7
+ }
8
+ export function validateR2PublicUrl(v) {
9
+ return v === '' || v.startsWith('https://') || 'https:// で始まる URL を入力してください';
10
+ }
11
+ export function validateStagingName(v) {
12
+ if (!v)
13
+ return 'ステージング名を入力してください';
14
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(v))
15
+ return '小文字英数字とハイフンのみ使用可能です';
16
+ if (v === 'staging')
17
+ return '"staging" は予約済みです。別の名前を使用してください';
18
+ return true;
19
+ }
20
+ export function validateRequired(v, label) {
21
+ return v.length > 0 || `${label}は必須です`;
22
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-time/frelio-cli",
3
- "version": "0.1.0",
3
+ "version": "1.3.0",
4
4
  "description": "Frelio CMS setup CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",