@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.
- package/dist/commands/add-staging.d.ts +2 -3
- package/dist/commands/add-staging.js +38 -184
- package/dist/commands/init.d.ts +4 -0
- package/dist/commands/init.js +171 -368
- package/dist/commands/update.d.ts +2 -0
- package/dist/commands/update.js +11 -67
- package/dist/core/bundle.d.ts +14 -0
- package/dist/core/bundle.js +122 -0
- package/dist/core/cloudflare.d.ts +26 -0
- package/dist/core/cloudflare.js +60 -0
- package/dist/core/config.d.ts +26 -0
- package/dist/core/config.js +120 -0
- package/dist/core/content-structure.d.ts +19 -0
- package/dist/core/content-structure.js +116 -0
- package/dist/core/file-generators.d.ts +28 -0
- package/dist/core/file-generators.js +93 -0
- package/dist/core/git-operations.d.ts +15 -0
- package/dist/core/git-operations.js +78 -0
- package/dist/core/github.d.ts +16 -0
- package/dist/core/github.js +43 -0
- package/dist/core/index.d.ts +23 -0
- package/dist/core/index.js +30 -0
- package/dist/core/prerequisites.d.ts +22 -0
- package/dist/core/prerequisites.js +107 -0
- package/dist/core/status.d.ts +18 -0
- package/dist/core/status.js +122 -0
- package/dist/core/terraform.d.ts +7 -0
- package/dist/core/terraform.js +47 -0
- package/dist/core/types.d.ts +48 -0
- package/dist/core/types.js +21 -0
- package/dist/core/workflows.d.ts +11 -0
- package/dist/core/workflows.js +180 -0
- package/dist/index.js +2 -4
- package/dist/lib/templates.d.ts +9 -1
- package/dist/lib/templates.js +351 -27
- package/package.json +1 -1
|
@@ -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 (
|
|
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();
|
package/dist/lib/templates.d.ts
CHANGED
|
@@ -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
|
|
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
|
*/
|