swallowkit 1.0.0-beta.9 → 1.0.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.
- package/README.ja.md +87 -181
- package/README.md +87 -238
- package/dist/__tests__/fixtures.d.ts +12 -0
- package/dist/__tests__/fixtures.d.ts.map +1 -1
- package/dist/__tests__/fixtures.js +101 -0
- package/dist/__tests__/fixtures.js.map +1 -1
- package/dist/cli/commands/add-auth.d.ts +15 -0
- package/dist/cli/commands/add-auth.d.ts.map +1 -0
- package/dist/cli/commands/add-auth.js +790 -0
- package/dist/cli/commands/add-auth.js.map +1 -0
- package/dist/cli/commands/add-connector.d.ts +20 -0
- package/dist/cli/commands/add-connector.d.ts.map +1 -0
- package/dist/cli/commands/add-connector.js +164 -0
- package/dist/cli/commands/add-connector.js.map +1 -0
- package/dist/cli/commands/cosmos-worktree-isolation.d.ts +25 -0
- package/dist/cli/commands/cosmos-worktree-isolation.d.ts.map +1 -0
- package/dist/cli/commands/cosmos-worktree-isolation.js +124 -0
- package/dist/cli/commands/cosmos-worktree-isolation.js.map +1 -0
- package/dist/cli/commands/create-model.d.ts +1 -4
- package/dist/cli/commands/create-model.d.ts.map +1 -1
- package/dist/cli/commands/create-model.js +20 -82
- package/dist/cli/commands/create-model.js.map +1 -1
- package/dist/cli/commands/dev-seeds.d.ts +27 -0
- package/dist/cli/commands/dev-seeds.d.ts.map +1 -1
- package/dist/cli/commands/dev-seeds.js +188 -6
- package/dist/cli/commands/dev-seeds.js.map +1 -1
- package/dist/cli/commands/dev.d.ts +30 -0
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +495 -129
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/init.d.ts +69 -1
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +788 -766
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +24 -3
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +408 -189
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts +5 -1
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +335 -58
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +13 -3
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +151 -8
- package/dist/core/config.js.map +1 -1
- package/dist/core/mock/connector-mock-server.d.ts +101 -0
- package/dist/core/mock/connector-mock-server.d.ts.map +1 -0
- package/dist/core/mock/connector-mock-server.js +480 -0
- package/dist/core/mock/connector-mock-server.js.map +1 -0
- package/dist/core/mock/zod-mock-generator.d.ts +14 -0
- package/dist/core/mock/zod-mock-generator.d.ts.map +1 -0
- package/dist/core/mock/zod-mock-generator.js +163 -0
- package/dist/core/mock/zod-mock-generator.js.map +1 -0
- package/dist/core/operations/auth-operations.d.ts +61 -0
- package/dist/core/operations/auth-operations.d.ts.map +1 -0
- package/dist/core/operations/auth-operations.js +272 -0
- package/dist/core/operations/auth-operations.js.map +1 -0
- package/dist/core/operations/create-model.d.ts +15 -0
- package/dist/core/operations/create-model.d.ts.map +1 -0
- package/dist/core/operations/create-model.js +185 -0
- package/dist/core/operations/create-model.js.map +1 -0
- package/dist/core/operations/file-session.d.ts +56 -0
- package/dist/core/operations/file-session.d.ts.map +1 -0
- package/dist/core/operations/file-session.js +203 -0
- package/dist/core/operations/file-session.js.map +1 -0
- package/dist/core/operations/provision-operations.d.ts +52 -0
- package/dist/core/operations/provision-operations.d.ts.map +1 -0
- package/dist/core/operations/provision-operations.js +211 -0
- package/dist/core/operations/provision-operations.js.map +1 -0
- package/dist/core/operations/runtime.d.ts +37 -0
- package/dist/core/operations/runtime.d.ts.map +1 -0
- package/dist/core/operations/runtime.js +248 -0
- package/dist/core/operations/runtime.js.map +1 -0
- package/dist/core/operations/scaffold-apply.d.ts +21 -0
- package/dist/core/operations/scaffold-apply.d.ts.map +1 -0
- package/dist/core/operations/scaffold-apply.js +57 -0
- package/dist/core/operations/scaffold-apply.js.map +1 -0
- package/dist/core/operations/scaffold-machine.d.ts +16 -0
- package/dist/core/operations/scaffold-machine.d.ts.map +1 -0
- package/dist/core/operations/scaffold-machine.js +51 -0
- package/dist/core/operations/scaffold-machine.js.map +1 -0
- package/dist/core/operations/scaffold-plan.d.ts +43 -0
- package/dist/core/operations/scaffold-plan.d.ts.map +1 -0
- package/dist/core/operations/scaffold-plan.js +187 -0
- package/dist/core/operations/scaffold-plan.js.map +1 -0
- package/dist/core/project/agent-instructions.d.ts +29 -0
- package/dist/core/project/agent-instructions.d.ts.map +1 -0
- package/dist/core/project/agent-instructions.js +160 -0
- package/dist/core/project/agent-instructions.js.map +1 -0
- package/dist/core/project/artifacts.d.ts +58 -0
- package/dist/core/project/artifacts.d.ts.map +1 -0
- package/dist/core/project/artifacts.js +179 -0
- package/dist/core/project/artifacts.js.map +1 -0
- package/dist/core/project/boundaries.d.ts +50 -0
- package/dist/core/project/boundaries.d.ts.map +1 -0
- package/dist/core/project/boundaries.js +117 -0
- package/dist/core/project/boundaries.js.map +1 -0
- package/dist/core/project/capabilities.d.ts +58 -0
- package/dist/core/project/capabilities.d.ts.map +1 -0
- package/dist/core/project/capabilities.js +135 -0
- package/dist/core/project/capabilities.js.map +1 -0
- package/dist/core/project/drift.d.ts +29 -0
- package/dist/core/project/drift.d.ts.map +1 -0
- package/dist/core/project/drift.js +190 -0
- package/dist/core/project/drift.js.map +1 -0
- package/dist/core/project/infra.d.ts +49 -0
- package/dist/core/project/infra.d.ts.map +1 -0
- package/dist/core/project/infra.js +167 -0
- package/dist/core/project/infra.js.map +1 -0
- package/dist/core/project/manifest.d.ts +92 -0
- package/dist/core/project/manifest.d.ts.map +1 -0
- package/dist/core/project/manifest.js +321 -0
- package/dist/core/project/manifest.js.map +1 -0
- package/dist/core/project/state.d.ts +15 -0
- package/dist/core/project/state.d.ts.map +1 -0
- package/dist/core/project/state.js +106 -0
- package/dist/core/project/state.js.map +1 -0
- package/dist/core/project/validation.d.ts +20 -0
- package/dist/core/project/validation.d.ts.map +1 -0
- package/dist/core/project/validation.js +274 -0
- package/dist/core/project/validation.js.map +1 -0
- package/dist/core/project/workflows.d.ts +43 -0
- package/dist/core/project/workflows.d.ts.map +1 -0
- package/dist/core/project/workflows.js +299 -0
- package/dist/core/project/workflows.js.map +1 -0
- package/dist/core/scaffold/auth-generator.d.ts +63 -0
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -0
- package/dist/core/scaffold/auth-generator.js +1774 -0
- package/dist/core/scaffold/auth-generator.js.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts +41 -0
- package/dist/core/scaffold/connector-functions-generator.d.ts.map +1 -0
- package/dist/core/scaffold/connector-functions-generator.js +1029 -0
- package/dist/core/scaffold/connector-functions-generator.js.map +1 -0
- package/dist/core/scaffold/functions-generator.d.ts +4 -3
- package/dist/core/scaffold/functions-generator.d.ts.map +1 -1
- package/dist/core/scaffold/functions-generator.js +405 -134
- package/dist/core/scaffold/functions-generator.js.map +1 -1
- package/dist/core/scaffold/model-parser.d.ts +20 -0
- package/dist/core/scaffold/model-parser.d.ts.map +1 -1
- package/dist/core/scaffold/model-parser.js +229 -78
- package/dist/core/scaffold/model-parser.js.map +1 -1
- package/dist/core/scaffold/native-schema-generator.d.ts +19 -0
- package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -0
- package/dist/core/scaffold/native-schema-generator.js +753 -0
- package/dist/core/scaffold/native-schema-generator.js.map +1 -0
- package/dist/core/scaffold/nextjs-generator.d.ts +8 -0
- package/dist/core/scaffold/nextjs-generator.d.ts.map +1 -1
- package/dist/core/scaffold/nextjs-generator.js +152 -8
- package/dist/core/scaffold/nextjs-generator.js.map +1 -1
- package/dist/core/scaffold/ui-generator.d.ts +17 -4
- package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
- package/dist/core/scaffold/ui-generator.js +174 -34
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/core/verify/index.d.ts +69 -0
- package/dist/core/verify/index.d.ts.map +1 -0
- package/dist/core/verify/index.js +412 -0
- package/dist/core/verify/index.js.map +1 -0
- package/dist/machine/contracts.d.ts +24 -0
- package/dist/machine/contracts.d.ts.map +1 -0
- package/dist/machine/contracts.js +3 -0
- package/dist/machine/contracts.js.map +1 -0
- package/dist/machine/errors.d.ts +14 -0
- package/dist/machine/errors.d.ts.map +1 -0
- package/dist/machine/errors.js +42 -0
- package/dist/machine/errors.js.map +1 -0
- package/dist/machine/index.d.ts +3 -0
- package/dist/machine/index.d.ts.map +1 -0
- package/dist/machine/index.js +566 -0
- package/dist/machine/index.js.map +1 -0
- package/dist/mcp/index.d.ts +25 -0
- package/dist/mcp/index.d.ts.map +1 -0
- package/dist/mcp/index.js +425 -0
- package/dist/mcp/index.js.map +1 -0
- package/dist/types/index.d.ts +105 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/utils/package-manager.d.ts +7 -11
- package/dist/utils/package-manager.d.ts.map +1 -1
- package/dist/utils/package-manager.js +42 -17
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/python-uv.d.ts +21 -0
- package/dist/utils/python-uv.d.ts.map +1 -0
- package/dist/utils/python-uv.js +111 -0
- package/dist/utils/python-uv.js.map +1 -0
- package/dist/version.d.ts +2 -0
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +49 -0
- package/dist/version.js.map +1 -0
- package/package.json +15 -17
- package/src/__tests__/__snapshots__/functions-generator.test.ts.snap +716 -22
- package/src/__tests__/__snapshots__/nextjs-generator.test.ts.snap +19 -7
- package/src/__tests__/__snapshots__/ui-generator.test.ts.snap +20 -12
- package/src/__tests__/agent-instructions.test.ts +237 -0
- package/src/__tests__/agent-loop-phase34.test.ts +619 -0
- package/src/__tests__/auth.test.ts +770 -0
- package/src/__tests__/bff-swa-auth.test.ts +275 -0
- package/src/__tests__/config.test.ts +176 -3
- package/src/__tests__/connector-functions-generator.test.ts +288 -0
- package/src/__tests__/connector-mock-server.test.ts +459 -0
- package/src/__tests__/connector-model-bff.test.ts +162 -0
- package/src/__tests__/cosmos-worktree-isolation.test.ts +149 -0
- package/src/__tests__/dev-seeds.test.ts +124 -0
- package/src/__tests__/dev.test.ts +254 -0
- package/src/__tests__/file-session.test.ts +98 -0
- package/src/__tests__/fixtures.ts +101 -0
- package/src/__tests__/functions-generator.test.ts +137 -1
- package/src/__tests__/init.test.ts +366 -2
- package/src/__tests__/jest-globals.d.ts +8 -0
- package/src/__tests__/machine.test.ts +371 -0
- package/src/__tests__/mcp.test.ts +253 -0
- package/src/__tests__/model-parser.test.ts +142 -0
- package/src/__tests__/multi-auth.test.ts +160 -0
- package/src/__tests__/nextjs-generator.test.ts +8 -0
- package/src/__tests__/package-manager.test.ts +59 -4
- package/src/__tests__/plan-apply.test.ts +499 -0
- package/src/__tests__/python-uv.test.ts +48 -0
- package/src/__tests__/scaffold.test.ts +287 -24
- package/src/__tests__/tsconfig.json +15 -0
- package/src/__tests__/ui-generator.test.ts +104 -0
- package/src/__tests__/zod-mock-generator.test.ts +132 -0
- package/src/cli/commands/add-auth.ts +853 -0
- package/src/cli/commands/add-connector.ts +159 -0
- package/src/cli/commands/cosmos-worktree-isolation.ts +130 -0
- package/src/cli/commands/create-model.ts +21 -100
- package/src/cli/commands/dev-seeds.ts +278 -7
- package/src/cli/commands/dev.ts +607 -160
- package/src/cli/commands/init.ts +851 -786
- package/src/cli/commands/scaffold.ts +531 -236
- package/src/cli/index.ts +338 -60
- package/src/core/config.ts +145 -9
- package/src/core/mock/connector-mock-server.ts +555 -0
- package/src/core/mock/zod-mock-generator.ts +205 -0
- package/src/core/operations/auth-operations.ts +360 -0
- package/src/core/operations/create-model.ts +191 -0
- package/src/core/operations/file-session.ts +222 -0
- package/src/core/operations/provision-operations.ts +297 -0
- package/src/core/operations/runtime.ts +258 -0
- package/src/core/operations/scaffold-apply.ts +106 -0
- package/src/core/operations/scaffold-machine.ts +77 -0
- package/src/core/operations/scaffold-plan.ts +215 -0
- package/src/core/project/agent-instructions.ts +167 -0
- package/src/core/project/agent-templates/AGENTS.md +504 -0
- package/src/core/project/agent-templates/CLAUDE.md +31 -0
- package/src/core/project/agent-templates/azure-functions.instructions.md +22 -0
- package/src/core/project/agent-templates/bff-routes.instructions.md +18 -0
- package/src/core/project/agent-templates/copilot-instructions.md +27 -0
- package/src/core/project/agent-templates/shared-models.instructions.md +72 -0
- package/src/core/project/artifacts.ts +205 -0
- package/src/core/project/boundaries.ts +170 -0
- package/src/core/project/capabilities.ts +193 -0
- package/src/core/project/drift.ts +203 -0
- package/src/core/project/infra.ts +196 -0
- package/src/core/project/manifest.ts +402 -0
- package/src/core/project/state.ts +77 -0
- package/src/core/project/validation.ts +295 -0
- package/src/core/project/workflows.ts +295 -0
- package/src/core/scaffold/auth-generator.ts +1824 -0
- package/src/core/scaffold/connector-functions-generator.ts +1133 -0
- package/src/core/scaffold/functions-generator.ts +432 -134
- package/src/core/scaffold/model-parser.ts +244 -90
- package/src/core/scaffold/native-schema-generator.ts +904 -0
- package/src/core/scaffold/nextjs-generator.ts +174 -9
- package/src/core/scaffold/ui-generator.ts +191 -36
- package/src/core/verify/index.ts +468 -0
- package/src/machine/contracts.ts +33 -0
- package/src/machine/errors.ts +45 -0
- package/src/machine/index.ts +690 -0
- package/src/mcp/index.ts +423 -0
- package/src/types/index.ts +137 -0
- package/src/utils/package-manager.ts +41 -19
- package/src/utils/python-uv.ts +96 -0
- package/src/version.ts +13 -0
|
@@ -0,0 +1,159 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SwallowKit Add-Connector コマンド
|
|
3
|
+
* swallowkit.config.js にコネクタ設定を追加する
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import * as fs from "fs";
|
|
7
|
+
import { detectFromProject, getCommands } from "../../utils/package-manager";
|
|
8
|
+
import * as path from "path";
|
|
9
|
+
import { ensureSwallowKitProject } from "../../core/config";
|
|
10
|
+
import { ApiConnectorConfig, ConnectorDefinition } from "../../types";
|
|
11
|
+
import { syncProjectManifest } from "../../core/project/manifest";
|
|
12
|
+
|
|
13
|
+
interface AddConnectorOptions {
|
|
14
|
+
name: string;
|
|
15
|
+
type: "rdb" | "api";
|
|
16
|
+
provider?: "mysql" | "postgres" | "sqlserver";
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* add-connector コマンド
|
|
21
|
+
*/
|
|
22
|
+
export async function addConnectorCommand(options: AddConnectorOptions) {
|
|
23
|
+
ensureSwallowKitProject("add-connector");
|
|
24
|
+
|
|
25
|
+
console.log(`🔌 SwallowKit Add-Connector: Adding '${options.name}' connector...\n`);
|
|
26
|
+
|
|
27
|
+
const configPath = findConfigFile();
|
|
28
|
+
if (!configPath) {
|
|
29
|
+
console.error("❌ swallowkit.config.js not found. Run 'swallowkit init' first.");
|
|
30
|
+
process.exit(1);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
// Build connector definition
|
|
34
|
+
const connectorDef = buildConnectorDefinition(options);
|
|
35
|
+
|
|
36
|
+
// Update config file
|
|
37
|
+
updateConfigWithConnector(configPath, options.name, connectorDef);
|
|
38
|
+
await syncProjectManifest();
|
|
39
|
+
|
|
40
|
+
console.log(`\n✅ Connector '${options.name}' added successfully!`);
|
|
41
|
+
console.log("\n📝 Next steps:");
|
|
42
|
+
console.log(` 1. Review the connector settings in ${configPath}`);
|
|
43
|
+
console.log(` 2. Set the required environment variables in functions/local.settings.json`);
|
|
44
|
+
console.log(` 3. Create models with: ${getCommands(detectFromProject()).exec} swallowkit create-model <name> --connector=${options.name}`);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function findConfigFile(): string | null {
|
|
48
|
+
const candidates = ["swallowkit.config.js", "swallowkit.config.json", ".swallowkitrc.json"];
|
|
49
|
+
for (const candidate of candidates) {
|
|
50
|
+
const fullPath = path.resolve(process.cwd(), candidate);
|
|
51
|
+
if (fs.existsSync(fullPath)) {
|
|
52
|
+
return fullPath;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return null;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
function buildConnectorDefinition(options: AddConnectorOptions): ConnectorDefinition {
|
|
59
|
+
const name = options.name.toUpperCase().replace(/[^A-Z0-9]/g, "_");
|
|
60
|
+
|
|
61
|
+
if (options.type === "rdb") {
|
|
62
|
+
return {
|
|
63
|
+
type: "rdb",
|
|
64
|
+
provider: options.provider || "mysql",
|
|
65
|
+
connectionEnvVar: `${name}_CONNECTION_STRING`,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return {
|
|
70
|
+
type: "api",
|
|
71
|
+
baseUrlEnvVar: `${name}_API_BASE_URL`,
|
|
72
|
+
auth: {
|
|
73
|
+
type: "apiKey",
|
|
74
|
+
envVar: `${name}_API_KEY`,
|
|
75
|
+
placement: "query",
|
|
76
|
+
paramName: "apiKey",
|
|
77
|
+
},
|
|
78
|
+
};
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* swallowkit.config.js にコネクタ設定を追加
|
|
83
|
+
*/
|
|
84
|
+
export function updateConfigWithConnector(
|
|
85
|
+
configPath: string,
|
|
86
|
+
connectorName: string,
|
|
87
|
+
connectorDef: ConnectorDefinition
|
|
88
|
+
): void {
|
|
89
|
+
const content = fs.readFileSync(configPath, "utf-8");
|
|
90
|
+
|
|
91
|
+
if (configPath.endsWith(".json")) {
|
|
92
|
+
// JSON config
|
|
93
|
+
const config = JSON.parse(content);
|
|
94
|
+
if (!config.connectors) {
|
|
95
|
+
config.connectors = {};
|
|
96
|
+
}
|
|
97
|
+
config.connectors[connectorName] = connectorDef;
|
|
98
|
+
fs.writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8");
|
|
99
|
+
console.log(`✅ Updated: ${configPath}`);
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
// JS config — append connectors section
|
|
104
|
+
if (content.includes("connectors:") || content.includes("connectors :")) {
|
|
105
|
+
console.log(`⚠️ 'connectors' section already exists in ${configPath}. Please add the connector manually:`);
|
|
106
|
+
console.log(formatConnectorSnippet(connectorName, connectorDef));
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Find the last property before the closing of module.exports
|
|
111
|
+
const closingBraceIdx = content.lastIndexOf("}");
|
|
112
|
+
if (closingBraceIdx === -1) {
|
|
113
|
+
console.error("❌ Could not parse config file structure. Please add the connector manually:");
|
|
114
|
+
console.log(formatConnectorSnippet(connectorName, connectorDef));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Check if we need a comma before inserting
|
|
119
|
+
const beforeClosing = content.substring(0, closingBraceIdx).trimEnd();
|
|
120
|
+
const needsComma = !beforeClosing.endsWith(",") && !beforeClosing.endsWith("{");
|
|
121
|
+
|
|
122
|
+
const connectorBlock = generateConnectorJSBlock(connectorName, connectorDef);
|
|
123
|
+
const insertion = `${needsComma ? "," : ""}\n // コネクタ定義\n connectors: {\n${connectorBlock}\n },\n`;
|
|
124
|
+
|
|
125
|
+
const newContent = content.substring(0, closingBraceIdx) + insertion + content.substring(closingBraceIdx);
|
|
126
|
+
fs.writeFileSync(configPath, newContent, "utf-8");
|
|
127
|
+
console.log(`✅ Updated: ${configPath}`);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function generateConnectorJSBlock(name: string, def: ConnectorDefinition): string {
|
|
131
|
+
if (def.type === "rdb") {
|
|
132
|
+
return ` ${name}: {
|
|
133
|
+
type: 'rdb',
|
|
134
|
+
provider: '${def.provider}',
|
|
135
|
+
connectionEnvVar: '${def.connectionEnvVar}',
|
|
136
|
+
},`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
const apiDef: ApiConnectorConfig = def;
|
|
140
|
+
let authBlock = "";
|
|
141
|
+
if (apiDef.auth) {
|
|
142
|
+
authBlock = `
|
|
143
|
+
auth: {
|
|
144
|
+
type: '${apiDef.auth.type}',
|
|
145
|
+
envVar: '${apiDef.auth.envVar}',
|
|
146
|
+
placement: '${apiDef.auth.placement || "query"}',
|
|
147
|
+
paramName: '${apiDef.auth.paramName || "apiKey"}',
|
|
148
|
+
},`;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
return ` ${name}: {
|
|
152
|
+
type: 'api',
|
|
153
|
+
baseUrlEnvVar: '${apiDef.baseUrlEnvVar}',${authBlock}
|
|
154
|
+
},`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function formatConnectorSnippet(name: string, def: ConnectorDefinition): string {
|
|
158
|
+
return `\n ${name}: ${JSON.stringify(def, null, 4)}\n`;
|
|
159
|
+
}
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
import { execFileSync } from "child_process";
|
|
2
|
+
import { createHash } from "crypto";
|
|
3
|
+
import * as fs from "fs";
|
|
4
|
+
import * as path from "path";
|
|
5
|
+
|
|
6
|
+
const WORKTREE_HASH_LENGTH = 8;
|
|
7
|
+
|
|
8
|
+
export interface GitWorktreeInfo {
|
|
9
|
+
worktreeRoot: string;
|
|
10
|
+
gitDir: string;
|
|
11
|
+
gitCommonDir: string;
|
|
12
|
+
isLinkedWorktree: boolean;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface CosmosDatabaseNameResolution {
|
|
16
|
+
databaseName: string;
|
|
17
|
+
worktreeIsolationEnabled: boolean;
|
|
18
|
+
worktreeRoot?: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export type GitCommandRunner = (args: string[], cwd: string) => string;
|
|
22
|
+
|
|
23
|
+
const runGitCommand: GitCommandRunner = (args, cwd) =>
|
|
24
|
+
execFileSync("git", args, {
|
|
25
|
+
cwd,
|
|
26
|
+
encoding: "utf-8",
|
|
27
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
28
|
+
windowsHide: true,
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolve Git's worktree metadata without relying on whether .git is a file or
|
|
33
|
+
* directory. A linked worktree has a per-worktree Git directory that differs
|
|
34
|
+
* from the repository's common Git directory.
|
|
35
|
+
*/
|
|
36
|
+
export function resolveGitWorktreeInfo(
|
|
37
|
+
cwd: string = process.cwd(),
|
|
38
|
+
runGit: GitCommandRunner = runGitCommand
|
|
39
|
+
): GitWorktreeInfo | null {
|
|
40
|
+
try {
|
|
41
|
+
const output = runGit(
|
|
42
|
+
[
|
|
43
|
+
"rev-parse",
|
|
44
|
+
"--show-toplevel",
|
|
45
|
+
"--absolute-git-dir",
|
|
46
|
+
"--git-common-dir",
|
|
47
|
+
],
|
|
48
|
+
cwd
|
|
49
|
+
);
|
|
50
|
+
const lines = output.split(/\r?\n/).map((line) => line.trim());
|
|
51
|
+
const [worktreeRootOutput, gitDirOutput, gitCommonDirOutput] = lines;
|
|
52
|
+
|
|
53
|
+
if (!worktreeRootOutput || !gitDirOutput || !gitCommonDirOutput) {
|
|
54
|
+
return null;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
const worktreeRoot = canonicalizePath(worktreeRootOutput, cwd);
|
|
58
|
+
const gitDir = canonicalizePath(gitDirOutput, cwd);
|
|
59
|
+
const gitCommonDir = canonicalizePath(gitCommonDirOutput, cwd);
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
worktreeRoot,
|
|
63
|
+
gitDir,
|
|
64
|
+
gitCommonDir,
|
|
65
|
+
isLinkedWorktree: gitDir !== gitCommonDir,
|
|
66
|
+
};
|
|
67
|
+
} catch {
|
|
68
|
+
return null;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Produce a stable, database-safe identifier for a canonical worktree path.
|
|
74
|
+
*/
|
|
75
|
+
export function createWorktreePathHash(worktreeRoot: string): string {
|
|
76
|
+
return createHash("sha256")
|
|
77
|
+
.update(canonicalizePath(worktreeRoot), "utf-8")
|
|
78
|
+
.digest("hex")
|
|
79
|
+
.slice(0, WORKTREE_HASH_LENGTH);
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export function applyCosmosDatabaseWorktreeIsolation(
|
|
83
|
+
baseDatabaseName: string,
|
|
84
|
+
worktreeInfo: GitWorktreeInfo | null
|
|
85
|
+
): CosmosDatabaseNameResolution {
|
|
86
|
+
if (!worktreeInfo?.isLinkedWorktree) {
|
|
87
|
+
return {
|
|
88
|
+
databaseName: baseDatabaseName,
|
|
89
|
+
worktreeIsolationEnabled: false,
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const suffix = createWorktreePathHash(worktreeInfo.worktreeRoot);
|
|
94
|
+
return {
|
|
95
|
+
databaseName: `${baseDatabaseName}_${suffix}`,
|
|
96
|
+
worktreeIsolationEnabled: true,
|
|
97
|
+
worktreeRoot: worktreeInfo.worktreeRoot,
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export function resolveCosmosDatabaseNameForWorktree(
|
|
102
|
+
baseDatabaseName: string,
|
|
103
|
+
cwd: string = process.cwd(),
|
|
104
|
+
runGit: GitCommandRunner = runGitCommand
|
|
105
|
+
): CosmosDatabaseNameResolution {
|
|
106
|
+
return applyCosmosDatabaseWorktreeIsolation(
|
|
107
|
+
baseDatabaseName,
|
|
108
|
+
resolveGitWorktreeInfo(cwd, runGit)
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
function canonicalizePath(
|
|
113
|
+
value: string,
|
|
114
|
+
basePath: string = process.cwd()
|
|
115
|
+
): string {
|
|
116
|
+
const absolutePath = path.resolve(basePath, value);
|
|
117
|
+
let canonicalPath = absolutePath;
|
|
118
|
+
|
|
119
|
+
try {
|
|
120
|
+
canonicalPath = fs.realpathSync.native(absolutePath);
|
|
121
|
+
} catch {
|
|
122
|
+
// Git metadata can disappear between discovery and normalization. The
|
|
123
|
+
// normalized absolute path remains a stable fallback for this invocation.
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const normalizedPath = path.normalize(canonicalPath).normalize("NFC");
|
|
127
|
+
return process.platform === "win32"
|
|
128
|
+
? normalizedPath.toLowerCase()
|
|
129
|
+
: normalizedPath;
|
|
130
|
+
}
|
|
@@ -1,41 +1,11 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* SwallowKit Create-Model コマンド
|
|
3
|
-
* Zod モデルの雛形を生成
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
import * as fs from "fs";
|
|
7
|
-
import * as path from "path";
|
|
8
1
|
import * as readline from "readline";
|
|
9
|
-
import {
|
|
10
|
-
import { ensureSwallowKitProject } from "../../core/config";
|
|
2
|
+
import { createModelOperation } from "../../core/operations/create-model";
|
|
11
3
|
import { detectFromProject, getCommands } from "../../utils/package-manager";
|
|
12
4
|
|
|
13
5
|
interface CreateModelOptions {
|
|
14
6
|
names: string[]; // モデル名のリスト(例: ["todo", "user", "post"])
|
|
15
7
|
modelsDir?: string; // モデルディレクトリ(デフォルト: "shared/models")
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* モデルテンプレートを生成
|
|
20
|
-
*/
|
|
21
|
-
function generateModelTemplate(modelName: string): string {
|
|
22
|
-
const pascalName = toPascalCase(modelName);
|
|
23
|
-
|
|
24
|
-
return `import { z } from 'zod/v4';
|
|
25
|
-
|
|
26
|
-
// ${pascalName} model (Zod official pattern: same name for value and type)
|
|
27
|
-
export const ${pascalName} = z.object({
|
|
28
|
-
id: z.string(),
|
|
29
|
-
name: z.string().min(1),
|
|
30
|
-
createdAt: z.string().optional(),
|
|
31
|
-
updatedAt: z.string().optional(),
|
|
32
|
-
});
|
|
33
|
-
|
|
34
|
-
export type ${pascalName} = z.infer<typeof ${pascalName}>;
|
|
35
|
-
|
|
36
|
-
// Display name for UI
|
|
37
|
-
export const displayName = '${pascalName}';
|
|
38
|
-
`;
|
|
8
|
+
connector?: string; // コネクタ名(例: "mysql", "backlog")
|
|
39
9
|
}
|
|
40
10
|
|
|
41
11
|
/**
|
|
@@ -59,83 +29,34 @@ function askConfirmation(question: string): Promise<boolean> {
|
|
|
59
29
|
* create-model コマンド
|
|
60
30
|
*/
|
|
61
31
|
export async function createModelCommand(options: CreateModelOptions) {
|
|
62
|
-
// SwallowKit プロジェクトディレクトリかどうかを検証
|
|
63
|
-
ensureSwallowKitProject("create-model");
|
|
64
|
-
|
|
65
32
|
console.log("🏗️ SwallowKit Create-Model: Generating model templates...\n");
|
|
66
33
|
|
|
67
|
-
const
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
const created: string[] = [];
|
|
76
|
-
const skipped: string[] = [];
|
|
77
|
-
|
|
78
|
-
for (const name of options.names) {
|
|
79
|
-
const kebabName = name.toLowerCase().replace(/[^a-z0-9]+/g, '-');
|
|
80
|
-
const filePath = path.join(modelsDir, `${kebabName}.ts`);
|
|
81
|
-
const pascalName = toPascalCase(name);
|
|
82
|
-
|
|
83
|
-
// 既存ファイルチェック
|
|
84
|
-
if (fs.existsSync(filePath)) {
|
|
85
|
-
const shouldOverwrite = await askConfirmation(
|
|
86
|
-
`⚠️ File ${filePath} already exists. Overwrite? (y/N): `
|
|
87
|
-
);
|
|
88
|
-
|
|
89
|
-
if (!shouldOverwrite) {
|
|
90
|
-
console.log(`⏭️ Skipped: ${kebabName}.ts`);
|
|
91
|
-
skipped.push(kebabName);
|
|
92
|
-
continue;
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// モデルファイルを生成
|
|
97
|
-
const content = generateModelTemplate(name);
|
|
98
|
-
fs.writeFileSync(filePath, content);
|
|
99
|
-
console.log(`✅ Created: ${filePath}`);
|
|
100
|
-
created.push(kebabName);
|
|
101
|
-
|
|
102
|
-
// shared/index.ts に re-export を追加
|
|
103
|
-
updateSharedIndex(kebabName, pascalName);
|
|
104
|
-
}
|
|
34
|
+
const result = await createModelOperation({
|
|
35
|
+
names: options.names,
|
|
36
|
+
modelsDir: options.modelsDir,
|
|
37
|
+
connector: options.connector,
|
|
38
|
+
overwriteMode: "prompt",
|
|
39
|
+
confirmOverwrite: async (filePath) => askConfirmation(`⚠️ File ${filePath} already exists. Overwrite? (y/N): `),
|
|
40
|
+
});
|
|
105
41
|
|
|
106
42
|
// サマリー表示
|
|
107
43
|
console.log("\n📋 Summary:");
|
|
108
|
-
if (
|
|
109
|
-
console.log(`
|
|
44
|
+
if (result.connectorType && options.connector) {
|
|
45
|
+
console.log(` 🔌 Connector: ${options.connector} (${result.connectorType})`);
|
|
46
|
+
}
|
|
47
|
+
if (result.createdFiles.length > 0) {
|
|
48
|
+
console.log(` ✅ Created ${result.createdFiles.length} model(s): ${result.createdFiles.join(", ")}`);
|
|
49
|
+
}
|
|
50
|
+
if (result.skippedFiles.length > 0) {
|
|
51
|
+
console.log(` ⏭️ Skipped ${result.skippedFiles.length} model(s): ${result.skippedFiles.join(", ")}`);
|
|
110
52
|
}
|
|
111
|
-
if (
|
|
112
|
-
console.log(
|
|
53
|
+
if (result.updatedIndex) {
|
|
54
|
+
console.log(" 📦 Updated shared/index.ts");
|
|
113
55
|
}
|
|
114
56
|
|
|
115
|
-
if (
|
|
57
|
+
if (result.createdFiles.length > 0) {
|
|
116
58
|
console.log("\n📝 Next steps:");
|
|
117
59
|
console.log(" 1. Customize the generated model fields in shared/models/");
|
|
118
|
-
console.log(` 2. Run '${getCommands(detectFromProject()).
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
/**
|
|
123
|
-
* shared/index.ts に re-export エントリを追加
|
|
124
|
-
*/
|
|
125
|
-
function updateSharedIndex(kebabName: string, pascalName: string): void {
|
|
126
|
-
const indexPath = path.join("shared", "index.ts");
|
|
127
|
-
|
|
128
|
-
if (!fs.existsSync(indexPath)) {
|
|
129
|
-
return;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
const content = fs.readFileSync(indexPath, "utf-8");
|
|
133
|
-
const exportLine = `export { ${pascalName} } from './models/${kebabName}';`;
|
|
134
|
-
|
|
135
|
-
// 既に存在する場合はスキップ
|
|
136
|
-
if (content.includes(exportLine)) {
|
|
137
|
-
return;
|
|
60
|
+
console.log(` 2. Run '${getCommands(detectFromProject()).exec} swallowkit scaffold <model>' to generate CRUD code`);
|
|
138
61
|
}
|
|
139
|
-
|
|
140
|
-
fs.appendFileSync(indexPath, exportLine + "\n");
|
|
141
62
|
}
|