@c-time/frelio-cli 1.3.13 → 1.4.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.
@@ -0,0 +1,48 @@
1
+ /**
2
+ * core/ モジュール共通の型定義
3
+ *
4
+ * 全 core 関数は OperationResult<T> を返す。
5
+ * AI エージェントが結果を構造的に判断できるようにする。
6
+ */
7
+ import type { ProjectConfig } from '../lib/templates.js';
8
+ export type { ProjectConfig };
9
+ export type ErrorCode = 'NOT_FOUND' | 'ALREADY_EXISTS' | 'AUTH_REQUIRED' | 'COMMAND_MISSING' | 'VALIDATION_ERROR' | 'EXEC_FAILED';
10
+ export type OperationSuccess<T = void> = {
11
+ success: true;
12
+ alreadyExisted?: boolean;
13
+ data: T;
14
+ };
15
+ export type OperationFailure = {
16
+ success: false;
17
+ error: string;
18
+ code: ErrorCode;
19
+ };
20
+ export type OperationResult<T = void> = OperationSuccess<T> | OperationFailure;
21
+ export declare function ok<T>(data: T, alreadyExisted?: boolean): OperationSuccess<T>;
22
+ export declare function okVoid(alreadyExisted?: boolean): OperationSuccess<void>;
23
+ export declare function fail(error: string, code: ErrorCode): OperationFailure;
24
+ export type ProjectStatus = {
25
+ projectDir: string;
26
+ hasGitRepo: boolean;
27
+ hasContentStructure: boolean;
28
+ hasAdminBundle: boolean;
29
+ hasConfigJson: boolean;
30
+ hasWranglerToml: boolean;
31
+ hasWorkflows: boolean;
32
+ hasTerraform: boolean;
33
+ config: ProjectConfig | null;
34
+ branches: string[];
35
+ remoteUrl: string | null;
36
+ missingPrerequisites: string[];
37
+ bundleVersion: string | null;
38
+ };
39
+ export type BuildConfigParams = {
40
+ contentRepo: string;
41
+ githubClientId?: string;
42
+ siteTitle?: string;
43
+ productionUrl?: string;
44
+ stagingDomain?: string;
45
+ r2BucketName?: string;
46
+ r2PublicUrl?: string;
47
+ ownerUsername?: string;
48
+ };
@@ -0,0 +1,21 @@
1
+ /**
2
+ * core/ モジュール共通の型定義
3
+ *
4
+ * 全 core 関数は OperationResult<T> を返す。
5
+ * AI エージェントが結果を構造的に判断できるようにする。
6
+ */
7
+ // ---------------------------------------------------------------------------
8
+ // Helper constructors
9
+ // ---------------------------------------------------------------------------
10
+ export function ok(data, alreadyExisted) {
11
+ const result = { success: true, data };
12
+ if (alreadyExisted)
13
+ result.alreadyExisted = true;
14
+ return result;
15
+ }
16
+ export function okVoid(alreadyExisted) {
17
+ return ok(undefined, alreadyExisted);
18
+ }
19
+ export function fail(error, code) {
20
+ return { success: false, error, code };
21
+ }
@@ -0,0 +1,11 @@
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
+ }>;
@@ -0,0 +1,180 @@
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 `name: Build Staging
70
+ on:
71
+ push:
72
+ branches: [staging, 'staging-*']
73
+
74
+ permissions:
75
+ contents: read
76
+
77
+ jobs:
78
+ build:
79
+ runs-on: ubuntu-latest
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+ - uses: actions/setup-node@v4
83
+ with:
84
+ node-version: 20
85
+ cache: 'npm'
86
+ - name: Restore SSG cache
87
+ uses: actions/cache@v4
88
+ with:
89
+ path: |
90
+ frelio-data/site/data/data-json
91
+ public
92
+ key: ssg-cache-\${{ github.ref_name }}-\${{ github.sha }}
93
+ restore-keys: |
94
+ ssg-cache-\${{ github.ref_name }}-
95
+ - run: npm ci
96
+ - name: SSG Build
97
+ run: echo "TODO: Add SSG build steps"
98
+ - name: Upload artifact
99
+ if: github.ref == 'refs/heads/staging'
100
+ uses: actions/upload-artifact@v4
101
+ with:
102
+ name: staging-build
103
+ path: public/
104
+ retention-days: 14
105
+ - name: Deploy preview
106
+ uses: cloudflare/wrangler-action@v3
107
+ with:
108
+ apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
109
+ accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
110
+ command: pages deploy public --project-name=${config.pagesProjectName} --branch=\${{ github.ref_name }}
111
+ `;
112
+ case 'promote-production':
113
+ return `name: Promote to Production
114
+ on:
115
+ push:
116
+ branches: [main]
117
+
118
+ permissions:
119
+ contents: write
120
+ actions: read
121
+
122
+ jobs:
123
+ deploy:
124
+ runs-on: ubuntu-latest
125
+ steps:
126
+ - uses: actions/checkout@v4
127
+ with:
128
+ fetch-depth: 0
129
+ - name: Download staging artifact
130
+ uses: actions/download-artifact@v4
131
+ with:
132
+ name: staging-build
133
+ path: public/
134
+ - name: Deploy to production
135
+ uses: cloudflare/wrangler-action@v3
136
+ with:
137
+ apiToken: \${{ secrets.CLOUDFLARE_API_TOKEN }}
138
+ accountId: \${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
139
+ command: pages deploy public --project-name=${config.pagesProjectName} --branch=main
140
+ - name: Create deploy tag
141
+ run: |
142
+ VERSION=\$(cat version.json | node -e "process.stdin.on('data',d=>console.log(JSON.parse(d).version))")
143
+ EXISTING=\$(git tag -l "d\${VERSION}.*" | wc -l)
144
+ NEXT=\$((EXISTING + 1))
145
+ TAG="d\${VERSION}.\${NEXT}"
146
+ git tag "\$TAG"
147
+ git push origin "\$TAG"
148
+ `;
149
+ case 'direct-deploy':
150
+ return `name: Direct Deploy
151
+ on:
152
+ workflow_dispatch:
153
+
154
+ permissions:
155
+ contents: write
156
+
157
+ jobs:
158
+ deploy:
159
+ runs-on: ubuntu-latest
160
+ steps:
161
+ - uses: actions/checkout@v4
162
+ with:
163
+ fetch-depth: 0
164
+ - name: Merge develop to staging
165
+ run: |
166
+ git config user.name "github-actions[bot]"
167
+ git config user.email "github-actions[bot]@users.noreply.github.com"
168
+ git checkout staging
169
+ git merge origin/develop --no-edit
170
+ git push origin staging
171
+ - name: Wait for staging build
172
+ run: echo "Staging build will be triggered by the push above. Monitor build-staging.yml."
173
+ - name: Fast-forward main
174
+ run: |
175
+ git checkout main
176
+ git merge staging --ff-only
177
+ git push origin main
178
+ `;
179
+ }
180
+ }
package/dist/index.js CHANGED
@@ -13,6 +13,7 @@ program
13
13
  .description('Initialize a new Frelio CMS project (creates repo, deploys admin, sets up R2)')
14
14
  .option('--skip-github', 'Skip GitHub repository creation')
15
15
  .option('--skip-cloudflare', 'Skip Cloudflare setup (R2, Pages)')
16
+ .option('--terraform', 'Generate Terraform files instead of running wrangler commands')
16
17
  .option('--content-repo <repo>', 'Repository name (owner/repo)')
17
18
  .option('--site-title <title>', 'Site title')
18
19
  .option('--production-url <url>', 'Production URL')
@@ -30,10 +31,7 @@ program
30
31
  .action(updateCommand);
31
32
  program
32
33
  .command('add-staging')
33
- .description('Add a staging environment (preview branch + Cloudflare Pages project)')
34
+ .description('Add a staging environment (creates branch, uses Pages branch preview)')
34
35
  .option('--name <name>', 'Staging name (creates staging-{name} branch)')
35
- .option('--skip-cloudflare', 'Skip Cloudflare Pages project creation')
36
- .option('--pages-project <name>', 'Cloudflare Pages project name for staging')
37
- .option('--domain <domain>', 'Custom domain for staging')
38
36
  .action(addStagingCommand);
39
37
  program.parse();
@@ -10,6 +10,7 @@ export type ProjectConfig = {
10
10
  r2BucketName: string;
11
11
  r2PublicUrl: string;
12
12
  pagesProjectName: string;
13
+ adminPagesProjectName: string;
13
14
  ownerUsername: string;
14
15
  stagingDomain: string;
15
16
  };
@@ -24,7 +25,8 @@ export declare function generateHash(): string;
24
25
  export declare function generateStagingDomain(productionUrl: string, pagesProjectName: string): string;
25
26
  export declare function generateConfigJson(config: ProjectConfig): string;
26
27
  export declare function generateWranglerToml(config: ProjectConfig): string;
27
- export declare function generateUsersIndex(config: ProjectConfig): string;
28
+ export declare function generateUsersJson(config: ProjectConfig): string;
29
+ export declare function generateStagesJson(): string;
28
30
  export declare function generateContentTypesJson(): string;
29
31
  export declare function generateVersionJson(): string;
30
32
  export declare function generateRedirects(): string;
@@ -34,6 +36,12 @@ export declare function generateViteConfig(): string;
34
36
  export declare function generatePackageJson(config: ProjectConfig): string;
35
37
  export declare function generateTsConfig(): string;
36
38
  export declare function generateTsConfigNode(): string;
39
+ export declare function generateTerraformProviders(): string;
40
+ export declare function generateTerraformVariables(config: ProjectConfig): string;
41
+ export declare function generateTerraformMain(config: ProjectConfig): string;
42
+ export declare function generateTerraformOutputs(): string;
43
+ export declare function generateTerraformTfvarsExample(config: ProjectConfig): string;
44
+ export declare function generateTerraformReadme(): string;
37
45
  /**
38
46
  * ファイルを書き込む(ディレクトリがなければ作成)
39
47
  */