@c-time/frelio-cli 1.3.13 → 1.4.1

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.
Files changed (44) hide show
  1. package/README.md +18 -14
  2. package/dist/commands/add-staging.d.ts +2 -3
  3. package/dist/commands/add-staging.js +38 -184
  4. package/dist/commands/init.d.ts +4 -0
  5. package/dist/commands/init.js +164 -373
  6. package/dist/commands/update.d.ts +2 -0
  7. package/dist/commands/update.js +11 -67
  8. package/dist/core/bundle.d.ts +14 -0
  9. package/dist/core/bundle.js +122 -0
  10. package/dist/core/cloudflare.d.ts +26 -0
  11. package/dist/core/cloudflare.js +60 -0
  12. package/dist/core/config.d.ts +26 -0
  13. package/dist/core/config.js +120 -0
  14. package/dist/core/content-structure.d.ts +13 -0
  15. package/dist/core/content-structure.js +13 -0
  16. package/dist/core/file-generators.d.ts +28 -0
  17. package/dist/core/file-generators.js +93 -0
  18. package/dist/core/git-operations.d.ts +15 -0
  19. package/dist/core/git-operations.js +78 -0
  20. package/dist/core/github.d.ts +16 -0
  21. package/dist/core/github.js +43 -0
  22. package/dist/core/index.d.ts +22 -0
  23. package/dist/core/index.js +30 -0
  24. package/dist/core/prerequisites.d.ts +22 -0
  25. package/dist/core/prerequisites.js +107 -0
  26. package/dist/core/status.d.ts +18 -0
  27. package/dist/core/status.js +122 -0
  28. package/dist/core/template-scaffold.d.ts +14 -0
  29. package/dist/core/template-scaffold.js +99 -0
  30. package/dist/core/terraform.d.ts +7 -0
  31. package/dist/core/terraform.js +47 -0
  32. package/dist/core/types.d.ts +48 -0
  33. package/dist/core/types.js +21 -0
  34. package/dist/core/workflows.d.ts +11 -0
  35. package/dist/core/workflows.js +345 -0
  36. package/dist/index.js +2 -4
  37. package/dist/lib/github-release.d.ts +15 -0
  38. package/dist/lib/github-release.js +41 -0
  39. package/dist/lib/initial-content.js +87 -55
  40. package/dist/lib/template-renderer.d.ts +16 -0
  41. package/dist/lib/template-renderer.js +32 -0
  42. package/dist/lib/templates.d.ts +7 -7
  43. package/dist/lib/templates.js +311 -214
  44. package/package.json +2 -3
@@ -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.pagesProjectName}"
48
+ return `name = "${config.adminPagesProjectName}"
45
49
  compatibility_date = "2024-01-01"
46
50
 
47
51
  [[r2_buckets]]
@@ -52,41 +56,6 @@ bucket_name = "${config.r2BucketName}"
52
56
  R2_PUBLIC_URL = "${config.r2PublicUrl}"
53
57
  `;
54
58
  }
55
- export function generateUsersIndex(config) {
56
- const owner = config.ownerUsername;
57
- return JSON.stringify({
58
- users: [
59
- {
60
- githubUsername: owner,
61
- displayName: owner,
62
- isOwner: true,
63
- permissions: {
64
- canViewUsers: true,
65
- canEditUsers: true,
66
- canViewStaging: true,
67
- canEditStaging: true,
68
- canViewContentType: true,
69
- canEditContentType: true,
70
- canViewBuildRecipes: true,
71
- canEditBuildRecipes: true,
72
- canViewTemplates: true,
73
- canEditTemplates: true,
74
- canViewStorage: true,
75
- canEditStorage: true,
76
- canViewDeploy: true,
77
- canEditDeploy: true,
78
- },
79
- },
80
- ],
81
- stagingBranches: [],
82
- }, null, 2);
83
- }
84
- export function generateContentTypesJson() {
85
- return JSON.stringify([], null, 2);
86
- }
87
- export function generateVersionJson() {
88
- return JSON.stringify({ version: '0.0.0' }, null, 2);
89
- }
90
59
  export function generateRedirects() {
91
60
  // 順序重要: 先にマッチしたルールが適用される
92
61
  return [
@@ -132,197 +101,325 @@ export const onRequest: PagesFunction<Env> = async (context) => {
132
101
  }
133
102
  `;
134
103
  }
135
- export function generateViteConfig() {
136
- return `import { defineConfig, type Plugin } from 'vite'
137
- import { resolve } from 'path'
138
- import { spawn, type ChildProcess } from 'child_process'
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
- },
104
+ // --- Terraform generators ---
105
+ export function generateTerraformProviders() {
106
+ return `terraform {
107
+ required_version = ">= 1.5.0"
108
+
109
+ required_providers {
110
+ cloudflare = {
111
+ source = "cloudflare/cloudflare"
112
+ version = "~> 5.0"
113
+ }
166
114
  }
115
+
116
+ # Cloudflare R2 をリモートバックエンドとして使う場合はコメントを外す:
117
+ # backend "s3" {
118
+ # bucket = "terraform-state"
119
+ # key = "frelio/terraform.tfstate"
120
+ # region = "auto"
121
+ # skip_credentials_validation = true
122
+ # skip_metadata_api_check = true
123
+ # skip_region_validation = true
124
+ # skip_requesting_account_id = true
125
+ # skip_s3_checksum = true
126
+ # endpoints = {
127
+ # s3 = "https://<account_id>.r2.cloudflarestorage.com"
128
+ # }
129
+ # }
167
130
  }
168
131
 
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
- }
132
+ provider "cloudflare" {
133
+ api_token = var.cloudflare_api_token
134
+ }
135
+ `;
136
+ }
137
+ export function generateTerraformVariables(config) {
138
+ return `# --- 必須変数 ---
192
139
 
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
- }
140
+ variable "cloudflare_account_id" {
141
+ type = string
142
+ description = "Cloudflare Account ID"
143
+ }
144
+
145
+ variable "cloudflare_api_token" {
146
+ type = string
147
+ sensitive = true
148
+ description = "Cloudflare API Token (Pages + R2 の操作権限が必要)"
149
+ }
150
+
151
+ variable "github_client_id" {
152
+ type = string
153
+ description = "GitHub OAuth App Client ID"
154
+ }
155
+
156
+ variable "github_client_secret" {
157
+ type = string
158
+ sensitive = true
159
+ description = "GitHub OAuth App Client Secret"
160
+ }
161
+
162
+ # --- リソース名 ---
163
+
164
+ variable "r2_bucket_name" {
165
+ type = string
166
+ default = "${config.r2BucketName}"
167
+ description = "R2 バケット名"
168
+ }
169
+
170
+ variable "pages_project_name" {
171
+ type = string
172
+ default = "${config.pagesProjectName}"
173
+ description = "コンテンツ配信 Pages プロジェクト名"
174
+ }
200
175
 
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
- }
176
+ variable "admin_pages_project_name" {
177
+ type = string
178
+ default = "${config.adminPagesProjectName}"
179
+ description = "管理画面 Pages プロジェクト名"
180
+ }
181
+
182
+ variable "r2_public_url" {
183
+ type = string
184
+ default = "${config.r2PublicUrl}"
185
+ description = "R2 公開 URL(例: https://yourdomain.com/storage)"
186
+ }
187
+
188
+ # --- オプション: カスタムドメイン ---
189
+
190
+ variable "production_domain" {
191
+ type = string
192
+ default = ""
193
+ description = "本番カスタムドメイン(空なら *.pages.dev で運用)"
194
+ }
195
+
196
+ variable "admin_domain" {
197
+ type = string
198
+ default = ""
199
+ description = "管理画面カスタムドメイン(空なら *.pages.dev で運用)"
200
+ }
201
+
202
+ variable "staging_domain" {
203
+ type = string
204
+ default = ""
205
+ description = "ステージングカスタムドメイン(空ならブランチプレビュー URL で運用)"
206
+ }
207
+ `;
208
+ }
209
+ export function generateTerraformMain(config) {
210
+ return `# --- R2 バケット ---
211
+
212
+ resource "cloudflare_r2_bucket" "files" {
213
+ account_id = var.cloudflare_account_id
214
+ name = var.r2_bucket_name
215
+ }
216
+
217
+ # --- Pages プロジェクト(コンテンツ配信) ---
218
+
219
+ resource "cloudflare_pages_project" "content" {
220
+ account_id = var.cloudflare_account_id
221
+ name = var.pages_project_name
222
+ production_branch = "main"
223
+ }
224
+
225
+ # --- Pages プロジェクト(管理画面) ---
226
+
227
+ resource "cloudflare_pages_project" "admin" {
228
+ account_id = var.cloudflare_account_id
229
+ name = var.admin_pages_project_name
230
+ production_branch = "admin"
231
+
232
+ deployment_configs {
233
+ production {
234
+ secrets = {
235
+ GITHUB_CLIENT_SECRET = var.github_client_secret
236
+ GITHUB_CLIENT_ID = var.github_client_id
237
+ }
238
+ environment_variables = {
239
+ R2_PUBLIC_URL = var.r2_public_url
213
240
  }
214
- },
241
+ }
215
242
  }
216
243
  }
217
244
 
218
- export default defineConfig(({ command }) => ({
219
- root: 'frelio-data/site/templates',
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
- },
235
- build: {
236
- outDir: resolve(__dirname, 'public'),
237
- emptyOutDir: false,
238
- cssCodeSplit: true,
239
- rollupOptions: {
240
- input: {
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'),
247
- },
248
- output: {
249
- entryFileNames: '[name].js',
250
- assetFileNames: '[name].[ext]',
251
- },
252
- },
253
- },
254
- server: {
255
- open: '/index.html',
256
- },
257
- }))
245
+ # --- カスタムドメイン(オプション) ---
246
+
247
+ resource "cloudflare_pages_domain" "production" {
248
+ count = var.production_domain != "" ? 1 : 0
249
+
250
+ account_id = var.cloudflare_account_id
251
+ project_name = cloudflare_pages_project.content.name
252
+ domain = var.production_domain
253
+ }
254
+
255
+ resource "cloudflare_pages_domain" "admin" {
256
+ count = var.admin_domain != "" ? 1 : 0
257
+
258
+ account_id = var.cloudflare_account_id
259
+ project_name = cloudflare_pages_project.admin.name
260
+ domain = var.admin_domain
261
+ }
262
+
263
+ resource "cloudflare_pages_domain" "staging" {
264
+ count = var.staging_domain != "" ? 1 : 0
265
+
266
+ account_id = var.cloudflare_account_id
267
+ project_name = cloudflare_pages_project.content.name
268
+ domain = var.staging_domain
269
+ }
270
+
271
+ # --- Workers(file-upload)---
272
+ # Workers スクリプトは TypeScript のビルドが必要なため、
273
+ # wrangler deploy で個別にデプロイすることを推奨。
274
+ # Terraform で管理する場合は以下のコメントを外し、
275
+ # ビルド済み JS バンドルのパスを workers_script_path に設定する。
276
+ #
277
+ # resource "cloudflare_workers_script" "file_upload" {
278
+ # account_id = var.cloudflare_account_id
279
+ # name = "frelio-file-upload"
280
+ # content = file(var.workers_script_path)
281
+ # module = true
282
+ #
283
+ # r2_bucket_binding {
284
+ # name = "R2"
285
+ # bucket_name = cloudflare_r2_bucket.files.name
286
+ # }
287
+ #
288
+ # plain_text_binding {
289
+ # name = "R2_PUBLIC_URL"
290
+ # text = var.r2_public_url
291
+ # }
292
+ # }
293
+
294
+ # --- Cloudflare Access(ステージング保護)---
295
+ # ステージングサイトにアクセス制限を設ける場合はコメントを外す。
296
+ #
297
+ # resource "cloudflare_zero_trust_access_application" "staging" {
298
+ # account_id = var.cloudflare_account_id
299
+ # name = "Frelio Staging"
300
+ # domain = var.staging_domain
301
+ # type = "self_hosted"
302
+ # session_duration = "24h"
303
+ # auto_redirect_to_identity = false
304
+ # }
305
+ #
306
+ # resource "cloudflare_zero_trust_access_policy" "staging_allow" {
307
+ # account_id = var.cloudflare_account_id
308
+ # application_id = cloudflare_zero_trust_access_application.staging.id
309
+ # name = "Allow members"
310
+ # decision = "allow"
311
+ # precedence = 1
312
+ #
313
+ # include {
314
+ # email = ["admin@example.com"]
315
+ # }
316
+ # }
258
317
  `;
259
318
  }
260
- export function generatePackageJson(config) {
261
- return JSON.stringify({
262
- name: config.pagesProjectName,
263
- private: true,
264
- type: 'module',
265
- scripts: {
266
- dev: 'vite',
267
- build: 'vite build',
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',
280
- },
281
- devDependencies: {
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',
289
- sass: '^1.80.0',
290
- tsx: '^4.0.0',
291
- typescript: '^5.7.0',
292
- vite: '^6.0.0',
293
- zod: '^3.25.0',
294
- },
295
- }, null, 2);
319
+ export function generateTerraformOutputs() {
320
+ return `output "r2_bucket_name" {
321
+ value = cloudflare_r2_bucket.files.name
322
+ description = "R2 バケット名"
296
323
  }
297
- export function generateTsConfig() {
298
- return JSON.stringify({
299
- compilerOptions: {
300
- target: 'ES2022',
301
- module: 'ESNext',
302
- moduleResolution: 'bundler',
303
- strict: true,
304
- esModuleInterop: true,
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);
324
+
325
+ output "content_pages_url" {
326
+ value = "\${cloudflare_pages_project.content.name}.pages.dev"
327
+ description = "コンテンツ配信 Pages URL"
311
328
  }
312
- export function generateTsConfigNode() {
313
- return JSON.stringify({
314
- compilerOptions: {
315
- target: 'ES2022',
316
- module: 'NodeNext',
317
- moduleResolution: 'NodeNext',
318
- strict: true,
319
- esModuleInterop: true,
320
- skipLibCheck: true,
321
- resolveJsonModule: true,
322
- outDir: 'dist',
323
- },
324
- include: ['scripts/**/*.ts'],
325
- }, null, 2);
329
+
330
+ output "admin_pages_url" {
331
+ value = "\${cloudflare_pages_project.admin.name}.pages.dev"
332
+ description = "管理画面 Pages URL"
333
+ }
334
+
335
+ output "production_domain" {
336
+ value = length(cloudflare_pages_domain.production) > 0 ? cloudflare_pages_domain.production[0].domain : null
337
+ description = "本番カスタムドメイン"
338
+ }
339
+
340
+ output "admin_domain" {
341
+ value = length(cloudflare_pages_domain.admin) > 0 ? cloudflare_pages_domain.admin[0].domain : null
342
+ description = "管理画面カスタムドメイン"
343
+ }
344
+ `;
345
+ }
346
+ export function generateTerraformTfvarsExample(config) {
347
+ return `# Cloudflare
348
+ cloudflare_account_id = "<YOUR_CLOUDFLARE_ACCOUNT_ID>"
349
+ cloudflare_api_token = "<YOUR_CLOUDFLARE_API_TOKEN>"
350
+
351
+ # GitHub OAuth
352
+ github_client_id = "${config.githubClientId || '<YOUR_GITHUB_CLIENT_ID>'}"
353
+ github_client_secret = "<YOUR_GITHUB_CLIENT_SECRET>"
354
+
355
+ # リソース名
356
+ r2_bucket_name = "${config.r2BucketName}"
357
+ pages_project_name = "${config.pagesProjectName}"
358
+ admin_pages_project_name = "${config.adminPagesProjectName}"
359
+ r2_public_url = "${config.r2PublicUrl || '<YOUR_R2_PUBLIC_URL>'}"
360
+
361
+ # カスタムドメイン(不要なら空文字のまま)
362
+ production_domain = "${config.productionUrl ? new URL(config.productionUrl).hostname : ''}"
363
+ admin_domain = ""
364
+ staging_domain = "${config.stagingDomain}"
365
+ `;
366
+ }
367
+ export function generateTerraformReadme() {
368
+ return `# Terraform - Cloudflare インフラ管理
369
+
370
+ Frelio で使用する Cloudflare リソースを Terraform で管理します。
371
+
372
+ ## 前提条件
373
+
374
+ - [Terraform CLI](https://developer.hashicorp.com/terraform/install) >= 1.5.0
375
+ - Cloudflare API トークン(Pages + R2 の操作権限)
376
+ - Cloudflare Dashboard → My Profile → API Tokens → Create Token
377
+
378
+ ## セットアップ
379
+
380
+ \`\`\`bash
381
+ cd terraform
382
+
383
+ # 1. 変数ファイルを作成
384
+ cp terraform.tfvars.example terraform.tfvars
385
+ # terraform.tfvars を編集し、実際の値を入力
386
+
387
+ # 2. 初期化
388
+ terraform init
389
+
390
+ # 3. 変更確認
391
+ terraform plan
392
+
393
+ # 4. 適用
394
+ terraform apply
395
+ \`\`\`
396
+
397
+ ## 注意事項
398
+
399
+ - \`terraform.tfvars\` にはシークレットが含まれるため **git にコミットしないこと**
400
+ - シークレットは環境変数でも設定可能: \`TF_VAR_cloudflare_api_token\`, \`TF_VAR_github_client_secret\`
401
+ - Pages シークレットは write-only のため、\`terraform plan\` で常に差分が表示されます(正常動作)
402
+
403
+ ## 既存リソースのインポート
404
+
405
+ \`frelio init\`(wrangler ベース)で作成済みのリソースがある場合:
406
+
407
+ \`\`\`bash
408
+ # R2 バケット
409
+ terraform import cloudflare_r2_bucket.files <account_id>/<bucket_name>
410
+
411
+ # Pages プロジェクト(コンテンツ配信)
412
+ terraform import cloudflare_pages_project.content <account_id>/<project_name>
413
+
414
+ # Pages プロジェクト(管理画面)
415
+ terraform import cloudflare_pages_project.admin <account_id>/<admin_project_name>
416
+ \`\`\`
417
+
418
+ ## リモートステート(チーム運用向け)
419
+
420
+ デフォルトはローカルステートです。チームで運用する場合は \`providers.tf\` の
421
+ S3 バックエンド設定をコメント解除し、Cloudflare R2 をリモートバックエンドとして使用できます。
422
+ `;
326
423
  }
327
424
  /**
328
425
  * ファイルを書き込む(ディレクトリがなければ作成)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@c-time/frelio-cli",
3
- "version": "1.3.13",
3
+ "version": "1.4.1",
4
4
  "description": "Frelio CMS setup CLI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -8,8 +8,7 @@
8
8
  "frelio": "./dist/index.js"
9
9
  },
10
10
  "files": [
11
- "dist",
12
- "templates"
11
+ "dist"
13
12
  ],
14
13
  "publishConfig": {
15
14
  "access": "public"