diff --git a/.changeset/four-elephants-count.md b/.changeset/four-elephants-count.md new file mode 100644 index 00000000..036b01ee --- /dev/null +++ b/.changeset/four-elephants-count.md @@ -0,0 +1,5 @@ +--- +"@skeet-framework/cli": patch +--- + +Update - skeet init/ai/check diff --git a/packages/cli/skeet-cloud.config.json b/packages/cli/skeet-cloud.config.json index 1036c5bf..74058f85 100644 --- a/packages/cli/skeet-cloud.config.json +++ b/packages/cli/skeet-cloud.config.json @@ -9,7 +9,7 @@ "nsDomain": "your-nameserver.com", "lbDomain": "loadbalancer.your-app-url.com", "hasLoadBalancer": false, - "cloudStatus": "NOT_CREATED" + "cloudStatus": "PROJECT_CREATED" }, "cloudRun": { "name": "skeet-nextjs-graphql-graphql", @@ -138,19 +138,14 @@ "securityPolicyName": "skeet-sql-armor" } ], - "secretKey": [ - "TEST_KEY" - ], + "secretKey": ["TEST_KEY"], "ai": { "lang": "en", "ais": [ { "name": "Gemini", - "availableModels": [ - "gemini-1.0-pro", - "gemini-1.0-pro-vision" - ] + "availableModels": ["gemini-1.0-pro", "gemini-1.0-pro-vision"] } ] } -} \ No newline at end of file +} diff --git a/packages/cli/src/cli/ai/ai.ts b/packages/cli/src/cli/ai/ai.ts index a3988962..a141f358 100644 --- a/packages/cli/src/cli/ai/ai.ts +++ b/packages/cli/src/cli/ai/ai.ts @@ -6,6 +6,8 @@ import { SkeetAIOptions } from '.' import { AIType, chat } from '@skeet-framework/ai' import { modeSelect } from './modeSelect' import { skeetMode } from './mode/skeetMode' +import { readOrCreateConfig } from '@/config/readOrCreateConfig' +import { skeetAiPromptV } from './skeetPromptV' export async function promptUser( options: SkeetAIOptions, @@ -17,6 +19,7 @@ export async function promptUser( } console.log('\n') + const userInput = await inquirer.prompt([ { type: 'input', @@ -52,7 +55,8 @@ export async function promptUser( return } - const skeetPrompt = skeetAiPrompt('en') + const config = await readOrCreateConfig() + const skeetPrompt = await skeetAiPromptV(config.lang) await chat( skeetPrompt.context, skeetPrompt.examples, diff --git a/packages/cli/src/cli/ai/index.ts b/packages/cli/src/cli/ai/index.ts index 651c7353..898a1f6b 100644 --- a/packages/cli/src/cli/ai/index.ts +++ b/packages/cli/src/cli/ai/index.ts @@ -2,11 +2,10 @@ import { program } from '@/index' import { promptUser } from './ai' import chalk from 'chalk' import { AIType } from '@skeet-framework/ai' -import { importConfig } from '@/lib/files/importConfig' import { AiLog } from './aiLog' import { validEnv } from './validEnv' -import { validateAiConfig } from './validateAiConfig' import { modeSelect } from './modeSelect' +import { readOrCreateConfig } from '@/config/readOrCreateConfig' export type SkeetAIOptions = { ai: AIType @@ -15,15 +14,14 @@ export type SkeetAIOptions = { export const aiCommands = () => { program .command('ai') - .description('AI Playground') - .option('-g, --gemini', 'Gemini') - .option('-o, --openai', 'OpenAI') - .option('-c, --claude', 'Claude') - .option('--mode', 'Mode') + .description('Call Skeet AI Assistant') + .option('-g, --gemini', 'Use Gemini - default') + .option('-o, --openai', 'Use OpenAI') + .option('-c, --claude', 'Use Claude') + .option('--mode', 'Call Mode Select Prompt') .action(async (options) => { - await validateAiConfig() - const { ai } = await importConfig() - const lang = ai.lang as 'en' | 'ja' + const config = await readOrCreateConfig() + const lang = config.lang as 'en' | 'ja' const logger = new AiLog(lang) let aiType = 'Gemini' if (options.claude) { diff --git a/packages/cli/src/cli/ai/skeetPrompt.ts b/packages/cli/src/cli/ai/skeetPrompt.ts index 9a8ffa66..a62e6359 100644 --- a/packages/cli/src/cli/ai/skeetPrompt.ts +++ b/packages/cli/src/cli/ai/skeetPrompt.ts @@ -1,393 +1,48 @@ import { Example } from '@skeet-framework/ai' -import { LINKS } from '@/config/links' -import { CLI_HELP } from '@/lib/cliHelp' -export const skeetAiPrompt = (lang: string): Example => { +export const skeetAiPrompt = async (): Promise => { return { - context: `You are a senior engineer specialized in assisting developers. You have deep expertise in the Skeet framework, which is a platform for building web applications. Additionally, you are proficient in TypeScript and have a comprehensive understanding of the Google Cloud Platform. You are also familiar with the Firebase Emulator Suite. You are a member of the Skeet framework community and have been helping developers with their questions. - Reference: Skeet Framework - https://skeet.dev - You must help the developer with the following CLI commands: - Skeet CLI: - ${CLI_HELP} - You must output with the language of the developer's choice. - : ${lang} - You must use @skeet-framework/firestore to operate Firestore Data/Models. - @skeet-framework/firestore:\n${skeetFirestore} + context: `You are a senior engineer specialized in assisting developers. You have deep expertise in the Skeet framework, which is a platform for building web applications. Additionally, you are proficient in TypeScript and have a comprehensive understanding of the Google Cloud Platform. You are also familiar with the Firebase Emulator Suite. +To successfully set up Skeet Cloud, users must progress through a series of seven steps, each associated with a specific status indicated in the ./skeet-cloud.config.json file. This file also contains the app.name, app.projectId, app.fbProjectId which is crucial for naming the Google Cloud and Firebase projects. Below is a guide detailing each step and the actions required to reach the next status: +1. NOT_CREATED - Immediately after creating your project, initiate the setup by creating a Google Cloud Project and a Firebase Project. Both should have the name specified in the app.name field of your ./skeet-cloud.config.json file. Detailed instructions for this step can be found at: https://skeet.dev/en/doc/skeet-firestore/setup/ +2. PROJECT_CREATED - Once the projects are created, proceed to set up your first Firebase Functions by executing the command:\n\n $ skeet deploy +3. FUNCTIONS_CREATED - After setting up Firebase Functions, the next step is to configure Github Actions for continuous integration and delivery. This is also done using the same command: $ skeet init --repo +4. GITHUB_ACTIONS_CREATED - With Github Actions configured, the following task is to establish a VPN to securely connect your resources. Use the command: $ skeet init --vpn +5. VPN_CREATED - After the VPN setup, the next milestone involves setting up Cloud SQL to manage your databases. This is accomplished with: $ skeet init + +It's important to follow these steps in order to properly set up and configure your Skeet Cloud environment. Ensure that you consult the provided documentation and use the specified commands as you progress through each status. +You will get a cloud status and answer what you need to do next. +You must use line breaks before and after the line if it is a link of commands. +You must say the welcome message at the beginning. +You must tell the user the user's current cloud status. +You must provide the user with the next steps to take based on their current status. `, examples: [ { - input: 'How to operate Database?', + input: 'NOT_CREATED', output: - 'You can operate Database by using the Skeet CLI command `$ skeet db`. For example, you can create a new migration by using `$ skeet db migrate ` command. You can also use $ skeet ai and $ prisma to call the Skeet AI Prisma Mode.', + 'Hello! Welcome to skeet framework AI playground!\nYour cloud status is NOT_CREATED. \n\nThe next step is to set up your Google Cloud Project. Please refer to the documentation at:\n\n https://skeet.dev/en/doc/skeet-firestore/setup/\n\n Once you have created your projects, \nPlease run the command: $ skeet init', }, { - input: 'Give an example of what the Skeet framework could be used for?', + input: 'PROJECT_CREATED', output: - 'The Skeet framework can be used for a variety of web applications, such as building a Chatbot', + 'Nice work!Your cloud status is PROJECT_CREATED.\nYou have successfully created your Google Cloud and Firebase Projects. \nThe next step is to set up your first Firebase Functions. \nPlease run the command:\n\n $ skeet deploy', }, { - input: - 'I got a credentials error while trying to use the Skeet framework. What should I do?', + input: 'FUNCTIONS_CREATED', output: - 'The Skeet framework uses Google Cloud. You might need to login using `gcloud auth application-default login` to use the framework.', + 'Great job!Your cloud status is FUNCTIONS_CREATED.\nYour Firebase Functions are up and running. The next task is to configure Github Actions for continuous integration and delivery. \nPlease run the command:\n\n $ skeet init --repo', }, { - input: 'How do I get in touch with the Skeet framework community?', + input: 'GITHUB_ACTIONS_CREATED', output: - 'Discord Link: https://discord.gg/nfZYMXgZ for help about the Skeet framework.', + 'Well done!Your cloud status is GITHUB_ACTIONS_CREATED.\n Github Actions are now configured. \nThe next step is to establish a VPN to securely connect your resources. \nPlease run the command:\n\n $ skeet init --vpn', }, { - input: 'How do I get help about the Skeet framework?', - output: 'type _$ skeet ai_ for help about the Skeet framework.', - }, - { - input: - 'Skeetフレームワークをインストールするにはどうすればいいですか?', - output: - 'Skeetフレームワークをインストールするには、以下のコマンドを実行します:\n\n```bash\n$ pnpm add -g @skeet-framework/cli\n$ pnpm add -g firebase-tools\n```', - }, - { - input: 'Skeet に関するリンクや公式ホームページは?', - output: '- 公式ホームページ https://skeet.dev', - }, - { - input: 'can I get the document link?', - output: 'Official Document: https://skeet.dev', - }, - { - input: 'Skeet App を作成する方法は?', - output: - '- $ skeet create コマンドを実行することで、Skeet App を作成できます。', - }, - { - input: 'Skeet App をローカルで起動する方法は?', - output: - '- $ skeet s コマンドを実行することで、Skeet App をローカルで起動できます。また、$ skeet docker psql コマンドを実行することで、PostgreSQL をローカルで起動できます。-b オプションを使用することで、バックエンドのみ起動できます。-f オプションを使用することで、Firebase Functions のみ起動できます。-w オプションを使用することで、フロントエンドのみ起動できます。', - }, - { - input: 'Skeet App のフロントエンドのみを起動する方法は?', + input: 'VPN_CREATED', output: - '- $ skeet s -w コマンドを実行することで、Skeet App のフロントエンドのみを起動できます。', - }, - { - input: 'Skeet WhatApp のバックエンドのみを起動する方法は?', - output: - '- $ skeet s -b コマンドを実行することで、Skeet App のバックエンドのみを起動できます。', - }, - { - input: 'Firestore のモデルを扱うには?', - output: `Firestore のモデルを扱うには、@skeet-framework/firestore を使用します。${skeetFirestore}`, - }, - { - input: 'Firestoreにデータを追加するには?', - output: skeetFirestoreAdd, - }, - { - input: 'Firestoreに複数のデータを追加するには?', - output: skeetFirestoreAdds, - }, - { - input: 'Firestoreのデータを取得するには?', - output: skeetFirestoreGet, - }, - { - input: 'Firestoreのデータを検索するには?', - output: skeetFirestoreQuery, - }, - { - input: 'Firestoreのデータを更新するには?', - output: skeetFirestoreUpdate, - }, - { - input: 'Firestoreのデータを削除するには?', - output: skeetFirestoreDelete, - }, - { - input: '言語設定を変更するには?', - output: - '言語設定を変更するには、./skeet-cloud.config.json を編集します。ai の lang プロパティを変更します。例:\n\n```json\n{\n "ai": {\n "lang": "ja"\n }\n}\n```\n現在使用できる言語:"ja", "de", "fr", "zh", "nl", "eo", "id", "it", "ko", "ru", "vi", "es", "pt", "ar"', - }, - { - input: '新しいモデルを追加するには?', - output: - '$ skeet ai コマンドを実行後、 $ prisma モードでSQLのモデル作成をすることができます。Firestoreの場合は $ firestore モードでNoSQLのモデル作成をすることができます。', - }, - { - input: 'Discord Bot を作成するには?', - output: `Discord Bot を作成するには以下のリンクを参考にしてください。\n\n- [Discord Bot を作成する](${LINKS.DISCORD_BOT_JA})`, - }, - { - input: 'Stripe App を作成するには?', - output: `Stripe App を作成するには以下のリンクを参考にしてください。\n\n- [Stripe App を作成する](${LINKS.STRIPE_APP_JA})`, - }, - { - input: 'How to create a Discord Bot?', - output: `You can create a Discord Bot by following the link below.\n\n- [How to create a Discord Bot](${LINKS.DISCORD_BOT_EN})`, - }, - { - input: 'How to create a Stripe App?', - output: `You can create a Stripe App by following the link below.\n\n- [How to create a Stripe App](${LINKS.STRIPE_APP_EN})`, + 'Congratulations 🎊 Your are all set!\nYour Skeet Cloud is now operational, and you have completed all tutorials. Well done!\nPlease ask me anything by\n\n $ skeet ai', }, ], } } - -const skeetFirestoreAdd = `## コレクションアイテムの追加 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { add } from '@skeet-framework/firestore' - -const db = admin.firestore() -const data: User = { - name: 'John Doe', - age: 30, -} - -async function run() { - try { - const path = 'Users' - const docRef = await add(db, path, data) - console.log(\`ID付きのドキュメントが追加されました: \${docRef.id}\`) - } catch (error) { - console.error(\`ドキュメントの追加エラー: \${error}\`) - } -}` - -const skeetFirestoreAdds = `## 複数のコレクションアイテムの追加 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { adds } from '@skeet-framework/firestore' - -const db = admin.firestore() -const users: User[] = [ - { name: 'John Doe', age: 30 }, - { name: 'Jane Smith', age: 25 }, - // ... 他のユーザー ... -] - -async function run() { - try { - const path = 'Users' - const results = await adds(db, path, users) - console.log( - \`\${users.length} 人のユーザーが \${results.length} バッチで追加されました。\` - ) - } catch (error) { - console.error(\`ドキュメントの追加エラー: \${error}\`) - } -} - -run() -\`\`\`` - -const skeetFirestoreGet = `## コレクションアイテムの取得 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { get } from '@skeet-framework/firestore' - -const db = admin.firestore() -async function run() { - try { - const path = 'Users' - const docId = 'user123' - const user = await get(db, path, docId) - console.log(\`ユーザー情報: \${JSON.stringify(user)}\`) - } catch (error) { - console.error(\`ドキュメントの取得エラー: \${error}\`) - } -} - -run() -\`\`\`` - -const skeetFirestoreQuery = `## コレクションアイテムのクエリ - -\`\`\`typescript -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { query } from '@skeet-framework/firestore' - -const db = admin.firestore() - -// 25歳以上のユーザーを取得するシンプルなクエリ -const simpleConditions: QueryCondition[] = [ - { field: 'age', operator: '>', value: 25 }, -] - -// 名前順に並べ替えた25歳以上のユーザーを取得する高度なクエリ -const advancedConditions: QueryCondition[] = [ - { field: 'age', operator: '>', value: 25 }, - { field: 'name', orderDirection: 'asc' }, -] - -// 25歳以上のユーザーを取得し、結果を5つに制限するクエリ -const limitedConditions: QueryCondition[] = [ - { field: 'age', operator: '>', value: 25 }, - { limit: 5 }, -] - -async function run() { - try { - const path = 'Users' - - // シンプルな条件を使用して取得 - const usersByAge = await query(db, path, simpleConditions) - console.log(\`25歳以上のユーザーが \${usersByAge.length} 人見つかりました。\`) - - // 高度な条件を使用して取得 - const orderedUsers = await query(db, path, advancedConditions) - console.log( - \`名前で昇順に並べた25歳以上のユーザーが \${orderedUsers.length} 人見つかりました。\` - ) - - // 制限付きの条件を使用して取得 - const limitedUsers = await query(db, path, limitedConditions) - console.log( - \`25歳以上のユーザーが \${limitedUsers.length} 人見つかりました(制限: 5人)。\` - ) - } catch (error) { - console.error(\`コレクションのクエリエラー: \${error}\`) - } -} - -run() -\`\`\`` - -const skeetFirestoreUpdate = `## コレクションアイテムの更新 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { update } from '@skeet-framework/firestore' - -const db = admin.firestore() -const updatedData: User = { - age: 38, -} - -async function run() { - try { - const path = 'Users' - const docId = '123456' - const success = await update(db, path, docId, updatedData) - if (success) { - console.log(\`ID \${docId} のドキュメントが正常に更新されました。\`) - } - } catch (error) { - console.error(\`ドキュメントの更新エラー: \${error}\`) - } -} - -run() -\`\`\`` - -const skeetFirestoreDelete = `## コレクションアイテムの削除 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { del } from '@skeet-framework/firestore' - -async function run() { - try { - const path = 'Users' - const docId = '123456' - const success = await del(db, path, docId) - if (success) { - console.log(\`ID \${docId} のドキュメントが正常に削除されました。\`) - } - } catch (error) { - console.error(\`ドキュメントの削除エラー: \${error}\`) - } -} - -run() -\`\`\`` - -const skeetFirestore = `# Skeet Framework プラグイン - Firestore - -Skeet Firestore プラグインは、Firestore コンバーターを使用した CRUD Firestore 操作をサポートします。 -型安全性があり、使いやすく、テストもしやすいです。 - -# インストール - -\`\`\`bash -$ pnpm add @skeet-framework/firestore -\`\`\` - -# Skeet Firestore Type ドキュメント - -- [Skeet Firestore TypeDoc](https://elsoul.github.io/skeet-firestore/) - -# 特徴 - -すべての CRUD 操作は Firestore コンバーターをサポートします。 -createdAt および updatedAt は Firebase ServerTimestamp で自動的にドキュメントに追加されます。 - -- [x] コレクションアイテムの追加 -- [x] 複数のコレクションアイテムの追加 -- [x] コレクションアイテムの取得 -- [x] コレクションアイテムのクエリ -- [x] コレクションアイテムの更新 -- [x] コレクションアイテムの削除 - -# 使用方法 - -## 初期化 - -\`\`\`typescript -import * as admin from 'firebase-admin' - -admin.initializeApp() -\`\`\` - -または - -\`\`\`typescript -import * as firebase from 'firebase/app' -import 'firebase/firestore' - -firebase.initializeApp({ - // プロジェクトの設定 -}) -\`\`\` - - - -run() -\`\`\` - -## 複数のコレクションアイテムの追加 - -\`\`\`ts -import { firestore } from 'firebase-admin' -import * as admin from 'firebase-admin' -import { adds } from '@skeet-framework/firestore' - -const db = admin.firestore() -const users: User[] = [ - { name: 'John Doe', age: 30 }, - { name: 'Jane Smith', age: 25 }, - // ... 他のユーザー ... -] - -async function run() { - try { - const path = 'Users' - const results = await adds(db, path, users) - console.log( - \`\${users.length} 人のユーザーが \${results.length} バッチで追加されました。\` - ) - } catch (error) { - console.error(\`ドキュメントの追加エラー: \${error}\`) - } -} - -run() -\`\`\`` diff --git a/packages/cli/src/cli/ai/skeetPromptV.ts b/packages/cli/src/cli/ai/skeetPromptV.ts new file mode 100644 index 00000000..9156c3ca --- /dev/null +++ b/packages/cli/src/cli/ai/skeetPromptV.ts @@ -0,0 +1,400 @@ +import { Example } from '@skeet-framework/ai' +import { LINKS } from '@/config/links' +import { CLI_HELP } from '@/lib/cliHelp' +import { readOrCreateConfig } from '@/config/readOrCreateConfig' + +export const skeetAiPromptV = async (lang: string): Promise => { + const config = await readOrCreateConfig() + return { + context: `You are a senior engineer specialized in assisting developers. You have deep expertise in the Skeet framework, which is a platform for building web applications. Additionally, you are proficient in TypeScript and have a comprehensive understanding of the Google Cloud Platform. You are also familiar with the Firebase Emulator Suite. +Reference: Skeet Framework - https://skeet.dev +You must help the developer with the following CLI commands: +Skeet CLI: +${CLI_HELP} +You must output with the language of the developer's choice. +: ${lang} +You must use @skeet-framework/firestore to operate Firestore Data/Models. +@skeet-framework/firestore:\n${skeetFirestore} +To successfully set up Skeet Cloud, users must progress through a series of seven steps, each associated with a specific status indicated in the ./skeet-cloud.config.json file. This file also contains the app.name, app.projectId, app.fbProjectId which is crucial for naming the Google Cloud and Firebase projects. Below is a guide detailing each step and the actions required to reach the next status: +1. NOT_CREATED - Immediately after creating your project, initiate the setup by creating a Google Cloud Project and a Firebase Project. Both should have the name specified in the app.name field of your ./skeet-cloud.config.json file. Detailed instructions for this step can be found at: https://skeet.dev/en/doc/skeet-firestore/setup/ +2. PROJECT_CREATED - Once the projects are created, proceed to set up your first Firebase Functions by executing the command: $ skeet init +3. FUNCTIONS_CREATED - After setting up Firebase Functions, the next step is to configure Github Actions for continuous integration and delivery. This is also done using the same command: $ skeet init +4. GITHUB_ACTIONS_CREATED - With Github Actions configured, the following task is to establish a VPN to securely connect your resources. Use the command: $ skeet init +5. VPN_CREATED - After the VPN setup, the next milestone involves setting up Cloud SQL to manage your databases. This is accomplished with: $ skeet init +6. SQL_CREATED - Having Cloud SQL ready, it's time to synchronize the routing configurations to update the load balancer, ensuring efficient traffic management. Execute the following command: $ skeet init +7. RUNNING - Reaching this status signifies the successful completion of the Skeet Cloud setup. Your Skeet Cloud is now operational, and you've completed all tutorials. + +It's important to follow these steps in order to properly set up and configure your Skeet Cloud environment. Ensure that you consult the provided documentation and use the specified commands as you progress through each status. +Here's User's Cloud Status: ${config.app.cloudStatus} + `, + examples: [ + { + input: 'How to operate Database?', + output: + 'You can operate Database by using the Skeet CLI command `$ skeet db`. For example, you can create a new migration by using `$ skeet db dev` command. You can also use $ skeet ai and select the prisma to call the Skeet AI Prisma Mode.', + }, + { + input: 'Give an example of what the Skeet framework could be used for?', + output: + 'The Skeet framework can be used for a variety of web applications, such as building a Chatbot', + }, + { + input: + 'I got a credentials error while trying to use the Skeet framework. What should I do?', + output: + 'The Skeet framework uses Google Cloud. You might need to login using `gcloud auth application-default login` to use the framework.', + }, + { + input: 'How do I get in touch with the Skeet framework community?', + output: + 'Discord Link: https://discord.gg/nfZYMXgZ for help about the Skeet framework.', + }, + { + input: 'How do I get help about the Skeet framework?', + output: 'type _$ skeet ai_ for help about the Skeet framework.', + }, + { + input: + 'Skeetフレームワークをインストールするにはどうすればいいですか?', + output: + 'Skeetフレームワークをインストールするには、以下のコマンドを実行します:\n\n```bash\n$ pnpm add -g @skeet-framework/cli\n$ pnpm add -g firebase-tools\n```', + }, + { + input: 'Skeet に関するリンクや公式ホームページは?', + output: '- 公式ホームページ https://skeet.dev', + }, + { + input: 'can I get the document link?', + output: 'Official Document: https://skeet.dev', + }, + { + input: 'Skeet App を作成する方法は?', + output: + '- $ skeet create コマンドを実行することで、Skeet App を作成できます。', + }, + { + input: 'Skeet App をローカルで起動する方法は?', + output: + '- $ skeet s コマンドを実行することで、Skeet App をローカルで起動できます。また、$ skeet docker psql コマンドを実行することで、PostgreSQL をローカルで起動できます。-b オプションを使用することで、バックエンドのみ起動できます。-f オプションを使用することで、Firebase Functions のみ起動できます。-w オプションを使用することで、フロントエンドのみ起動できます。', + }, + { + input: 'Skeet App のフロントエンドのみを起動する方法は?', + output: + '- $ skeet s -w コマンドを実行することで、Skeet App のフロントエンドのみを起動できます。', + }, + { + input: 'Skeet WhatApp のバックエンドのみを起動する方法は?', + output: + '- $ skeet s -b コマンドを実行することで、Skeet App のバックエンドのみを起動できます。', + }, + { + input: 'Firestore のモデルを扱うには?', + output: `Firestore のモデルを扱うには、@skeet-framework/firestore を使用します。${skeetFirestore}`, + }, + { + input: 'Firestoreにデータを追加するには?', + output: skeetFirestoreAdd, + }, + { + input: 'Firestoreに複数のデータを追加するには?', + output: skeetFirestoreAdds, + }, + { + input: 'Firestoreのデータを取得するには?', + output: skeetFirestoreGet, + }, + { + input: 'Firestoreのデータを検索するには?', + output: skeetFirestoreQuery, + }, + { + input: 'Firestoreのデータを更新するには?', + output: skeetFirestoreUpdate, + }, + { + input: 'Firestoreのデータを削除するには?', + output: skeetFirestoreDelete, + }, + { + input: '言語設定を変更するには?', + output: + '言語設定を変更するには、./skeet-cloud.config.json を編集します。ai の lang プロパティを変更します。例:\n\n```json\n{\n "ai": {\n "lang": "ja"\n }\n}\n```\n現在使用できる言語:"ja", "de", "fr", "zh", "nl", "eo", "id", "it", "ko", "ru", "vi", "es", "pt", "ar"', + }, + { + input: '新しいモデルを追加するには?', + output: + '$ skeet ai コマンドを実行後、 $ prisma モードでSQLのモデル作成をすることができます。Firestoreの場合は $ firestore モードでNoSQLのモデル作成をすることができます。', + }, + { + input: 'Discord Bot を作成するには?', + output: `Discord Bot を作成するには以下のリンクを参考にしてください。\n\n- [Discord Bot を作成する](${LINKS.DISCORD_BOT_JA})`, + }, + { + input: 'Stripe App を作成するには?', + output: `Stripe App を作成するには以下のリンクを参考にしてください。\n\n- [Stripe App を作成する](${LINKS.STRIPE_APP_JA})`, + }, + { + input: 'How to create a Discord Bot?', + output: `You can create a Discord Bot by following the link below.\n\n- [How to create a Discord Bot](${LINKS.DISCORD_BOT_EN})`, + }, + { + input: 'How to create a Stripe App?', + output: `You can create a Stripe App by following the link below.\n\n- [How to create a Stripe App](${LINKS.STRIPE_APP_EN})`, + }, + ], + } +} + +const skeetFirestoreAdd = `## コレクションアイテムの追加 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { add } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) +const data: User = { + name: 'John Doe', + age: 30, +} + +async function run() { + try { + const path = 'Users' + const docRef = await add(db, path, data) + console.log(\`ID付きのドキュメントが追加されました: \${docRef.id}\`) + } catch (error) { + console.error(\`ドキュメントの追加エラー: \${error}\`) + } +}` + +const skeetFirestoreAdds = `## 複数のコレクションアイテムの追加 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { adds } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) +const users: User[] = [ + { name: 'John Doe', age: 30 }, + { name: 'Jane Smith', age: 25 }, + // ... 他のユーザー ... +] + +async function run() { + try { + const path = 'Users' + const results = await adds(db, path, users) + console.log( + \`\${users.length} 人のユーザーが \${results.length} バッチで追加されました。\` + ) + } catch (error) { + console.error(\`ドキュメントの追加エラー: \${error}\`) + } +} + +run() +\`\`\`` + +const skeetFirestoreGet = `## コレクションアイテムの取得 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { get } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) +async function run() { + try { + const path = 'Users' + const docId = 'user123' + const user = await get(db, path, docId) + console.log(\`ユーザー情報: \${JSON.stringify(user)}\`) + } catch (error) { + console.error(\`ドキュメントの取得エラー: \${error}\`) + } +} + +run() +\`\`\`` + +const skeetFirestoreQuery = `## コレクションアイテムのクエリ + +\`\`\`typescript +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { query } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) + +// 25歳以上のユーザーを取得するシンプルなクエリ +const simpleConditions: QueryCondition[] = [ + { field: 'age', operator: '>', value: 25 }, +] + +// 名前順に並べ替えた25歳以上のユーザーを取得する高度なクエリ +const advancedConditions: QueryCondition[] = [ + { field: 'age', operator: '>', value: 25 }, + { field: 'name', orderDirection: 'asc' }, +] + +// 25歳以上のユーザーを取得し、結果を5つに制限するクエリ +const limitedConditions: QueryCondition[] = [ + { field: 'age', operator: '>', value: 25 }, + { limit: 5 }, +] + +async function run() { + try { + const path = 'Users' + + // シンプルな条件を使用して取得 + const usersByAge = await query(db, path, simpleConditions) + console.log(\`25歳以上のユーザーが \${usersByAge.length} 人見つかりました。\`) + + // 高度な条件を使用して取得 + const orderedUsers = await query(db, path, advancedConditions) + console.log( + \`名前で昇順に並べた25歳以上のユーザーが \${orderedUsers.length} 人見つかりました。\` + ) + + // 制限付きの条件を使用して取得 + const limitedUsers = await query(db, path, limitedConditions) + console.log( + \`25歳以上のユーザーが \${limitedUsers.length} 人見つかりました(制限: 5人)。\` + ) + } catch (error) { + console.error(\`コレクションのクエリエラー: \${error}\`) + } +} + +run() +\`\`\`` + +const skeetFirestoreUpdate = `## コレクションアイテムの更新 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { update } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) +const updatedData: User = { + age: 38, +} + +async function run() { + try { + const path = 'Users' + const docId = '123456' + const success = await update(db, path, docId, updatedData) + if (success) { + console.log(\`ID \${docId} のドキュメントが正常に更新されました。\`) + } + } catch (error) { + console.error(\`ドキュメントの更新エラー: \${error}\`) + } +} + +run() +\`\`\`` + +const skeetFirestoreDelete = `## コレクションアイテムの削除 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { del } from '@skeet-framework/firestore' + +export const db = getFirestore(firebaseApp) + +async function run() { + try { + const path = 'Users' + const docId = '123456' + const success = await del(db, path, docId) + if (success) { + console.log(\`ID \${docId} のドキュメントが正常に削除されました。\`) + } + } catch (error) { + console.error(\`ドキュメントの削除エラー: \${error}\`) + } +} + +run() +\`\`\`` + +const skeetFirestore = `# Skeet Framework プラグイン - Firestore + +Skeet Firestore プラグインは、Firestore コンバーターを使用した CRUD Firestore 操作をサポートします。 +型安全性があり、使いやすく、テストもしやすいです。 + +# インストール + +\`\`\`bash +$ pnpm add @skeet-framework/firestore +\`\`\` + +# Skeet Firestore Type ドキュメント + +- [Skeet Firestore TypeDoc](https://elsoul.github.io/skeet-firestore/) + +# 特徴 + +すべての CRUD 操作は Firestore コンバーターをサポートします。 +createdAt および updatedAt は Firebase ServerTimestamp で自動的にドキュメントに追加されます。 + +- [x] コレクションアイテムの追加 +- [x] 複数のコレクションアイテムの追加 +- [x] コレクションアイテムの取得 +- [x] コレクションアイテムのクエリ +- [x] コレクションアイテムの更新 +- [x] コレクションアイテムの削除 + +# 使用方法 + +## 初期化 + +\`\`\`typescript +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' + +const firebaseApp = initializeApp({ + credential: applicationDefault(), +}) +export const db = getFirestore(firebaseApp) +\`\`\` + + +## 複数のコレクションアイテムの追加 + +\`\`\`ts +import { applicationDefault, initializeApp } from 'firebase-admin/app' +import { getFirestore } from 'firebase-admin/firestore' +import { adds } from '@skeet-framework/firestore' + +const firebaseApp = initializeApp({ + credential: applicationDefault(), +}) +export const db = getFirestore(firebaseApp) +const users: User[] = [ + { name: 'John Doe', age: 30 }, + { name: 'Jane Smith', age: 25 }, + // ... 他のユーザー ... +] + +async function run() { + try { + const path = 'Users' + const results = await adds(db, path, users) + console.log( + \`\${users.length} 人のユーザーが \${results.length} バッチで追加されました。\` + ) + } catch (error) { + console.error(\`ドキュメントの追加エラー: \${error}\`) + } +} + +run() +\`\`\`` diff --git a/packages/cli/src/cli/ai/validateAiConfig.ts b/packages/cli/src/cli/ai/validateAiConfig.ts deleted file mode 100644 index 6455c44a..00000000 --- a/packages/cli/src/cli/ai/validateAiConfig.ts +++ /dev/null @@ -1,29 +0,0 @@ -import { SKEET_CONFIG_PATH } from '@/index' -import { SkeetCloudConfig } from '@/types/skeetTypes' -import { readFile, writeFile } from 'fs/promises' - -const defaultAiConfig = { - lang: 'en', - ais: [ - { - name: 'Gemini', - availableModels: ['gemini-1.0-pro', 'gemini-1.0-pro-vision'], - }, - ], -} - -export const validateAiConfig = async () => { - try { - const config = await readFile(`./skeet-cloud.config.json`) - const skeetConfig: SkeetCloudConfig = JSON.parse(String(config)) - if (!skeetConfig.ai) { - skeetConfig.ai = defaultAiConfig - await writeFile(SKEET_CONFIG_PATH, JSON.stringify(skeetConfig, null, 2)) - } - } catch (error) { - const skeetConfig = { - ai: defaultAiConfig, - } - await writeFile(SKEET_CONFIG_PATH, JSON.stringify(skeetConfig, null, 2)) - } -} diff --git a/packages/cli/src/cli/check/checkAi.ts b/packages/cli/src/cli/check/checkAi.ts new file mode 100644 index 00000000..93b4d93e --- /dev/null +++ b/packages/cli/src/cli/check/checkAi.ts @@ -0,0 +1,29 @@ +import chalk from 'chalk' +import { AIType, chat } from '@skeet-framework/ai' +import { readOrCreateConfig } from '@/config/readOrCreateConfig' +import { SkeetAIOptions } from '..' +import { AiLog } from '../ai/aiLog' +import { skeetAiPrompt } from '../ai/skeetPrompt' + +export async function checkAi( + options: SkeetAIOptions, + logger: AiLog, +): Promise { + const log = logger.text() as SkeetLog + const aiOptions = { + ai: (options.ai as AIType) || ('Gemini' as AIType), + } + + console.log('\n') + + console.log(chalk.blue('Skeet:')) + + const config = await readOrCreateConfig() + const skeetPrompt = await skeetAiPrompt() + await chat( + skeetPrompt.context, + skeetPrompt.examples, + config.app.cloudStatus, + aiOptions.ai, + ) +} diff --git a/packages/cli/src/cli/check/index.ts b/packages/cli/src/cli/check/index.ts new file mode 100644 index 00000000..0fcca19e --- /dev/null +++ b/packages/cli/src/cli/check/index.ts @@ -0,0 +1,50 @@ +import { readOrCreateConfig } from '@/config/readOrCreateConfig' +import { SkeetCloudStatusType } from '@/config/skeetCloud' +import { program } from '@/index' +import { initFirebaseProject } from '../init/initStep/initFirebaseProject' +import { deployFirebaseFunctions } from '../init/initStep/deployFirebaseFunctions' +import { generanteGitRepo } from '../init/initStep/generanteGitRepo' +import { createVPN } from '../init/initStep/createVPN' +import chalk from 'chalk' +import { checkAi } from './checkAi' +import { AiLog } from '../ai/aiLog' + +export const checkCommands = async () => { + program + .command('check') + .description('Check Cloud Configurations') + .action(async () => { + const config = await readOrCreateConfig() + const lang = config.lang as 'en' | 'ja' + const logger = new AiLog(lang) + const cloudStatus: SkeetCloudStatusType = config.app.cloudStatus + await checkAi({ ai: 'Gemini' }, logger) + // await checkCloudByStatus(cloudStatus) + }) +} + +const checkCloudByStatus = async (cloudStatus: SkeetCloudStatusType) => { + switch (cloudStatus) { + case 'NOT_CREATED': + // Initialize Firebase Project + await initFirebaseProject() + break + case 'PROJECT_CREATED': + // Deploy Firebase Functions + await deployFirebaseFunctions() + break + case 'FUNCTIONS_CREATED': + // Add Github Actions + await generanteGitRepo() + break + case 'GITHUB_ACTIONS_CREATED': + // Add Cloud VPN + await createVPN() + break + case 'VPN_CREATED': + console.log(chalk.white(`⭐️ You are all set!`)) + break + default: + break + } +} diff --git a/packages/cli/src/cli/init/index.ts b/packages/cli/src/cli/init/index.ts index 34cfadee..0ae44f4c 100644 --- a/packages/cli/src/cli/init/index.ts +++ b/packages/cli/src/cli/init/index.ts @@ -1,32 +1,26 @@ import { program } from '@/index' -import { skeetCloudConfigAppGen } from '@/templates/init/skeet-cloud.config-app' -import { initLb } from './initLb' import { init } from './init' -import { writeFile } from 'fs/promises' -import { setupNetwork } from '@/lib/setup/setupNetwork' -export * from './askQuestions' +import { generanteGitRepo } from './initStep/generanteGitRepo' +import { createVPN } from './initStep/createVPN' type Options = { - login: boolean - config: boolean - lb: boolean - network: boolean + repo: boolean + vpn: boolean } export const initCommands = async () => { program .command('init') - .option('--login', 'Activate Firebase Login', false) - .option('--lb', 'Setup Cloud Load Balancer', false) - .option('-n, --network', 'Setup Network', false) - .description('Initialize Google Cloud Setups for Skeet APP') + .option('--repo', 'Configure Github Repo/Actions', false) + .option('--vpn', 'Setup Cloud VPN', false) + .description('Initialize Google Cloud Setups') .action(async (options: Options) => { - if (options.lb) { - await initLb() - } else if (options.network) { - await setupNetwork() + if (options.repo) { + await generanteGitRepo() + } else if (options.vpn) { + await createVPN() } else { - await init(options.login) + await init() } }) } diff --git a/packages/cli/src/cli/init/indexV2.ts b/packages/cli/src/cli/init/indexV2.ts deleted file mode 100644 index a6ba87b0..00000000 --- a/packages/cli/src/cli/init/indexV2.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { readOrCreateConfig } from '@/config/readOrCreateConfig' -import { SkeetCloudStatusType } from '@/config/skeetCloud' -import { program } from '@/index' -import { initWhenNotCreated } from './initCloud/initWhenNotCreated' -import { initWhenProjectCreated } from './initCloud/initWhenProjectCreated' -import { initWhenFunctionsCreated } from './initCloud/initWhenFunctionsCreated' -import { initWhenGithubActionsCreated } from './initCloud/initWhenGithubActionsCreated' -import { initWhenVPNCreated } from './initCloud/initWhenVPNCreated' -import { initWhenSQLCreated } from './initCloud/initWhenSQLCreated' -import chalk from 'chalk' -export * from './askQuestions' - -export const initV2Commands = async () => { - program - .command('init') - .description('Initialize Cloud Configurations') - .action(async () => { - const config = await readOrCreateConfig() - const cloudStatus: SkeetCloudStatusType = config.app.cloudStatus - await initCloudByStatus(cloudStatus) - }) -} - -const initCloudByStatus = async (cloudStatus: SkeetCloudStatusType) => { - switch (cloudStatus) { - case 'NOT_CREATED': - // Initialize Firebase Project - await initWhenNotCreated() - break - case 'PROJECT_CREATED': - // Deploy Firebase Functions - await initWhenProjectCreated() - break - case 'FUNCTIONS_CREATED': - // Add Github Actions - await initWhenFunctionsCreated() - break - case 'GITHUB_ACTIONS_CREATED': - // Add Cloud VPN - await initWhenGithubActionsCreated() - break - case 'VPN_CREATED': - // Add Cloud SQL - await initWhenVPNCreated() - break - case 'SQL_CREATED': - await initWhenSQLCreated() - break - case 'RUNNING': - console.log(chalk.white('🚀 Your Project looks perfect!')) - break - default: - break - } -} diff --git a/packages/cli/src/cli/init/init.ts b/packages/cli/src/cli/init/init.ts index a13f60bb..6b800be6 100644 --- a/packages/cli/src/cli/init/init.ts +++ b/packages/cli/src/cli/init/init.ts @@ -1,114 +1,18 @@ -import { - Logger, - importConfig, - firebaseUseAdd, - firebaseLogin, - createLoadBalancer, - setupCloud, - createServiceAccount, - setupNetwork, - getZone, - runAddAllRole, - runEnableAllPermission, -} from '@/lib' -import { addFirebaseApp } from '../sub/add/addFirebaseApp' -import { pnpmBuild } from '../../lib/pnpmBuild' -import { firebaseFunctionsDeploy } from '../deploy/firebaseDeploy' -import { deployRules } from '../deploy/deployRules' -import { DomainAnswer, askForGithubRepo } from './askQuestions' -import { addProjectRegionToSkeetOptions } from '@/lib/files/addJson' -import { genGithubActions } from '../gen' -import { projectIdNotExists } from '@/lib/gcloud/billing/checkBillingAccount' -import { DEFAULT_FUNCTION_NAME, FIREBASERC_PATH } from '@/index' -import { syncRoutings } from '../sub/sync/syncRoutings' -import inquirer from 'inquirer' -import { projectQuestions } from './questionList' -import { spawnSync } from 'node:child_process' -import { readFile, writeFile } from 'fs/promises' -import { domains } from './initLb' -import { readOrCreateConfig } from '@/config/readOrCreateConfig' +import { initFirebaseProject } from './initStep/initFirebaseProject' +import { deployFirebaseFunctions } from './initStep/deployFirebaseFunctions' +import { generanteGitRepo } from './initStep/generanteGitRepo' +import { createVPN } from './initStep/createVPN' -export type initialParams = { - projectId: string - fbProjectId: string - region: string -} - -export const init = async (loginMode = false) => { - // Setup Google Cloud Project - const { projectId, fbProjectId, region } = - await inquirer.prompt(await projectQuestions()) - if (await projectIdNotExists(projectId)) - Logger.projectIdNotExistsError(projectId) - - await updateFirebaserc(fbProjectId) - - if (!region) throw new Error('region is undefined') - - // Setup Firebase Project - await firebaseLogin() - await firebaseUseAdd(fbProjectId) - await addProjectRegionToSkeetOptions( - region, - projectId, - fbProjectId, - DEFAULT_FUNCTION_NAME, - ) - const defaultAppDisplayName = fbProjectId - await addFirebaseApp(fbProjectId, defaultAppDisplayName) - const { app } = await importConfig() - await createServiceAccount(projectId, app.name) - await runEnableAllPermission(projectId) - await runAddAllRole(projectId, app.name) - if (loginMode) return - - const skeetConfig = await readOrCreateConfig() - await Logger.confirmFirebaseSetup(fbProjectId, '') - - const githubRepo = await askForGithubRepo() +export const init = async () => { + // Initialize Firebase Project - cloudStatus: 'PROJECT_CREATED' + await initFirebaseProject() - let domainAnswer: DomainAnswer = { - isDomain: false, - appDomain: '', - nsDomain: '', - lbDomain: '', - } + // Deploy Firebase Functions(skeet-func) - cloudStatus: 'FUNCTIONS_CREATED' + await deployFirebaseFunctions() - // Ask Domain info if LB is not exists - if (!skeetConfig.app.hasLoadBalancer) { - domainAnswer = await inquirer.prompt(domains) - } - - // Setup Cloud - await setupCloud(skeetConfig, githubRepo, skeetConfig.app.region) - - // Setup Network - await setupNetwork() - - // Deploy Default Firebase Functions - await pnpmBuild(DEFAULT_FUNCTION_NAME) - await firebaseFunctionsDeploy(skeetConfig.app.fbProjectId) - await deployRules(skeetConfig.app.fbProjectId) - - // Create Github Actions - await genGithubActions() - - // Create Load Balancer if not exists - if (!skeetConfig.app.hasLoadBalancer) { - await createLoadBalancer(skeetConfig, domainAnswer) - await syncRoutings() - const cmd = `pnpm deploy` - spawnSync(cmd, { stdio: 'inherit', shell: true }) - const ips = await getZone(projectId, skeetConfig.app.name) - Logger.dnsSetupLog(ips) - } else { - const cmd = `pnpm deploy` - spawnSync(cmd, { stdio: 'inherit', shell: true }) - } -} + // Generate Github Actions - cloudStatus: 'GITHUB_ACTIONS_CREATED' + await generanteGitRepo() -const updateFirebaserc = async (fbProjectId: string) => { - const firebaserc = JSON.parse(await readFile(FIREBASERC_PATH, 'utf-8')) - firebaserc.projects.default = fbProjectId - await writeFile(FIREBASERC_PATH, JSON.stringify(firebaserc, null, 2)) + // Create VPN and NAT - cloudStatus: 'VPN_CREATED' + await createVPN() } diff --git a/packages/cli/src/cli/init/initCloud/initWhenGithubActionsCreated.ts b/packages/cli/src/cli/init/initCloud/initWhenGithubActionsCreated.ts deleted file mode 100644 index c23350f7..00000000 --- a/packages/cli/src/cli/init/initCloud/initWhenGithubActionsCreated.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { setupNetwork } from '@/lib' -import { updateSkeetCloudConfigCloudStatus } from '../updateSkeetCloudConfigCloudStatus' - -export const initWhenGithubActionsCreated = async () => { - await setupNetwork() - await updateSkeetCloudConfigCloudStatus('VPN_CREATED') -} diff --git a/packages/cli/src/cli/init/initCloud/initWhenSQLCreated.ts b/packages/cli/src/cli/init/initCloud/initWhenSQLCreated.ts deleted file mode 100644 index f612efb5..00000000 --- a/packages/cli/src/cli/init/initCloud/initWhenSQLCreated.ts +++ /dev/null @@ -1,5 +0,0 @@ -import chalk from 'chalk' - -export const initWhenSQLCreated = async () => { - console.log(chalk.white('Coming soon!')) -} diff --git a/packages/cli/src/cli/init/initCloud/initWhenVPNCreated.ts b/packages/cli/src/cli/init/initCloud/initWhenVPNCreated.ts deleted file mode 100644 index 36b093d6..00000000 --- a/packages/cli/src/cli/init/initCloud/initWhenVPNCreated.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { readOrCreateConfig } from '@/config/readOrCreateConfig' -import { updateSkeetCloudConfigCloudStatus } from '../updateSkeetCloudConfigCloudStatus' -import { getSQLs } from '@/lib/files/getSQLs' -import chalk from 'chalk' - -export const initWhenVPNCreated = async () => { - const config = await readOrCreateConfig() - const sqlDirs = await getSQLs() - if (sqlDirs.length > 0) { - const sqls = config.SQL.filter((sql) => sql.status === 'NOT_CREATED') - if (sqls.length > 0) { - console.log(chalk.white(`You have ${sqls.length} SQLs to create.`)) - console.log( - chalk.white( - 'Please run this command to create Cloud SQL:\n\n$ skeet deploy --sql\n', - ), - ) - } else { - await updateSkeetCloudConfigCloudStatus('SQL_CREATED') - } - return - } else { - console.log(chalk.white('No SQL API found.')) - console.log( - chalk.white( - 'Please run this command to create SQL API:\n\n$ skeet add sql\n', - ), - ) - return - } -} diff --git a/packages/cli/src/cli/init/initStep/createVPN.ts b/packages/cli/src/cli/init/initStep/createVPN.ts new file mode 100644 index 00000000..9131a06e --- /dev/null +++ b/packages/cli/src/cli/init/initStep/createVPN.ts @@ -0,0 +1,7 @@ +import { setupNetwork } from '@/lib' +import { updateSkeetCloudConfigCloudStatus } from '../../init/updateSkeetCloudConfigCloudStatus' + +export const createVPN = async () => { + await setupNetwork() + await updateSkeetCloudConfigCloudStatus('VPN_CREATED') +} diff --git a/packages/cli/src/cli/init/initCloud/initWhenProjectCreated.ts b/packages/cli/src/cli/init/initStep/deployFirebaseFunctions.ts similarity index 68% rename from packages/cli/src/cli/init/initCloud/initWhenProjectCreated.ts rename to packages/cli/src/cli/init/initStep/deployFirebaseFunctions.ts index 2d9d7104..aacae9d2 100644 --- a/packages/cli/src/cli/init/initCloud/initWhenProjectCreated.ts +++ b/packages/cli/src/cli/init/initStep/deployFirebaseFunctions.ts @@ -1,16 +1,18 @@ import { readOrCreateConfig } from '@/config/readOrCreateConfig' import { execAsync } from '@skeet-framework/utils' import { spawnSync } from 'node:child_process' -import { updateSkeetCloudConfigCloudStatus } from '../updateSkeetCloudConfigCloudStatus' +import { updateSkeetCloudConfigCloudStatus } from '../../init/updateSkeetCloudConfigCloudStatus' -export const initWhenProjectCreated = async () => { +export const deployFirebaseFunctions = async () => { const config = await readOrCreateConfig() const cmd1 = `firebase deploy --only functions:skeet-func:root --project ${config.app.projectId}` spawnSync(cmd1, { shell: true, stdio: 'inherit' }) const cmd2 = `firebase functions:list --project ${config.app.projectId}` const { stdout } = await execAsync(cmd2) if (stdout.includes('root')) { - console.log('🚀 Deployed Your First Firebase Functions') + console.log( + '🚀 Deployed Your First Firebase Functions!Please Call Skeet AI with the following command:\n\n$ skeet ai', + ) await updateSkeetCloudConfigCloudStatus('FUNCTIONS_CREATED') return true } else { diff --git a/packages/cli/src/cli/init/initCloud/initWhenFunctionsCreated.ts b/packages/cli/src/cli/init/initStep/generanteGitRepo.ts similarity index 87% rename from packages/cli/src/cli/init/initCloud/initWhenFunctionsCreated.ts rename to packages/cli/src/cli/init/initStep/generanteGitRepo.ts index 7d45333b..0fa0050f 100644 --- a/packages/cli/src/cli/init/initCloud/initWhenFunctionsCreated.ts +++ b/packages/cli/src/cli/init/initStep/generanteGitRepo.ts @@ -3,7 +3,7 @@ import { addGhActions } from '@/cli/sub/add/addGhActions' import { addJsonEnv } from '@/lib' import { updateSkeetCloudConfigCloudStatus } from '../updateSkeetCloudConfigCloudStatus' -export const initWhenFunctionsCreated = async () => { +export const generanteGitRepo = async () => { await genGithubActions() await addGhActions() await addJsonEnv() diff --git a/packages/cli/src/cli/init/initCloud/initWhenNotCreated.ts b/packages/cli/src/cli/init/initStep/initFirebaseProject.ts similarity index 63% rename from packages/cli/src/cli/init/initCloud/initWhenNotCreated.ts rename to packages/cli/src/cli/init/initStep/initFirebaseProject.ts index 5e42260b..30ef5aa7 100644 --- a/packages/cli/src/cli/init/initCloud/initWhenNotCreated.ts +++ b/packages/cli/src/cli/init/initStep/initFirebaseProject.ts @@ -1,6 +1,5 @@ import inquirer from 'inquirer' -import { initialParams } from '../init' -import { projectQuestions } from '../questionList' +import { projectQuestions } from '../../init/questionList' import { projectIdNotExists } from '@/lib/gcloud/billing/checkBillingAccount' import { Logger, @@ -10,17 +9,24 @@ import { runAddAllRole, runEnableAllPermission, } from '@/lib' -import { readFile, writeFile } from 'fs/promises' -import { DEFAULT_FUNCTION_NAME, FIREBASERC_PATH } from '@/index' +import { writeFile } from 'fs/promises' +import { DEFAULT_FUNCTION_NAME } from '@/index' import { addProjectRegionToSkeetOptions } from '@/lib/files/addJson' import { addFirebaseApp } from '../../sub/add/addFirebaseApp' import { readOrCreateConfig } from '@/config/readOrCreateConfig' -import { checkFileDirExists } from '@/lib/files/checkFileDirExists' import { SKEET_CONFIG_CLOUD_PATH } from '@/config/config' import { Spinner } from 'cli-spinner' import chalk from 'chalk' +import { updateFirebaserc } from '@/lib/files/updateFirebaserc' +import { updateSkeetCloudConfigCloudStatus } from '../updateSkeetCloudConfigCloudStatus' -export const initWhenNotCreated = async () => { +type initialParams = { + projectId: string + fbProjectId: string + region: string +} + +export const initFirebaseProject = async () => { const { projectId, fbProjectId, region } = await inquirer.prompt(await projectQuestions()) const isProjectExists = await projectIdNotExists(projectId) @@ -50,30 +56,11 @@ export const initWhenNotCreated = async () => { await createServiceAccount(projectId, config.app.name) await runEnableAllPermission(projectId) await runAddAllRole(projectId, config.app.name) - config.app.cloudStatus = 'PROJECT_CREATED' + await updateSkeetCloudConfigCloudStatus('PROJECT_CREATED') await writeFile(SKEET_CONFIG_CLOUD_PATH, JSON.stringify(config, null, 2)) await writeFile( '.env', `GCP_PROJECT_ID=${projectId}\nGCP_LOCATION=${region}\n`, ) spinner.stop() - console.log(chalk.white('\n ✔️ Successfully Initialized Your Project')) - console.log( - chalk.white( - `Now you can try your AI Assistant 🔥\n\n $ skeet ai --help\n\n`, - ), - ) -} - -const updateFirebaserc = async (fbProjectId: string) => { - if (!(await checkFileDirExists(FIREBASERC_PATH))) { - await writeFile( - FIREBASERC_PATH, - JSON.stringify({ projects: { default: fbProjectId } }, null, 2), - ) - return - } - const firebaserc = JSON.parse(await readFile(FIREBASERC_PATH, 'utf-8')) - firebaserc.projects.default = fbProjectId - await writeFile(FIREBASERC_PATH, JSON.stringify(firebaserc, null, 2)) } diff --git a/packages/cli/src/cli/sub/add/addCloudSQL.ts b/packages/cli/src/cli/sub/add/addCloudSQL.ts index f32b956c..eb3f624c 100644 --- a/packages/cli/src/cli/sub/add/addCloudSQL.ts +++ b/packages/cli/src/cli/sub/add/addCloudSQL.ts @@ -125,9 +125,6 @@ export const updateSkeetConfigDb = async ( sql.status = 'RUNNING' } }) - if (config.app.cloudStatus === 'VPN_CREATED') { - config.app.cloudStatus = 'SQL_CREATED' - } await writeFile(SKEET_CONFIG_PATH, JSON.stringify(config, null, 2)) return } diff --git a/packages/cli/src/cli/sub/add/deployCloudSQL.ts b/packages/cli/src/cli/sub/add/deployCloudSQL.ts index 94101d54..f96cdba7 100644 --- a/packages/cli/src/cli/sub/add/deployCloudSQL.ts +++ b/packages/cli/src/cli/sub/add/deployCloudSQL.ts @@ -1,4 +1,3 @@ -import { askForSqlPassword } from '@/cli/init' import { getNetworkConfig } from '@/lib/files/getSkeetConfig' import { createSQL } from '@/lib/gcloud/sql/createSQL' import { patchSQL } from '@/lib/gcloud/sql/patchSQL' @@ -13,6 +12,7 @@ import { addEnv } from '@/lib' import { SkeetCloudConfig } from '@/config/skeetCloud' import chalk from 'chalk' import { generateEnvProduction } from '@/lib/gcloud/sql/generateEnvProduction' +import { askForSqlPassword } from '@/cli/init/askQuestions' export const deployCloudSQL = async ( instanceName: string, diff --git a/packages/cli/src/config/skeetCloud.ts b/packages/cli/src/config/skeetCloud.ts index 7f62befd..790b9c28 100644 --- a/packages/cli/src/config/skeetCloud.ts +++ b/packages/cli/src/config/skeetCloud.ts @@ -25,8 +25,6 @@ export type SkeetCloudStatusType = | 'FUNCTIONS_CREATED' | 'GITHUB_ACTIONS_CREATED' | 'VPN_CREATED' - | 'SQL_CREATED' - | 'RUNNING' export enum SkeetCloudStatus { NOT_CREATED, @@ -34,8 +32,6 @@ export enum SkeetCloudStatus { FUNCTIONS_CREATED, GITHUB_ACTIONS_CREATED, VPN_CREATED, - SQL_CREATED, - RUNNING, } export type LangType = 'en' | 'ja' diff --git a/packages/cli/src/config/templateVersion.ts b/packages/cli/src/config/templateVersion.ts index 32a9cfbd..bfa80c21 100644 --- a/packages/cli/src/config/templateVersion.ts +++ b/packages/cli/src/config/templateVersion.ts @@ -19,7 +19,7 @@ export const getTemplateVersion = (templateType: TemplateType) => { return TEMPLATE_VERSION.BASE_FUNCTIONS case 'base-sql': return TEMPLATE_VERSION.BASE_SQL - case 'skeet-func': + case 'skeet-func-template': return TEMPLATE_VERSION.SKEET_FUNC default: return TEMPLATE_VERSION.BASE_TEMPLATE diff --git a/packages/cli/src/index.ts b/packages/cli/src/index.ts index 5443139a..4de9b984 100644 --- a/packages/cli/src/index.ts +++ b/packages/cli/src/index.ts @@ -19,8 +19,9 @@ import { serverCommands } from '@/cli/server' import { logCommands } from '@/cli/log' import { dbSubCommands } from '@/cli/sub/db' import { newCommands } from './cli/new' -import { initV2Commands } from './cli/init/indexV2' import { consoleCommands } from './cli/console' +import { checkCommands } from './cli/check' +import { initCommands } from './cli' export const SKEET_CONFIG_PATH = './skeet-cloud.config.json' export const DEFAULT_FUNCTION_NAME = 'skeet' @@ -42,7 +43,7 @@ async function main() { await createCommands() await serverCommands() await deployCommands() - await initV2Commands() + await initCommands() await loginCommands() await curlCommands() await genCommands() @@ -59,6 +60,7 @@ async function main() { runCommands() await newCommands() await consoleCommands() + await checkCommands() // program // .command('test') // .description('Run tests') diff --git a/packages/cli/src/lib/cliHelp.ts b/packages/cli/src/lib/cliHelp.ts index 34dc31ed..12d04b53 100644 --- a/packages/cli/src/lib/cliHelp.ts +++ b/packages/cli/src/lib/cliHelp.ts @@ -10,7 +10,7 @@ Commands: create [options] Create Skeet Framework App server|s [options] Run Skeet App deploy [options] Deploy Skeet APP to Firebase - init Initialize Cloud Configurations + init [options] Initialize Google Cloud Setups login Skeet Login Command - Create Firebase Login Token curl [options] Skeet Curl Command - Call Firebase Functions @@ -24,11 +24,12 @@ Commands: sync Skeet Sync Comannd to sync backend and frontend delete|d Skeet Delete Command get Get Skeet App List - ai [options] AI Playground + ai [options] Call Skeet AI Assistant config Config commands run [options] Run commands new|n [options] Create Skeet Framework App console|c Call Firebase Console to Test Functions + check Check Cloud Configurations help [command] display help for command Usage: skeet create [options] @@ -54,9 +55,11 @@ Options: Usage: skeet init [options] -Initialize Cloud Configurations +Initialize Google Cloud Setups Options: + --repo Configure Github Repo/Actions (default: false) + --vpn Setup Cloud VPN (default: false) -h, --help display help for command Usage: skeet login [options] @@ -78,7 +81,7 @@ Commands: create [options] Create Skeet Framework App server|s [options] Run Skeet App deploy [options] Deploy Skeet APP to Firebase - init Initialize Cloud Configurations + init [options] Initialize Google Cloud Setups login Skeet Login Command - Create Firebase Login Token curl [options] Skeet Curl Command - Call Firebase Functions @@ -92,11 +95,12 @@ Commands: sync Skeet Sync Comannd to sync backend and frontend delete|d Skeet Delete Command get Get Skeet App List - ai [options] AI Playground + ai [options] Call Skeet AI Assistant config Config commands run [options] Run commands new|n [options] Create Skeet Framework App console|c Call Firebase Console to Test Functions + check Check Cloud Configurations help [command] display help for command Usage: skeet [options] [command] @@ -111,7 +115,7 @@ Commands: create [options] Create Skeet Framework App server|s [options] Run Skeet App deploy [options] Deploy Skeet APP to Firebase - init Initialize Cloud Configurations + init [options] Initialize Google Cloud Setups login Skeet Login Command - Create Firebase Login Token curl [options] Skeet Curl Command - Call Firebase Functions @@ -125,11 +129,12 @@ Commands: sync Skeet Sync Comannd to sync backend and frontend delete|d Skeet Delete Command get Get Skeet App List - ai [options] AI Playground + ai [options] Call Skeet AI Assistant config Config commands run [options] Run commands new|n [options] Create Skeet Framework App console|c Call Firebase Console to Test Functions + check Check Cloud Configurations help [command] display help for command Usage: skeet log [options] @@ -243,13 +248,13 @@ Commands: Usage: skeet ai [options] -AI Playground +Call Skeet AI Assistant Options: - -g, --gemini Gemini - -o, --openai OpenAI - -c, --claude Claude - --mode Mode + -g, --gemini Use Gemini - default + -o, --openai Use OpenAI + -c, --claude Use Claude + --mode Call Mode Select Prompt -h, --help display help for command Usage: skeet config [options] [command] @@ -272,6 +277,13 @@ Options: -C, --cmd Command (default: "") -h, --help display help for command +Usage: skeet check [options] + +Check Cloud Configurations + +Options: + -h, --help display help for command + Usage: skeet [options] [command] CLI for Skeet - Full-stack TypeScript Serverless framework @@ -284,7 +296,7 @@ Commands: create [options] Create Skeet Framework App server|s [options] Run Skeet App deploy [options] Deploy Skeet APP to Firebase - init Initialize Cloud Configurations + init [options] Initialize Google Cloud Setups login Skeet Login Command - Create Firebase Login Token curl [options] Skeet Curl Command - Call Firebase Functions @@ -298,10 +310,11 @@ Commands: sync Skeet Sync Comannd to sync backend and frontend delete|d Skeet Delete Command get Get Skeet App List - ai [options] AI Playground + ai [options] Call Skeet AI Assistant config Config commands run [options] Run commands new|n [options] Create Skeet Framework App console|c Call Firebase Console to Test Functions + check Check Cloud Configurations help [command] display help for command ` \ No newline at end of file diff --git a/packages/cli/src/lib/files/updateFirebaserc.ts b/packages/cli/src/lib/files/updateFirebaserc.ts new file mode 100644 index 00000000..a9aa6911 --- /dev/null +++ b/packages/cli/src/lib/files/updateFirebaserc.ts @@ -0,0 +1,16 @@ +import { FIREBASERC_PATH } from '@/index' +import { checkFileDirExists } from './checkFileDirExists' +import { readFile, writeFile } from 'fs/promises' + +export const updateFirebaserc = async (fbProjectId: string) => { + if (!(await checkFileDirExists(FIREBASERC_PATH))) { + await writeFile( + FIREBASERC_PATH, + JSON.stringify({ projects: { default: fbProjectId } }, null, 2), + ) + return + } + const firebaserc = JSON.parse(await readFile(FIREBASERC_PATH, 'utf-8')) + firebaserc.projects.default = fbProjectId + await writeFile(FIREBASERC_PATH, JSON.stringify(firebaserc, null, 2)) +}