@c-time/frelio-cli 1.3.12 → 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
package/dist/lib/templates.js
CHANGED
|
@@ -38,10 +38,14 @@ export function generateConfigJson(config) {
|
|
|
38
38
|
siteTitle: config.siteTitle,
|
|
39
39
|
productionUrl: config.productionUrl,
|
|
40
40
|
previewUrl: config.previewUrl,
|
|
41
|
+
pagesProjectName: config.pagesProjectName,
|
|
42
|
+
adminPagesProjectName: config.adminPagesProjectName,
|
|
43
|
+
r2BucketName: config.r2BucketName,
|
|
44
|
+
r2PublicUrl: config.r2PublicUrl,
|
|
41
45
|
}, null, 2);
|
|
42
46
|
}
|
|
43
47
|
export function generateWranglerToml(config) {
|
|
44
|
-
return `name = "${config.
|
|
48
|
+
return `name = "${config.adminPagesProjectName}"
|
|
45
49
|
compatibility_date = "2024-01-01"
|
|
46
50
|
|
|
47
51
|
[[r2_buckets]]
|
|
@@ -52,34 +56,34 @@ bucket_name = "${config.r2BucketName}"
|
|
|
52
56
|
R2_PUBLIC_URL = "${config.r2PublicUrl}"
|
|
53
57
|
`;
|
|
54
58
|
}
|
|
55
|
-
export function
|
|
59
|
+
export function generateUsersJson(config) {
|
|
56
60
|
const owner = config.ownerUsername;
|
|
57
|
-
return JSON.stringify(
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
canEditDeploy: true,
|
|
78
|
-
},
|
|
61
|
+
return JSON.stringify([
|
|
62
|
+
{
|
|
63
|
+
githubUsername: owner,
|
|
64
|
+
displayName: owner,
|
|
65
|
+
isOwner: true,
|
|
66
|
+
permissions: {
|
|
67
|
+
canViewUsers: true,
|
|
68
|
+
canEditUsers: true,
|
|
69
|
+
canViewStaging: true,
|
|
70
|
+
canEditStaging: true,
|
|
71
|
+
canViewContentType: true,
|
|
72
|
+
canEditContentType: true,
|
|
73
|
+
canViewBuildRecipes: true,
|
|
74
|
+
canEditBuildRecipes: true,
|
|
75
|
+
canViewTemplates: true,
|
|
76
|
+
canEditTemplates: true,
|
|
77
|
+
canViewStorage: true,
|
|
78
|
+
canEditStorage: true,
|
|
79
|
+
canViewDeploy: true,
|
|
80
|
+
canEditDeploy: true,
|
|
79
81
|
},
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
82
|
+
},
|
|
83
|
+
], null, 2);
|
|
84
|
+
}
|
|
85
|
+
export function generateStagesJson() {
|
|
86
|
+
return JSON.stringify([], null, 2);
|
|
83
87
|
}
|
|
84
88
|
export function generateContentTypesJson() {
|
|
85
89
|
return JSON.stringify([], null, 2);
|
|
@@ -324,6 +328,326 @@ export function generateTsConfigNode() {
|
|
|
324
328
|
include: ['scripts/**/*.ts'],
|
|
325
329
|
}, null, 2);
|
|
326
330
|
}
|
|
331
|
+
// --- Terraform generators ---
|
|
332
|
+
export function generateTerraformProviders() {
|
|
333
|
+
return `terraform {
|
|
334
|
+
required_version = ">= 1.5.0"
|
|
335
|
+
|
|
336
|
+
required_providers {
|
|
337
|
+
cloudflare = {
|
|
338
|
+
source = "cloudflare/cloudflare"
|
|
339
|
+
version = "~> 5.0"
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
# Cloudflare R2 をリモートバックエンドとして使う場合はコメントを外す:
|
|
344
|
+
# backend "s3" {
|
|
345
|
+
# bucket = "terraform-state"
|
|
346
|
+
# key = "frelio/terraform.tfstate"
|
|
347
|
+
# region = "auto"
|
|
348
|
+
# skip_credentials_validation = true
|
|
349
|
+
# skip_metadata_api_check = true
|
|
350
|
+
# skip_region_validation = true
|
|
351
|
+
# skip_requesting_account_id = true
|
|
352
|
+
# skip_s3_checksum = true
|
|
353
|
+
# endpoints = {
|
|
354
|
+
# s3 = "https://<account_id>.r2.cloudflarestorage.com"
|
|
355
|
+
# }
|
|
356
|
+
# }
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
provider "cloudflare" {
|
|
360
|
+
api_token = var.cloudflare_api_token
|
|
361
|
+
}
|
|
362
|
+
`;
|
|
363
|
+
}
|
|
364
|
+
export function generateTerraformVariables(config) {
|
|
365
|
+
return `# --- 必須変数 ---
|
|
366
|
+
|
|
367
|
+
variable "cloudflare_account_id" {
|
|
368
|
+
type = string
|
|
369
|
+
description = "Cloudflare Account ID"
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
variable "cloudflare_api_token" {
|
|
373
|
+
type = string
|
|
374
|
+
sensitive = true
|
|
375
|
+
description = "Cloudflare API Token (Pages + R2 の操作権限が必要)"
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
variable "github_client_id" {
|
|
379
|
+
type = string
|
|
380
|
+
description = "GitHub OAuth App Client ID"
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
variable "github_client_secret" {
|
|
384
|
+
type = string
|
|
385
|
+
sensitive = true
|
|
386
|
+
description = "GitHub OAuth App Client Secret"
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
# --- リソース名 ---
|
|
390
|
+
|
|
391
|
+
variable "r2_bucket_name" {
|
|
392
|
+
type = string
|
|
393
|
+
default = "${config.r2BucketName}"
|
|
394
|
+
description = "R2 バケット名"
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
variable "pages_project_name" {
|
|
398
|
+
type = string
|
|
399
|
+
default = "${config.pagesProjectName}"
|
|
400
|
+
description = "コンテンツ配信 Pages プロジェクト名"
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
variable "admin_pages_project_name" {
|
|
404
|
+
type = string
|
|
405
|
+
default = "${config.adminPagesProjectName}"
|
|
406
|
+
description = "管理画面 Pages プロジェクト名"
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
variable "r2_public_url" {
|
|
410
|
+
type = string
|
|
411
|
+
default = "${config.r2PublicUrl}"
|
|
412
|
+
description = "R2 公開 URL(例: https://yourdomain.com/storage)"
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
# --- オプション: カスタムドメイン ---
|
|
416
|
+
|
|
417
|
+
variable "production_domain" {
|
|
418
|
+
type = string
|
|
419
|
+
default = ""
|
|
420
|
+
description = "本番カスタムドメイン(空なら *.pages.dev で運用)"
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
variable "admin_domain" {
|
|
424
|
+
type = string
|
|
425
|
+
default = ""
|
|
426
|
+
description = "管理画面カスタムドメイン(空なら *.pages.dev で運用)"
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
variable "staging_domain" {
|
|
430
|
+
type = string
|
|
431
|
+
default = ""
|
|
432
|
+
description = "ステージングカスタムドメイン(空ならブランチプレビュー URL で運用)"
|
|
433
|
+
}
|
|
434
|
+
`;
|
|
435
|
+
}
|
|
436
|
+
export function generateTerraformMain(config) {
|
|
437
|
+
return `# --- R2 バケット ---
|
|
438
|
+
|
|
439
|
+
resource "cloudflare_r2_bucket" "files" {
|
|
440
|
+
account_id = var.cloudflare_account_id
|
|
441
|
+
name = var.r2_bucket_name
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
# --- Pages プロジェクト(コンテンツ配信) ---
|
|
445
|
+
|
|
446
|
+
resource "cloudflare_pages_project" "content" {
|
|
447
|
+
account_id = var.cloudflare_account_id
|
|
448
|
+
name = var.pages_project_name
|
|
449
|
+
production_branch = "main"
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
# --- Pages プロジェクト(管理画面) ---
|
|
453
|
+
|
|
454
|
+
resource "cloudflare_pages_project" "admin" {
|
|
455
|
+
account_id = var.cloudflare_account_id
|
|
456
|
+
name = var.admin_pages_project_name
|
|
457
|
+
production_branch = "admin"
|
|
458
|
+
|
|
459
|
+
deployment_configs {
|
|
460
|
+
production {
|
|
461
|
+
secrets = {
|
|
462
|
+
GITHUB_CLIENT_SECRET = var.github_client_secret
|
|
463
|
+
GITHUB_CLIENT_ID = var.github_client_id
|
|
464
|
+
}
|
|
465
|
+
environment_variables = {
|
|
466
|
+
R2_PUBLIC_URL = var.r2_public_url
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
# --- カスタムドメイン(オプション) ---
|
|
473
|
+
|
|
474
|
+
resource "cloudflare_pages_domain" "production" {
|
|
475
|
+
count = var.production_domain != "" ? 1 : 0
|
|
476
|
+
|
|
477
|
+
account_id = var.cloudflare_account_id
|
|
478
|
+
project_name = cloudflare_pages_project.content.name
|
|
479
|
+
domain = var.production_domain
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
resource "cloudflare_pages_domain" "admin" {
|
|
483
|
+
count = var.admin_domain != "" ? 1 : 0
|
|
484
|
+
|
|
485
|
+
account_id = var.cloudflare_account_id
|
|
486
|
+
project_name = cloudflare_pages_project.admin.name
|
|
487
|
+
domain = var.admin_domain
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
resource "cloudflare_pages_domain" "staging" {
|
|
491
|
+
count = var.staging_domain != "" ? 1 : 0
|
|
492
|
+
|
|
493
|
+
account_id = var.cloudflare_account_id
|
|
494
|
+
project_name = cloudflare_pages_project.content.name
|
|
495
|
+
domain = var.staging_domain
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
# --- Workers(file-upload)---
|
|
499
|
+
# Workers スクリプトは TypeScript のビルドが必要なため、
|
|
500
|
+
# wrangler deploy で個別にデプロイすることを推奨。
|
|
501
|
+
# Terraform で管理する場合は以下のコメントを外し、
|
|
502
|
+
# ビルド済み JS バンドルのパスを workers_script_path に設定する。
|
|
503
|
+
#
|
|
504
|
+
# resource "cloudflare_workers_script" "file_upload" {
|
|
505
|
+
# account_id = var.cloudflare_account_id
|
|
506
|
+
# name = "frelio-file-upload"
|
|
507
|
+
# content = file(var.workers_script_path)
|
|
508
|
+
# module = true
|
|
509
|
+
#
|
|
510
|
+
# r2_bucket_binding {
|
|
511
|
+
# name = "R2"
|
|
512
|
+
# bucket_name = cloudflare_r2_bucket.files.name
|
|
513
|
+
# }
|
|
514
|
+
#
|
|
515
|
+
# plain_text_binding {
|
|
516
|
+
# name = "R2_PUBLIC_URL"
|
|
517
|
+
# text = var.r2_public_url
|
|
518
|
+
# }
|
|
519
|
+
# }
|
|
520
|
+
|
|
521
|
+
# --- Cloudflare Access(ステージング保護)---
|
|
522
|
+
# ステージングサイトにアクセス制限を設ける場合はコメントを外す。
|
|
523
|
+
#
|
|
524
|
+
# resource "cloudflare_zero_trust_access_application" "staging" {
|
|
525
|
+
# account_id = var.cloudflare_account_id
|
|
526
|
+
# name = "Frelio Staging"
|
|
527
|
+
# domain = var.staging_domain
|
|
528
|
+
# type = "self_hosted"
|
|
529
|
+
# session_duration = "24h"
|
|
530
|
+
# auto_redirect_to_identity = false
|
|
531
|
+
# }
|
|
532
|
+
#
|
|
533
|
+
# resource "cloudflare_zero_trust_access_policy" "staging_allow" {
|
|
534
|
+
# account_id = var.cloudflare_account_id
|
|
535
|
+
# application_id = cloudflare_zero_trust_access_application.staging.id
|
|
536
|
+
# name = "Allow members"
|
|
537
|
+
# decision = "allow"
|
|
538
|
+
# precedence = 1
|
|
539
|
+
#
|
|
540
|
+
# include {
|
|
541
|
+
# email = ["admin@example.com"]
|
|
542
|
+
# }
|
|
543
|
+
# }
|
|
544
|
+
`;
|
|
545
|
+
}
|
|
546
|
+
export function generateTerraformOutputs() {
|
|
547
|
+
return `output "r2_bucket_name" {
|
|
548
|
+
value = cloudflare_r2_bucket.files.name
|
|
549
|
+
description = "R2 バケット名"
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
output "content_pages_url" {
|
|
553
|
+
value = "\${cloudflare_pages_project.content.name}.pages.dev"
|
|
554
|
+
description = "コンテンツ配信 Pages URL"
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
output "admin_pages_url" {
|
|
558
|
+
value = "\${cloudflare_pages_project.admin.name}.pages.dev"
|
|
559
|
+
description = "管理画面 Pages URL"
|
|
560
|
+
}
|
|
561
|
+
|
|
562
|
+
output "production_domain" {
|
|
563
|
+
value = length(cloudflare_pages_domain.production) > 0 ? cloudflare_pages_domain.production[0].domain : null
|
|
564
|
+
description = "本番カスタムドメイン"
|
|
565
|
+
}
|
|
566
|
+
|
|
567
|
+
output "admin_domain" {
|
|
568
|
+
value = length(cloudflare_pages_domain.admin) > 0 ? cloudflare_pages_domain.admin[0].domain : null
|
|
569
|
+
description = "管理画面カスタムドメイン"
|
|
570
|
+
}
|
|
571
|
+
`;
|
|
572
|
+
}
|
|
573
|
+
export function generateTerraformTfvarsExample(config) {
|
|
574
|
+
return `# Cloudflare
|
|
575
|
+
cloudflare_account_id = "<YOUR_CLOUDFLARE_ACCOUNT_ID>"
|
|
576
|
+
cloudflare_api_token = "<YOUR_CLOUDFLARE_API_TOKEN>"
|
|
577
|
+
|
|
578
|
+
# GitHub OAuth
|
|
579
|
+
github_client_id = "${config.githubClientId || '<YOUR_GITHUB_CLIENT_ID>'}"
|
|
580
|
+
github_client_secret = "<YOUR_GITHUB_CLIENT_SECRET>"
|
|
581
|
+
|
|
582
|
+
# リソース名
|
|
583
|
+
r2_bucket_name = "${config.r2BucketName}"
|
|
584
|
+
pages_project_name = "${config.pagesProjectName}"
|
|
585
|
+
admin_pages_project_name = "${config.adminPagesProjectName}"
|
|
586
|
+
r2_public_url = "${config.r2PublicUrl || '<YOUR_R2_PUBLIC_URL>'}"
|
|
587
|
+
|
|
588
|
+
# カスタムドメイン(不要なら空文字のまま)
|
|
589
|
+
production_domain = "${config.productionUrl ? new URL(config.productionUrl).hostname : ''}"
|
|
590
|
+
admin_domain = ""
|
|
591
|
+
staging_domain = "${config.stagingDomain}"
|
|
592
|
+
`;
|
|
593
|
+
}
|
|
594
|
+
export function generateTerraformReadme() {
|
|
595
|
+
return `# Terraform - Cloudflare インフラ管理
|
|
596
|
+
|
|
597
|
+
Frelio で使用する Cloudflare リソースを Terraform で管理します。
|
|
598
|
+
|
|
599
|
+
## 前提条件
|
|
600
|
+
|
|
601
|
+
- [Terraform CLI](https://developer.hashicorp.com/terraform/install) >= 1.5.0
|
|
602
|
+
- Cloudflare API トークン(Pages + R2 の操作権限)
|
|
603
|
+
- Cloudflare Dashboard → My Profile → API Tokens → Create Token
|
|
604
|
+
|
|
605
|
+
## セットアップ
|
|
606
|
+
|
|
607
|
+
\`\`\`bash
|
|
608
|
+
cd terraform
|
|
609
|
+
|
|
610
|
+
# 1. 変数ファイルを作成
|
|
611
|
+
cp terraform.tfvars.example terraform.tfvars
|
|
612
|
+
# terraform.tfvars を編集し、実際の値を入力
|
|
613
|
+
|
|
614
|
+
# 2. 初期化
|
|
615
|
+
terraform init
|
|
616
|
+
|
|
617
|
+
# 3. 変更確認
|
|
618
|
+
terraform plan
|
|
619
|
+
|
|
620
|
+
# 4. 適用
|
|
621
|
+
terraform apply
|
|
622
|
+
\`\`\`
|
|
623
|
+
|
|
624
|
+
## 注意事項
|
|
625
|
+
|
|
626
|
+
- \`terraform.tfvars\` にはシークレットが含まれるため **git にコミットしないこと**
|
|
627
|
+
- シークレットは環境変数でも設定可能: \`TF_VAR_cloudflare_api_token\`, \`TF_VAR_github_client_secret\`
|
|
628
|
+
- Pages シークレットは write-only のため、\`terraform plan\` で常に差分が表示されます(正常動作)
|
|
629
|
+
|
|
630
|
+
## 既存リソースのインポート
|
|
631
|
+
|
|
632
|
+
\`frelio init\`(wrangler ベース)で作成済みのリソースがある場合:
|
|
633
|
+
|
|
634
|
+
\`\`\`bash
|
|
635
|
+
# R2 バケット
|
|
636
|
+
terraform import cloudflare_r2_bucket.files <account_id>/<bucket_name>
|
|
637
|
+
|
|
638
|
+
# Pages プロジェクト(コンテンツ配信)
|
|
639
|
+
terraform import cloudflare_pages_project.content <account_id>/<project_name>
|
|
640
|
+
|
|
641
|
+
# Pages プロジェクト(管理画面)
|
|
642
|
+
terraform import cloudflare_pages_project.admin <account_id>/<admin_project_name>
|
|
643
|
+
\`\`\`
|
|
644
|
+
|
|
645
|
+
## リモートステート(チーム運用向け)
|
|
646
|
+
|
|
647
|
+
デフォルトはローカルステートです。チームで運用する場合は \`providers.tf\` の
|
|
648
|
+
S3 バックエンド設定をコメント解除し、Cloudflare R2 をリモートバックエンドとして使用できます。
|
|
649
|
+
`;
|
|
650
|
+
}
|
|
327
651
|
/**
|
|
328
652
|
* ファイルを書き込む(ディレクトリがなければ作成)
|
|
329
653
|
*/
|