swallowkit 1.0.0-beta.5 → 1.0.0-beta.7

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 (97) hide show
  1. package/LICENSE +21 -21
  2. package/README.ja.md +251 -242
  3. package/README.md +252 -243
  4. package/dist/__tests__/fixtures.d.ts +14 -0
  5. package/dist/__tests__/fixtures.d.ts.map +1 -0
  6. package/dist/__tests__/fixtures.js +85 -0
  7. package/dist/__tests__/fixtures.js.map +1 -0
  8. package/dist/cli/commands/create-model.js +14 -14
  9. package/dist/cli/commands/dev.d.ts +8 -0
  10. package/dist/cli/commands/dev.d.ts.map +1 -1
  11. package/dist/cli/commands/dev.js +238 -30
  12. package/dist/cli/commands/dev.js.map +1 -1
  13. package/dist/cli/commands/init.d.ts +5 -0
  14. package/dist/cli/commands/init.d.ts.map +1 -1
  15. package/dist/cli/commands/init.js +2507 -1664
  16. package/dist/cli/commands/init.js.map +1 -1
  17. package/dist/cli/commands/scaffold.d.ts +3 -0
  18. package/dist/cli/commands/scaffold.d.ts.map +1 -1
  19. package/dist/cli/commands/scaffold.js +281 -117
  20. package/dist/cli/commands/scaffold.js.map +1 -1
  21. package/dist/cli/index.js +2 -0
  22. package/dist/cli/index.js.map +1 -1
  23. package/dist/core/config.d.ts +2 -1
  24. package/dist/core/config.d.ts.map +1 -1
  25. package/dist/core/config.js +28 -0
  26. package/dist/core/config.js.map +1 -1
  27. package/dist/core/scaffold/functions-generator.d.ts +5 -0
  28. package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
  29. package/dist/core/scaffold/functions-generator.js +649 -218
  30. package/dist/core/scaffold/functions-generator.js.map +1 -1
  31. package/dist/core/scaffold/model-parser.d.ts +1 -1
  32. package/dist/core/scaffold/model-parser.js +99 -99
  33. package/dist/core/scaffold/nextjs-generator.js +181 -181
  34. package/dist/core/scaffold/openapi-generator.d.ts +3 -0
  35. package/dist/core/scaffold/openapi-generator.d.ts.map +1 -0
  36. package/dist/core/scaffold/openapi-generator.js +190 -0
  37. package/dist/core/scaffold/openapi-generator.js.map +1 -0
  38. package/dist/core/scaffold/ui-generator.js +656 -656
  39. package/dist/database/base-model.d.ts +3 -3
  40. package/dist/database/base-model.js +3 -3
  41. package/dist/index.d.ts +2 -2
  42. package/dist/index.d.ts.map +1 -1
  43. package/dist/index.js +2 -1
  44. package/dist/index.js.map +1 -1
  45. package/dist/types/index.d.ts +4 -0
  46. package/dist/types/index.d.ts.map +1 -1
  47. package/dist/utils/package-manager.d.ts +2 -1
  48. package/dist/utils/package-manager.d.ts.map +1 -1
  49. package/dist/utils/package-manager.js +14 -10
  50. package/dist/utils/package-manager.js.map +1 -1
  51. package/package.json +81 -74
  52. package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +445 -0
  53. package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +194 -0
  54. package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +524 -0
  55. package/src/__tests__/config.test.ts +122 -0
  56. package/src/__tests__/dev.test.ts +42 -0
  57. package/src/__tests__/fixtures.ts +83 -0
  58. package/src/__tests__/functions-generator.test.ts +101 -0
  59. package/src/__tests__/init.test.ts +59 -0
  60. package/src/__tests__/nextjs-generator.test.ts +97 -0
  61. package/src/__tests__/openapi-generator.test.ts +43 -0
  62. package/src/__tests__/package-manager.test.ts +189 -0
  63. package/src/__tests__/scaffold.test.ts +39 -0
  64. package/src/__tests__/string-utils.test.ts +75 -0
  65. package/src/__tests__/ui-generator.test.ts +144 -0
  66. package/src/cli/commands/create-model.ts +141 -0
  67. package/src/cli/commands/dev.ts +794 -0
  68. package/src/cli/commands/index.ts +8 -0
  69. package/src/cli/commands/init.ts +3363 -0
  70. package/src/cli/commands/provision.ts +193 -0
  71. package/src/cli/commands/scaffold.ts +786 -0
  72. package/src/cli/index.ts +73 -0
  73. package/src/core/config.ts +244 -0
  74. package/src/core/scaffold/functions-generator.ts +674 -0
  75. package/src/core/scaffold/model-parser.ts +627 -0
  76. package/src/core/scaffold/nextjs-generator.ts +217 -0
  77. package/src/core/scaffold/openapi-generator.ts +212 -0
  78. package/src/core/scaffold/ui-generator.ts +945 -0
  79. package/src/database/base-model.ts +184 -0
  80. package/src/database/client.ts +140 -0
  81. package/src/database/repository.ts +104 -0
  82. package/src/database/runtime-check.ts +25 -0
  83. package/src/index.ts +27 -0
  84. package/src/types/index.ts +45 -0
  85. package/src/utils/package-manager.ts +229 -0
  86. package/dist/cli/commands/build.d.ts +0 -6
  87. package/dist/cli/commands/build.d.ts.map +0 -1
  88. package/dist/cli/commands/build.js +0 -177
  89. package/dist/cli/commands/build.js.map +0 -1
  90. package/dist/cli/commands/deploy.d.ts +0 -3
  91. package/dist/cli/commands/deploy.d.ts.map +0 -1
  92. package/dist/cli/commands/deploy.js +0 -147
  93. package/dist/cli/commands/deploy.js.map +0 -1
  94. package/dist/cli/commands/setup.d.ts +0 -6
  95. package/dist/cli/commands/setup.d.ts.map +0 -1
  96. package/dist/cli/commands/setup.js +0 -254
  97. package/dist/cli/commands/setup.js.map +0 -1
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env node
2
+
3
+ // Ensure UTF-8 console output on Windows (fixes emoji/Unicode garbling in PowerShell 5.1)
4
+ if (process.platform === 'win32') {
5
+ try {
6
+ require('child_process').execSync('chcp 65001', { stdio: 'ignore' });
7
+ } catch { /* ignore — non-critical */ }
8
+ }
9
+
10
+ import { Command } from "commander";
11
+ import { initCommand, devCommand, scaffoldCommand, createModelCommand } from "./commands";
12
+ import { provisionCommand } from "./commands/provision";
13
+
14
+ const program = new Command();
15
+
16
+ program
17
+ .name("swallowkit")
18
+ .description("Next.js framework optimized for Azure deployment - Automatically splits SSR into individual Azure Functions")
19
+ .version("1.0.0-beta.5");
20
+
21
+ // Register commands
22
+ program
23
+ .command("init [project-name]")
24
+ .description("Initialize a new SwallowKit project")
25
+ .option("--template <template>", "Template to use", "default")
26
+ .option("--next-version <version>", "Next.js version to install (e.g., 16.0.7, latest)", "latest")
27
+ .option("--cicd <provider>", "CI/CD provider: github | azure | skip")
28
+ .option("--backend-language <language>", "Azure Functions backend language: typescript | csharp | python")
29
+ .option("--cosmos-db-mode <mode>", "Cosmos DB mode: freetier | serverless")
30
+ .option("--vnet <option>", "Network security: outbound | none")
31
+ .action((projectName, options) => {
32
+ initCommand({
33
+ name: projectName || "swallowkit-app",
34
+ template: options.template,
35
+ nextVersion: options.nextVersion,
36
+ cicd: options.cicd,
37
+ backendLanguage: options.backendLanguage,
38
+ cosmosDbMode: options.cosmosDbMode,
39
+ vnet: options.vnet,
40
+ });
41
+ });
42
+
43
+ program.addCommand(devCommand);
44
+
45
+ program.addCommand(provisionCommand);
46
+
47
+ program
48
+ .command("create-model <names...>")
49
+ .description("Create model template files with id, createdAt, and updatedAt fields")
50
+ .option("--models-dir <dir>", "Models directory", "shared/models")
51
+ .action((names, options) => {
52
+ createModelCommand({
53
+ names,
54
+ modelsDir: options.modelsDir,
55
+ });
56
+ });
57
+
58
+ program
59
+ .command("scaffold <model>")
60
+ .description("Generate CRUD code for Azure Functions and Next.js BFF from Zod models")
61
+ .option("--functions-dir <dir>", "Azure Functions directory", "functions")
62
+ .option("--api-dir <dir>", "Next.js API routes directory", "app/api")
63
+ .option("--api-only", "Generate API only, skip UI components", false)
64
+ .action((model, options) => {
65
+ scaffoldCommand({
66
+ model,
67
+ functionsDir: options.functionsDir,
68
+ apiDir: options.apiDir,
69
+ apiOnly: options.apiOnly,
70
+ });
71
+ });
72
+
73
+ program.parse();
@@ -0,0 +1,244 @@
1
+ import * as fs from "fs";
2
+ import * as path from "path";
3
+ import { BackendLanguage, SwallowKitConfig } from "../types";
4
+ import { detectFromProject, getCommands } from "../utils/package-manager";
5
+
6
+ const VALID_BACKEND_LANGUAGES: BackendLanguage[] = ["typescript", "csharp", "python"];
7
+
8
+ /**
9
+ * デフォルト設定
10
+ */
11
+ const DEFAULT_CONFIG: SwallowKitConfig = {
12
+ database: {},
13
+ backend: {
14
+ language: "typescript",
15
+ },
16
+ api: {
17
+ endpoint: "/api/_swallowkit",
18
+ cors: {
19
+ origin: "*",
20
+ credentials: true,
21
+ },
22
+ },
23
+ };
24
+
25
+ /**
26
+ * 設定ファイルを読み込み
27
+ */
28
+ export function loadConfig(configPath?: string): SwallowKitConfig {
29
+ const defaultPaths = [
30
+ "swallowkit.config.json",
31
+ "swallowkit.config.js",
32
+ ".swallowkitrc.json",
33
+ ];
34
+
35
+ const paths = configPath ? [configPath] : defaultPaths;
36
+
37
+ for (const filePath of paths) {
38
+ const fullPath = path.resolve(process.cwd(), filePath);
39
+
40
+ if (fs.existsSync(fullPath)) {
41
+ try {
42
+ console.log(`📋 設定ファイルを読み込み: ${filePath}`);
43
+
44
+ if (filePath.endsWith(".json")) {
45
+ const configData = fs.readFileSync(fullPath, "utf-8");
46
+ const userConfig = JSON.parse(configData);
47
+ return mergeConfig(DEFAULT_CONFIG, userConfig);
48
+ } else if (filePath.endsWith(".js")) {
49
+ delete require.cache[fullPath];
50
+ const userConfig = require(fullPath);
51
+ return mergeConfig(DEFAULT_CONFIG, userConfig.default || userConfig);
52
+ }
53
+ } catch (error) {
54
+ console.warn(`⚠️ 設定ファイルの読み込みに失敗: ${filePath}`, error);
55
+ }
56
+ }
57
+ }
58
+
59
+ console.log("📋 デフォルト設定を使用");
60
+ return DEFAULT_CONFIG;
61
+ }
62
+
63
+ /**
64
+ * 設定をマージ
65
+ */
66
+ function mergeConfig(defaultConfig: SwallowKitConfig, userConfig: Partial<SwallowKitConfig>): SwallowKitConfig {
67
+ return {
68
+ database: {
69
+ ...defaultConfig.database,
70
+ ...userConfig.database,
71
+ },
72
+ backend: {
73
+ ...defaultConfig.backend,
74
+ ...userConfig.backend,
75
+ },
76
+ api: {
77
+ ...defaultConfig.api,
78
+ ...userConfig.api,
79
+ cors: {
80
+ ...defaultConfig.api?.cors,
81
+ ...userConfig.api?.cors,
82
+ },
83
+ },
84
+ };
85
+ }
86
+
87
+ /**
88
+ * 設定ファイルを生成
89
+ */
90
+ export function generateConfig(outputPath: string = "swallowkit.config.json"): void {
91
+ const config = {
92
+ $schema: "https://swallowkit.dev/schema.json",
93
+ database: {
94
+ connectionString: "your-cosmos-connection-string",
95
+ databaseName: "SwallowKitDB",
96
+ },
97
+ backend: {
98
+ language: "typescript",
99
+ },
100
+ api: {
101
+ endpoint: "/api/_swallowkit",
102
+ cors: {
103
+ origin: ["http://localhost:3000"],
104
+ credentials: true,
105
+ },
106
+ },
107
+ };
108
+
109
+ fs.writeFileSync(outputPath, JSON.stringify(config, null, 2));
110
+ console.log(`✅ 設定ファイルを生成しました: ${outputPath}`);
111
+ }
112
+
113
+ /**
114
+ * 環境変数からの設定読み込み
115
+ */
116
+ export function loadConfigFromEnv(): Partial<SwallowKitConfig> {
117
+ const config: Partial<SwallowKitConfig> = {};
118
+
119
+ // データベース設定
120
+ if (process.env.SWALLOWKIT_DB_CONNECTION_STRING) {
121
+ config.database = {
122
+ ...config.database,
123
+ connectionString: process.env.SWALLOWKIT_DB_CONNECTION_STRING,
124
+ };
125
+ }
126
+
127
+ if (process.env.SWALLOWKIT_DB_NAME) {
128
+ config.database = {
129
+ ...config.database,
130
+ databaseName: process.env.SWALLOWKIT_DB_NAME,
131
+ };
132
+ }
133
+
134
+ // API設定
135
+ if (process.env.SWALLOWKIT_API_ENDPOINT) {
136
+ config.api = {
137
+ ...config.api,
138
+ endpoint: process.env.SWALLOWKIT_API_ENDPOINT,
139
+ };
140
+ }
141
+
142
+ if (process.env.SWALLOWKIT_BACKEND_LANGUAGE) {
143
+ config.backend = {
144
+ ...config.backend,
145
+ language: process.env.SWALLOWKIT_BACKEND_LANGUAGE as BackendLanguage,
146
+ };
147
+ }
148
+
149
+ return config;
150
+ }
151
+
152
+ export function getBackendLanguage(configPath?: string): BackendLanguage {
153
+ const language = getFullConfig(configPath).backend?.language;
154
+ if (language && VALID_BACKEND_LANGUAGES.includes(language)) {
155
+ return language;
156
+ }
157
+
158
+ return "typescript";
159
+ }
160
+
161
+ /**
162
+ * 完全な設定を取得(ファイル + 環境変数)
163
+ */
164
+ export function getFullConfig(configPath?: string): SwallowKitConfig {
165
+ const fileConfig = loadConfig(configPath);
166
+ const envConfig = loadConfigFromEnv();
167
+
168
+ return mergeConfig(fileConfig, envConfig);
169
+ }
170
+
171
+ /**
172
+ * 設定の検証
173
+ */
174
+ export function validateConfig(config: SwallowKitConfig): { valid: boolean; errors: string[] } {
175
+ const errors: string[] = [];
176
+
177
+ // データベース設定の検証
178
+ if (config.database && !config.database.connectionString) {
179
+ errors.push("Cosmos DB connection string is required");
180
+ }
181
+
182
+ // API設定の検証
183
+ if (config.api?.endpoint && !config.api.endpoint.startsWith("/")) {
184
+ errors.push("API endpoint must start with '/'");
185
+ }
186
+
187
+ if (config.backend?.language && !VALID_BACKEND_LANGUAGES.includes(config.backend.language)) {
188
+ errors.push("Backend language must be one of: typescript, csharp, python");
189
+ }
190
+
191
+ return {
192
+ valid: errors.length === 0,
193
+ errors,
194
+ };
195
+ }
196
+
197
+ /**
198
+ * SwallowKit プロジェクトディレクトリかどうかを検証するための設定ファイルパス一覧
199
+ */
200
+ const SWALLOWKIT_PROJECT_MARKERS = [
201
+ "swallowkit.config.js",
202
+ "swallowkit.config.json",
203
+ ".swallowkitrc.json",
204
+ ];
205
+
206
+ /**
207
+ * 現在のディレクトリが SwallowKit プロジェクトディレクトリかどうかを検証
208
+ * @param projectRoot 検証するディレクトリパス(省略時は process.cwd())
209
+ * @returns プロジェクトが有効な場合は true、無効な場合は false
210
+ */
211
+ export function isSwallowKitProject(projectRoot?: string): boolean {
212
+ const cwd = projectRoot || process.cwd();
213
+
214
+ // swallowkit 設定ファイルの存在をチェック
215
+ for (const marker of SWALLOWKIT_PROJECT_MARKERS) {
216
+ const markerPath = path.resolve(cwd, marker);
217
+ if (fs.existsSync(markerPath)) {
218
+ return true;
219
+ }
220
+ }
221
+
222
+ return false;
223
+ }
224
+
225
+ /**
226
+ * SwallowKit プロジェクトディレクトリかどうかを検証し、無効な場合はエラーメッセージを表示して終了
227
+ * init 以外のコマンドの冒頭で呼び出すこと
228
+ * @param commandName コマンド名(エラーメッセージ用)
229
+ * @param projectRoot 検証するディレクトリパス(省略時は process.cwd())
230
+ */
231
+ export function ensureSwallowKitProject(commandName: string, projectRoot?: string): void {
232
+ if (!isSwallowKitProject(projectRoot)) {
233
+ console.error(`❌ Error: This directory is not a SwallowKit project.`);
234
+ console.error(`\n The '${commandName}' command must be run from a SwallowKit project directory.`);
235
+ console.error(` A SwallowKit project should contain one of the following files:`);
236
+ for (const marker of SWALLOWKIT_PROJECT_MARKERS) {
237
+ console.error(` - ${marker}`);
238
+ }
239
+ const pmCmd = getCommands(detectFromProject());
240
+ console.error(`\n💡 Tip: Run '${pmCmd.dlx} swallowkit init' first to create a new SwallowKit project,`);
241
+ console.error(` or navigate to an existing SwallowKit project directory.`);
242
+ process.exit(1);
243
+ }
244
+ }