@c-time/frelio-cli 1.4.1 → 1.4.3

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.
@@ -20,6 +20,9 @@ export declare function generateAndWriteRoutesJson(projectDir: string): Operatio
20
20
  export declare function generateAndWritePublicRoutesJson(projectDir: string): OperationResult<{
21
21
  path: string;
22
22
  }>;
23
+ export declare function generateAndWriteWorkerWranglerToml(projectDir: string, config: ProjectConfig): OperationResult<{
24
+ path: string;
25
+ }>;
23
26
  export declare function generateAndWriteStorageFunction(projectDir: string): OperationResult<{
24
27
  path: string;
25
28
  }>;
@@ -6,7 +6,7 @@
6
6
  */
7
7
  import path from 'node:path';
8
8
  import { ok, fail } from './types.js';
9
- import { generateConfigJson, generateWranglerToml, generateRedirects, generateRoutesJson, generateStorageFunction, writeFile, } from '../lib/templates.js';
9
+ import { generateConfigJson, generateWranglerToml, generateWorkerWranglerToml, generateRedirects, generateRoutesJson, generateStorageFunction, writeFile, } from '../lib/templates.js';
10
10
  // ---------------------------------------------------------------------------
11
11
  // Individual file generators
12
12
  // ---------------------------------------------------------------------------
@@ -61,6 +61,16 @@ export function generateAndWritePublicRoutesJson(projectDir) {
61
61
  return fail(`public/_routes.json 生成失敗: ${e.message}`, 'EXEC_FAILED');
62
62
  }
63
63
  }
64
+ export function generateAndWriteWorkerWranglerToml(projectDir, config) {
65
+ try {
66
+ const filePath = path.join(projectDir, 'workers', 'file-upload', 'wrangler.toml');
67
+ writeFile(filePath, generateWorkerWranglerToml(config));
68
+ return ok({ path: filePath });
69
+ }
70
+ catch (e) {
71
+ return fail(`worker wrangler.toml 生成失敗: ${e.message}`, 'EXEC_FAILED');
72
+ }
73
+ }
64
74
  export function generateAndWriteStorageFunction(projectDir) {
65
75
  try {
66
76
  const filePath = path.join(projectDir, 'functions', 'storage', '[[path]].ts');
@@ -79,6 +89,7 @@ export function regenerateAllConfigFiles(projectDir, config) {
79
89
  const generators = [
80
90
  () => generateAndWriteConfigJson(projectDir, config),
81
91
  () => generateAndWriteWranglerToml(projectDir, config),
92
+ () => generateAndWriteWorkerWranglerToml(projectDir, config),
82
93
  () => generateAndWriteRedirects(projectDir),
83
94
  () => generateAndWriteRoutesJson(projectDir),
84
95
  () => generateAndWritePublicRoutesJson(projectDir),
@@ -25,6 +25,7 @@ export declare function generateHash(): string;
25
25
  export declare function generateStagingDomain(productionUrl: string, pagesProjectName: string): string;
26
26
  export declare function generateConfigJson(config: ProjectConfig): string;
27
27
  export declare function generateWranglerToml(config: ProjectConfig): string;
28
+ export declare function generateWorkerWranglerToml(config: ProjectConfig): string;
28
29
  export declare function generateRedirects(): string;
29
30
  export declare function generateRoutesJson(): string;
30
31
  export declare function generateStorageFunction(): string;
@@ -56,6 +56,27 @@ bucket_name = "${config.r2BucketName}"
56
56
  R2_PUBLIC_URL = "${config.r2PublicUrl}"
57
57
  `;
58
58
  }
59
+ export function generateWorkerWranglerToml(config) {
60
+ const allowedOrigins = [
61
+ 'http://localhost:5173',
62
+ 'http://localhost:5174',
63
+ config.productionUrl,
64
+ config.previewUrl,
65
+ ].filter(Boolean).join(',');
66
+ return `name = "frelio-file-upload"
67
+ main = "src/index.ts"
68
+ compatibility_date = "2024-02-08"
69
+
70
+ [[r2_buckets]]
71
+ binding = "R2"
72
+ bucket_name = "${config.r2BucketName}"
73
+
74
+ [vars]
75
+ R2_PUBLIC_URL = "${config.r2PublicUrl}"
76
+ ALLOWED_ORIGINS = "${allowedOrigins}"
77
+ CONTENT_REPO = "${config.contentRepo}"
78
+ `;
79
+ }
59
80
  export function generateRedirects() {
60
81
  // 順序重要: 先にマッチしたルールが適用される
61
82
  return [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-time/frelio-cli",
3
- "version": "1.4.1",
3
+ "version": "1.4.3",
4
4
  "description": "Frelio CMS setup CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,11 +0,0 @@
1
- /**
2
- * core/workflows — GitHub Actions ワークフロー生成
3
- */
4
- import { type ProjectConfig, type OperationResult } from './types.js';
5
- export type WorkflowName = 'deploy-admin' | 'build-staging' | 'promote-production' | 'direct-deploy';
6
- export declare function generateWorkflow(projectDir: string, config: ProjectConfig, workflow: WorkflowName): OperationResult<{
7
- path: string;
8
- }>;
9
- export declare function generateWorkflows(projectDir: string, config: ProjectConfig): OperationResult<{
10
- files: string[];
11
- }>;
@@ -1,345 +0,0 @@
1
- /**
2
- * core/workflows — GitHub Actions ワークフロー生成
3
- */
4
- import fs from 'node:fs';
5
- import path from 'node:path';
6
- import { ok, fail } from './types.js';
7
- import { writeFile } from '../lib/templates.js';
8
- // ---------------------------------------------------------------------------
9
- // Individual workflow
10
- // ---------------------------------------------------------------------------
11
- export function generateWorkflow(projectDir, config, workflow) {
12
- const workflowsDir = path.join(projectDir, '.github', 'workflows');
13
- const content = getWorkflowContent(config, workflow);
14
- const fileName = `${workflow}.yml`;
15
- const filePath = path.join(workflowsDir, fileName);
16
- try {
17
- fs.mkdirSync(workflowsDir, { recursive: true });
18
- writeFile(filePath, content);
19
- return ok({ path: filePath });
20
- }
21
- catch (e) {
22
- return fail(`ワークフロー生成失敗 (${fileName}): ${e.message}`, 'EXEC_FAILED');
23
- }
24
- }
25
- // ---------------------------------------------------------------------------
26
- // All workflows
27
- // ---------------------------------------------------------------------------
28
- export function generateWorkflows(projectDir, config) {
29
- const names = ['deploy-admin', 'build-staging', 'promote-production', 'direct-deploy'];
30
- const files = [];
31
- for (const name of names) {
32
- const result = generateWorkflow(projectDir, config, name);
33
- if (!result.success)
34
- return result;
35
- files.push(result.data.path);
36
- }
37
- return ok({ files });
38
- }
39
- // ---------------------------------------------------------------------------
40
- // Workflow templates
41
- // ---------------------------------------------------------------------------
42
- function getWorkflowContent(config, workflow) {
43
- switch (workflow) {
44
- case 'deploy-admin':
45
- return `name: Deploy Admin
46
- on:
47
- push:
48
- branches: [admin]
49
-
50
- jobs:
51
- deploy:
52
- runs-on: ubuntu-latest
53
- steps:
54
- - uses: actions/checkout@v4
55
- - uses: actions/setup-node@v4
56
- with:
57
- node-version: 20
58
- cache: 'npm'
59
- - run: npm ci
60
- - run: npm run build
61
- - name: Deploy to Cloudflare Pages
62
- uses: cloudflare/wrangler-action@v3
63
- with:
64
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
65
- accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
66
- command: pages deploy dist --project-name=${config.adminPagesProjectName}
67
- `;
68
- case 'build-staging':
69
- return `# staging ブランチ(デフォルト + カスタム)への push で発火し、SSG を実行する。
70
- # カスタム staging(staging-*)は artifact アップロードなし(プレビュー専用)。
71
- name: Build Staging
72
- on:
73
- push:
74
- branches: [staging, 'staging-*']
75
-
76
- permissions:
77
- contents: read
78
-
79
- jobs:
80
- build:
81
- runs-on: ubuntu-latest
82
- steps:
83
- - uses: actions/checkout@v4
84
- - uses: actions/setup-node@v4
85
- with:
86
- node-version: 20
87
- cache: 'npm'
88
-
89
- # 前回のビルド状態を復元(差分ビルド用)
90
- - name: Restore SSG cache
91
- uses: actions/cache@v4
92
- with:
93
- path: |
94
- frelio-data/site/data/data-json
95
- public
96
- key: ssg-cache-\${{ github.ref_name }}-\${{ github.sha }}
97
- restore-keys: |
98
- ssg-cache-\${{ github.ref_name }}-
99
-
100
- - run: npm ci
101
-
102
- # Phase 1: JSON 中間データ生成
103
- - name: Generate JSON data
104
- run: npx frelio-data-json-generator
105
-
106
- # Phase 2: HTML 生成
107
- - name: Generate HTML
108
- run: npx frelio-gentl
109
-
110
- # Phase 3: アセットビルド(静的アセットコピー + Vite)
111
- - name: Build assets
112
- run: npm run build
113
-
114
- # デフォルト staging のみ: artifact をアップロード(本番デプロイ用)
115
- - name: Upload artifact
116
- if: github.ref == 'refs/heads/staging'
117
- uses: actions/upload-artifact@v4
118
- with:
119
- name: staging-build
120
- path: public/
121
- retention-days: 14
122
-
123
- # Cloudflare Pages にブランチプレビューとしてデプロイ
124
- - name: Deploy preview
125
- uses: cloudflare/wrangler-action@v3
126
- with:
127
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
128
- accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
129
- command: pages deploy public --project-name=${config.pagesProjectName} --branch=\${{ github.ref_name }}
130
- `;
131
- case 'promote-production':
132
- return `# staging → main マージ(push to main)で発火。
133
- # 最新の staging artifact をダウンロードし、Pages 本番にデプロイする。
134
- # artifact 欠損時はフォールバックとしてフル SSG ビルドを実行する。
135
- name: Promote to Production
136
- on:
137
- push:
138
- branches: [main]
139
-
140
- permissions:
141
- contents: write
142
- actions: read
143
-
144
- jobs:
145
- deploy:
146
- runs-on: ubuntu-latest
147
- steps:
148
- - uses: actions/checkout@v4
149
- with:
150
- fetch-depth: 0
151
-
152
- # 最新の成功した Build Staging ワークフロー run を検索
153
- - name: Find latest staging build run
154
- id: find-run
155
- uses: actions/github-script@v7
156
- with:
157
- script: |
158
- const runs = await github.rest.actions.listWorkflowRuns({
159
- owner: context.repo.owner,
160
- repo: context.repo.repo,
161
- workflow_id: 'build-staging.yml',
162
- branch: 'staging',
163
- status: 'success',
164
- per_page: 1,
165
- });
166
- if (runs.data.workflow_runs.length > 0) {
167
- core.setOutput('run-id', runs.data.workflow_runs[0].id);
168
- } else {
169
- core.setOutput('run-id', '');
170
- }
171
-
172
- # cross-workflow artifact ダウンロード
173
- - name: Download staging artifact
174
- id: download-artifact
175
- if: steps.find-run.outputs.run-id != ''
176
- continue-on-error: true
177
- uses: actions/download-artifact@v4
178
- with:
179
- name: staging-build
180
- path: public/
181
- github-token: \${{ secrets.GITHUB_TOKEN }}
182
- run-id: \${{ steps.find-run.outputs.run-id }}
183
-
184
- # artifact 取得結果を判定
185
- - name: Check if artifact was downloaded
186
- id: check-artifact
187
- run: |
188
- if [ -d "public" ] && [ "\$(ls -A public 2>/dev/null)" ]; then
189
- echo "has_artifact=true" >> "\$GITHUB_OUTPUT"
190
- else
191
- echo "::warning::Staging artifact not found or expired. Running full SSG build."
192
- echo "has_artifact=false" >> "\$GITHUB_OUTPUT"
193
- fi
194
-
195
- # --- フォールバックビルド(artifact 欠損時のみ) ---
196
- - name: Setup Node.js (fallback)
197
- if: steps.check-artifact.outputs.has_artifact == 'false'
198
- uses: actions/setup-node@v4
199
- with:
200
- node-version: 20
201
- cache: 'npm'
202
-
203
- - name: Install dependencies (fallback)
204
- if: steps.check-artifact.outputs.has_artifact == 'false'
205
- run: npm ci
206
-
207
- - name: Full SSG build (fallback)
208
- if: steps.check-artifact.outputs.has_artifact == 'false'
209
- run: |
210
- npx frelio-data-json-generator --full-rebuild
211
- npx frelio-gentl
212
- npm run build
213
-
214
- # Cloudflare Pages 本番にデプロイ
215
- - name: Deploy to production
216
- uses: cloudflare/wrangler-action@v3
217
- with:
218
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
219
- accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
220
- command: pages deploy public --project-name=${config.pagesProjectName} --branch=main
221
-
222
- # デプロイタグ作成
223
- - name: Create deploy tag
224
- run: |
225
- VERSION=\$(jq -r '.version' version.json 2>/dev/null || echo "0.0.0")
226
- PREFIX="d\${VERSION}."
227
-
228
- LATEST=\$(git tag -l "\${PREFIX}*" | sed "s/^\${PREFIX}//" | sort -n | tail -1)
229
- NEXT=\$(( \${LATEST:-0} + 1 ))
230
-
231
- TAG="\${PREFIX}\${NEXT}"
232
- echo "Creating tag: \$TAG"
233
-
234
- git config user.name "github-actions[bot]"
235
- git config user.email "github-actions[bot]@users.noreply.github.com"
236
- git tag -a "\$TAG" -m "Production deploy \$TAG"
237
- git push origin "\$TAG"
238
-
239
- echo "::notice::Tagged as \$TAG"
240
- `;
241
- case 'direct-deploy':
242
- return `# CMS の「直接デプロイ」ボタンから workflow_dispatch で発火。
243
- # develop → staging マージ → SSG ビルド → artifact → staging プレビュー →
244
- # staging → main マージ → 本番デプロイ → デプロイタグ付与
245
- name: Direct Deploy
246
- on:
247
- workflow_dispatch:
248
-
249
- permissions:
250
- contents: write
251
-
252
- jobs:
253
- build:
254
- runs-on: ubuntu-latest
255
- steps:
256
- - uses: actions/checkout@v4
257
- with:
258
- fetch-depth: 0
259
-
260
- - name: Configure git
261
- run: |
262
- git config user.name "github-actions[bot]"
263
- git config user.email "github-actions[bot]@users.noreply.github.com"
264
-
265
- # Step 1: develop → staging マージ
266
- - name: Merge develop into staging
267
- run: |
268
- git checkout staging
269
- git merge origin/develop --no-edit
270
- git push origin staging
271
-
272
- # Step 2: SSG ビルド
273
- - uses: actions/setup-node@v4
274
- with:
275
- node-version: 20
276
- cache: 'npm'
277
-
278
- # 前回の staging ビルド状態を復元(差分ビルド用)
279
- - name: Restore SSG cache
280
- uses: actions/cache@v4
281
- with:
282
- path: |
283
- frelio-data/site/data/data-json
284
- public
285
- key: ssg-cache-staging-\${{ github.sha }}
286
- restore-keys: |
287
- ssg-cache-staging-
288
-
289
- - run: npm ci
290
-
291
- - name: Generate JSON data
292
- run: npx frelio-data-json-generator
293
-
294
- - name: Generate HTML
295
- run: npx frelio-gentl
296
-
297
- - name: Build assets
298
- run: npm run build
299
-
300
- # Step 3: artifact アップロード
301
- - name: Upload artifact
302
- uses: actions/upload-artifact@v4
303
- with:
304
- name: staging-build
305
- path: public/
306
- retention-days: 14
307
-
308
- # Step 4: Cloudflare Pages プレビューデプロイ(staging ブランチ)
309
- - name: Deploy staging preview
310
- uses: cloudflare/wrangler-action@v3
311
- with:
312
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
313
- accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
314
- command: pages deploy public --project-name=${config.pagesProjectName} --branch=staging
315
-
316
- # Step 5: staging → main マージ
317
- - name: Fast-forward main to staging
318
- run: |
319
- git checkout main
320
- git merge --ff-only staging
321
- git push origin main
322
-
323
- # Step 6: Cloudflare Pages 本番デプロイ
324
- - name: Deploy to production
325
- uses: cloudflare/wrangler-action@v3
326
- with:
327
- apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
328
- accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
329
- command: pages deploy public --project-name=${config.pagesProjectName} --branch=main
330
-
331
- # Step 7: デプロイタグ作成
332
- - name: Create deploy tag
333
- run: |
334
- VERSION=\$(jq -r '.version' version.json 2>/dev/null || echo "0.0.0")
335
- PREFIX="d\${VERSION}."
336
- LATEST=\$(git tag -l "\${PREFIX}*" | sed "s/^\${PREFIX}//" | sort -n | tail -1)
337
- NEXT=\$(( \${LATEST:-0} + 1 ))
338
- TAG="\${PREFIX}\${NEXT}"
339
-
340
- git tag -a "\$TAG" -m "Direct deploy \$TAG"
341
- git push origin "\$TAG"
342
- echo "::notice::Tagged as \$TAG"
343
- `;
344
- }
345
- }
@@ -1,15 +0,0 @@
1
- /**
2
- * GitHub Release からの tarball ダウンロード
3
- */
4
- type ReleaseAsset = {
5
- name: string;
6
- browser_download_url: string;
7
- };
8
- type Release = {
9
- tag_name: string;
10
- assets: ReleaseAsset[];
11
- };
12
- export declare function getLatestRelease(): Promise<Release>;
13
- export declare function getRelease(version: string): Promise<Release>;
14
- export declare function downloadTarball(release: Release, destDir: string): Promise<string>;
15
- export {};
@@ -1,41 +0,0 @@
1
- /**
2
- * GitHub Release からの tarball ダウンロード
3
- */
4
- import { createWriteStream } from 'node:fs';
5
- import { pipeline } from 'node:stream/promises';
6
- import { Readable } from 'node:stream';
7
- import path from 'node:path';
8
- const REPO = 'ctime-projects/frelio';
9
- export async function getLatestRelease() {
10
- const res = await fetch(`https://api.github.com/repos/${REPO}/releases/latest`, {
11
- headers: { Accept: 'application/vnd.github.v3+json' },
12
- });
13
- if (!res.ok) {
14
- throw new Error(`Failed to fetch latest release: ${res.status} ${res.statusText}`);
15
- }
16
- return res.json();
17
- }
18
- export async function getRelease(version) {
19
- const tag = version.startsWith('v') ? version : `v${version}`;
20
- const res = await fetch(`https://api.github.com/repos/${REPO}/releases/tags/${tag}`, {
21
- headers: { Accept: 'application/vnd.github.v3+json' },
22
- });
23
- if (!res.ok) {
24
- throw new Error(`Release ${tag} not found: ${res.status}`);
25
- }
26
- return res.json();
27
- }
28
- export async function downloadTarball(release, destDir) {
29
- const asset = release.assets.find((a) => a.name.endsWith('.tar.gz'));
30
- if (!asset) {
31
- throw new Error('No tarball found in release assets');
32
- }
33
- const destPath = path.join(destDir, asset.name);
34
- const res = await fetch(asset.browser_download_url);
35
- if (!res.ok || !res.body) {
36
- throw new Error(`Failed to download: ${res.status}`);
37
- }
38
- const readable = Readable.fromWeb(res.body);
39
- await pipeline(readable, createWriteStream(destPath));
40
- return destPath;
41
- }
@@ -1,5 +0,0 @@
1
- /**
2
- * 初期コンテンツ・テンプレート・レシピの生成
3
- * frelio-demo を踏襲したデモサイト構造
4
- */
5
- export declare function generateInitialContent(projectDir: string): void;