swallowkit 2.0.0-alpha.1 → 2.0.0-alpha.10
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 +14 -0
- package/README.md +14 -0
- package/dist/cli/commands/add-auth.js +37 -6
- package/dist/cli/commands/add-auth.js.map +1 -1
- package/dist/cli/commands/configure-mcp.d.ts +12 -0
- package/dist/cli/commands/configure-mcp.d.ts.map +1 -0
- package/dist/cli/commands/configure-mcp.js +42 -0
- package/dist/cli/commands/configure-mcp.js.map +1 -0
- package/dist/cli/commands/dev.d.ts +2 -2
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +39 -27
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/init.d.ts +8 -2
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +67 -132
- package/dist/cli/commands/init.js.map +1 -1
- package/dist/cli/commands/migrations.d.ts.map +1 -1
- package/dist/cli/commands/migrations.js +25 -0
- package/dist/cli/commands/migrations.js.map +1 -1
- package/dist/cli/commands/provision.d.ts +5 -0
- package/dist/cli/commands/provision.d.ts.map +1 -1
- package/dist/cli/commands/provision.js +278 -55
- package/dist/cli/commands/provision.js.map +1 -1
- package/dist/cli/commands/scaffold.d.ts +4 -0
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +85 -3
- package/dist/cli/commands/scaffold.js.map +1 -1
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.d.ts.map +1 -1
- package/dist/cli/index.js +43 -5
- package/dist/cli/index.js.map +1 -1
- package/dist/core/operations/create-model.d.ts +2 -0
- package/dist/core/operations/create-model.d.ts.map +1 -1
- package/dist/core/operations/create-model.js +60 -8
- package/dist/core/operations/create-model.js.map +1 -1
- package/dist/core/operations/migration-generator.d.ts.map +1 -1
- package/dist/core/operations/migration-generator.js +12 -1
- package/dist/core/operations/migration-generator.js.map +1 -1
- package/dist/core/operations/model-migration.d.ts +22 -0
- package/dist/core/operations/model-migration.d.ts.map +1 -0
- package/dist/core/operations/model-migration.js +36 -0
- package/dist/core/operations/model-migration.js.map +1 -0
- package/dist/core/operations/provision-deployment.d.ts +52 -0
- package/dist/core/operations/provision-deployment.d.ts.map +1 -0
- package/dist/core/operations/provision-deployment.js +164 -0
- package/dist/core/operations/provision-deployment.js.map +1 -0
- package/dist/core/operations/provision-operations.d.ts +62 -6
- package/dist/core/operations/provision-operations.d.ts.map +1 -1
- package/dist/core/operations/provision-operations.js +653 -115
- package/dist/core/operations/provision-operations.js.map +1 -1
- package/dist/core/operations/scaffold-apply.d.ts +1 -0
- package/dist/core/operations/scaffold-apply.d.ts.map +1 -1
- package/dist/core/operations/scaffold-apply.js +1 -0
- package/dist/core/operations/scaffold-apply.js.map +1 -1
- package/dist/core/operations/scaffold-machine.d.ts +1 -0
- package/dist/core/operations/scaffold-machine.d.ts.map +1 -1
- package/dist/core/operations/scaffold-machine.js.map +1 -1
- package/dist/core/operations/scaffold-plan.d.ts +2 -0
- package/dist/core/operations/scaffold-plan.d.ts.map +1 -1
- package/dist/core/operations/scaffold-plan.js +3 -1
- package/dist/core/operations/scaffold-plan.js.map +1 -1
- package/dist/core/project/agent-instructions.d.ts.map +1 -1
- package/dist/core/project/agent-instructions.js +4 -1
- package/dist/core/project/agent-instructions.js.map +1 -1
- package/dist/core/project/boundaries.d.ts +5 -2
- package/dist/core/project/boundaries.d.ts.map +1 -1
- package/dist/core/project/boundaries.js +51 -20
- package/dist/core/project/boundaries.js.map +1 -1
- package/dist/core/project/capabilities.d.ts +10 -0
- package/dist/core/project/capabilities.d.ts.map +1 -1
- package/dist/core/project/capabilities.js +38 -6
- package/dist/core/project/capabilities.js.map +1 -1
- package/dist/core/project/home-page.d.ts +4 -0
- package/dist/core/project/home-page.d.ts.map +1 -0
- package/dist/core/project/home-page.js +113 -0
- package/dist/core/project/home-page.js.map +1 -0
- package/dist/core/project/mcp-config.d.ts +26 -0
- package/dist/core/project/mcp-config.d.ts.map +1 -0
- package/dist/core/project/mcp-config.js +117 -0
- package/dist/core/project/mcp-config.js.map +1 -0
- package/dist/core/project/react-project.d.ts +1 -1
- package/dist/core/project/react-project.d.ts.map +1 -1
- package/dist/core/project/react-project.js +46 -25
- package/dist/core/project/react-project.js.map +1 -1
- package/dist/core/project/state.d.ts +7 -0
- package/dist/core/project/state.d.ts.map +1 -1
- package/dist/core/project/state.js +86 -0
- package/dist/core/project/state.js.map +1 -1
- package/dist/core/project/workflows.d.ts.map +1 -1
- package/dist/core/project/workflows.js +53 -7
- package/dist/core/project/workflows.js.map +1 -1
- package/dist/core/scaffold/auth-generator.d.ts.map +1 -1
- package/dist/core/scaffold/auth-generator.js +26 -27
- package/dist/core/scaffold/auth-generator.js.map +1 -1
- package/dist/core/scaffold/model-parser.d.ts +23 -0
- package/dist/core/scaffold/model-parser.d.ts.map +1 -1
- package/dist/core/scaffold/model-parser.js +407 -137
- package/dist/core/scaffold/model-parser.js.map +1 -1
- package/dist/core/scaffold/native-schema-generator.d.ts +13 -0
- package/dist/core/scaffold/native-schema-generator.d.ts.map +1 -1
- package/dist/core/scaffold/native-schema-generator.js +294 -91
- package/dist/core/scaffold/native-schema-generator.js.map +1 -1
- package/dist/core/scaffold/openapi-generator.d.ts +5 -0
- package/dist/core/scaffold/openapi-generator.d.ts.map +1 -1
- package/dist/core/scaffold/openapi-generator.js +53 -3
- package/dist/core/scaffold/openapi-generator.js.map +1 -1
- package/dist/core/scaffold/ui-generator.d.ts +0 -3
- package/dist/core/scaffold/ui-generator.d.ts.map +1 -1
- package/dist/core/scaffold/ui-generator.js +68 -7
- package/dist/core/scaffold/ui-generator.js.map +1 -1
- package/dist/core/verify/index.d.ts +4 -3
- package/dist/core/verify/index.d.ts.map +1 -1
- package/dist/core/verify/index.js +122 -5
- package/dist/core/verify/index.js.map +1 -1
- package/dist/machine/contracts.d.ts +1 -0
- package/dist/machine/contracts.d.ts.map +1 -1
- package/dist/machine/errors.d.ts +3 -2
- package/dist/machine/errors.d.ts.map +1 -1
- package/dist/machine/errors.js +2 -1
- package/dist/machine/errors.js.map +1 -1
- package/dist/machine/index.d.ts.map +1 -1
- package/dist/machine/index.js +59 -28
- package/dist/machine/index.js.map +1 -1
- package/dist/mcp/index.d.ts +6 -4
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +210 -25
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/version-selection.d.ts +55 -0
- package/dist/mcp/version-selection.d.ts.map +1 -0
- package/dist/mcp/version-selection.js +152 -0
- package/dist/mcp/version-selection.js.map +1 -0
- package/dist/utils/azure-cli.d.ts +56 -0
- package/dist/utils/azure-cli.d.ts.map +1 -0
- package/dist/utils/azure-cli.js +326 -0
- package/dist/utils/azure-cli.js.map +1 -0
- package/dist/utils/azure-diagnostics.d.ts +16 -0
- package/dist/utils/azure-diagnostics.d.ts.map +1 -0
- package/dist/utils/azure-diagnostics.js +68 -0
- package/dist/utils/azure-diagnostics.js.map +1 -0
- package/dist/utils/package-manager.js +2 -2
- package/dist/utils/package-manager.js.map +1 -1
- package/dist/utils/python-uv.d.ts +5 -7
- package/dist/utils/python-uv.d.ts.map +1 -1
- package/dist/utils/python-uv.js +50 -24
- package/dist/utils/python-uv.js.map +1 -1
- package/dist/utils/react-dev.d.ts +4 -0
- package/dist/utils/react-dev.d.ts.map +1 -0
- package/dist/utils/react-dev.js +35 -0
- package/dist/utils/react-dev.js.map +1 -0
- package/dist/utils/semver.d.ts +14 -0
- package/dist/utils/semver.d.ts.map +1 -0
- package/dist/utils/semver.js +61 -0
- package/dist/utils/semver.js.map +1 -0
- package/package.json +6 -3
- package/src/__tests__/__snapshots__/boundaries.test.ts.snap +154 -0
- package/src/__tests__/agent-instructions.test.ts +5 -0
- package/src/__tests__/agent-loop-phase34.test.ts +143 -8
- package/src/__tests__/auth.test.ts +9 -0
- package/src/__tests__/azure-cli.test.ts +202 -0
- package/src/__tests__/boundaries.test.ts +42 -0
- package/src/__tests__/csharp-schema.test.ts +261 -0
- package/src/__tests__/dev.test.ts +13 -6
- package/src/__tests__/fixtures/az wrapper.cmd +2 -0
- package/src/__tests__/fixtures/azure-cli.cjs +153 -0
- package/src/__tests__/fixtures/provision-runner.cjs +28 -0
- package/src/__tests__/generated-project-matrix.test.ts +789 -0
- package/src/__tests__/home-page.test.ts +50 -0
- package/src/__tests__/init.test.ts +116 -0
- package/src/__tests__/mcp-version.test.ts +262 -0
- package/src/__tests__/mcp.test.ts +120 -3
- package/src/__tests__/multi-auth.test.ts +115 -4
- package/src/__tests__/package-manager.test.ts +17 -2
- package/src/__tests__/plan-apply.test.ts +179 -0
- package/src/__tests__/provision-runtime.test.ts +722 -0
- package/src/__tests__/python-uv.test.ts +50 -14
- package/src/__tests__/python-venv.test.ts +48 -0
- package/src/__tests__/react-dev.test.ts +72 -0
- package/src/__tests__/react.test.ts +19 -0
- package/src/__tests__/schema-analysis.test.ts +329 -0
- package/src/cli/commands/add-auth.ts +36 -6
- package/src/cli/commands/configure-mcp.ts +54 -0
- package/src/cli/commands/dev.ts +40 -31
- package/src/cli/commands/init.ts +73 -138
- package/src/cli/commands/migrations.ts +22 -0
- package/src/cli/commands/provision.ts +294 -56
- package/src/cli/commands/scaffold.ts +105 -3
- package/src/cli/index.ts +40 -7
- package/src/core/operations/create-model.ts +51 -13
- package/src/core/operations/migration-generator.ts +14 -1
- package/src/core/operations/model-migration.ts +52 -0
- package/src/core/operations/provision-deployment.ts +183 -0
- package/src/core/operations/provision-operations.ts +662 -154
- package/src/core/operations/scaffold-apply.ts +2 -0
- package/src/core/operations/scaffold-machine.ts +1 -0
- package/src/core/operations/scaffold-plan.ts +5 -1
- package/src/core/project/agent-instructions.ts +4 -1
- package/src/core/project/agent-templates/AGENTS.md +89 -6
- package/src/core/project/agent-templates/CLAUDE.md +14 -1
- package/src/core/project/agent-templates/copilot-instructions.md +15 -1
- package/src/core/project/agent-templates/shared-models.instructions.md +11 -3
- package/src/core/project/boundaries.ts +62 -20
- package/src/core/project/capabilities.ts +49 -6
- package/src/core/project/home-page.ts +114 -0
- package/src/core/project/mcp-config.ts +84 -0
- package/src/core/project/react-project.ts +50 -28
- package/src/core/project/state.ts +70 -0
- package/src/core/project/workflows.ts +53 -7
- package/src/core/scaffold/auth-generator.ts +26 -27
- package/src/core/scaffold/model-parser.ts +413 -129
- package/src/core/scaffold/native-schema-generator.ts +319 -103
- package/src/core/scaffold/openapi-generator.ts +63 -5
- package/src/core/scaffold/ui-generator.ts +70 -8
- package/src/core/verify/index.ts +118 -6
- package/src/machine/contracts.ts +1 -0
- package/src/machine/errors.ts +4 -2
- package/src/machine/index.ts +65 -34
- package/src/mcp/index.ts +221 -31
- package/src/mcp/version-selection.ts +163 -0
- package/src/utils/azure-cli.ts +315 -0
- package/src/utils/azure-diagnostics.ts +75 -0
- package/src/utils/package-manager.ts +2 -2
- package/src/utils/python-uv.ts +53 -33
- package/src/utils/react-dev.ts +31 -0
- package/src/utils/semver.ts +59 -0
|
@@ -428,7 +428,7 @@ export async function addAuthCommand(options: AddAuthOptions) {
|
|
|
428
428
|
|
|
429
429
|
// 10. Install dependencies
|
|
430
430
|
console.log("\n Installing auth dependencies...");
|
|
431
|
-
|
|
431
|
+
installAuthDependenciesSync(cwd, backendLanguage, rdbProvider, session);
|
|
432
432
|
await finalize();
|
|
433
433
|
|
|
434
434
|
console.log("\n Authentication setup complete!");
|
|
@@ -458,7 +458,8 @@ function findObjectEnd(content: string, open: number): number {
|
|
|
458
458
|
function updateConfigWithNamedScheme(cwd: string, scheme: string, provider: AuthProvider, session: FileOperationSession, allowedProviders?: string[]): void {
|
|
459
459
|
const jsPath = path.join(cwd, "swallowkit.config.js");
|
|
460
460
|
const jsonPath = path.join(cwd, "swallowkit.config.json");
|
|
461
|
-
|
|
461
|
+
// Match loadConfig precedence: swallowkit.config.json wins when both files exist.
|
|
462
|
+
const configPath = session.fileExists(jsonPath) ? jsonPath : jsPath;
|
|
462
463
|
if (!session.fileExists(configPath)) throw new Error("swallowkit.config.js or swallowkit.config.json is required");
|
|
463
464
|
const swaProviders = provider === "swa" ? normalizeSwaProviders(allowedProviders) : undefined;
|
|
464
465
|
if (configPath.endsWith(".json")) {
|
|
@@ -510,6 +511,11 @@ function addNamedScheme(cwd: string, scheme: string, provider: AuthProvider, lan
|
|
|
510
511
|
// Validate/update config before creating files, so duplicate names stop safely.
|
|
511
512
|
updateConfigWithNamedScheme(cwd, scheme, provider, session, allowedProviders);
|
|
512
513
|
const slug = scheme.replace(/([a-z0-9])([A-Z])/g, "$1-$2").replace(/_/g, "-").toLowerCase();
|
|
514
|
+
if (provider === "custom-jwt") {
|
|
515
|
+
// The scheme's JWT helper needs the same token/password/driver packages as single-provider custom-jwt.
|
|
516
|
+
const connector = getConnectorDefinition(defaultCustomJwtConfig().userConnector) as RdbConnectorConfig | undefined;
|
|
517
|
+
installAuthDependenciesSync(cwd, language, connector?.provider ?? "mysql", session);
|
|
518
|
+
}
|
|
513
519
|
if (language === "typescript") {
|
|
514
520
|
const dir = path.join(cwd, "functions", "src", "auth", "schemes", slug);
|
|
515
521
|
if (provider === "external-token") writeIfMissing(session, path.join(dir, "verifier.ts"), generateExternalTokenVerifierTS());
|
|
@@ -689,9 +695,14 @@ function generateFunctionsAuth(
|
|
|
689
695
|
const functionAppPath = path.join(functionsDir, "function_app.py");
|
|
690
696
|
if (session.fileExists(functionAppPath)) {
|
|
691
697
|
const content = session.readFile(functionAppPath);
|
|
692
|
-
const authImport = "from blueprints.auth import
|
|
698
|
+
const authImport = "from blueprints.auth import auth_bp";
|
|
693
699
|
const authRegister = "app.register_blueprint(auth_bp)";
|
|
694
|
-
|
|
700
|
+
// Earlier releases imported a non-existent `bp`; repair it in place when re-running.
|
|
701
|
+
const legacyImport = "from blueprints.auth import bp as auth_bp";
|
|
702
|
+
if (content.includes(legacyImport)) {
|
|
703
|
+
session.writeFile(functionAppPath, content.replace(legacyImport, authImport), extensionMeta);
|
|
704
|
+
console.log(` Updated: functions/function_app.py (fixed auth blueprint import)`);
|
|
705
|
+
} else if (!content.includes(authImport)) {
|
|
695
706
|
const marker = "# SwallowKit scaffold registrations";
|
|
696
707
|
if (content.includes(marker)) {
|
|
697
708
|
const updated = content.replace(
|
|
@@ -742,6 +753,24 @@ function generateBFFAuth(cwd: string, projectName: string, sharedPackageName: st
|
|
|
742
753
|
}
|
|
743
754
|
|
|
744
755
|
function updateConfigWithAuth(cwd: string, provider: AuthProvider, config: CustomJwtConfig, session: FileOperationSession, allowedProviders?: string[]): void {
|
|
756
|
+
const jsonPath = path.join(cwd, "swallowkit.config.json");
|
|
757
|
+
if (session.fileExists(jsonPath)) {
|
|
758
|
+
// loadConfig reads swallowkit.config.json first, so it is the effective configuration.
|
|
759
|
+
const value = JSON.parse(session.readFile(jsonPath));
|
|
760
|
+
if (value.auth) {
|
|
761
|
+
console.log(" 'auth' section already exists in swallowkit.config.json");
|
|
762
|
+
return;
|
|
763
|
+
}
|
|
764
|
+
value.auth = {
|
|
765
|
+
provider,
|
|
766
|
+
...(provider === "custom-jwt" ? { customJwt: { ...config, jwtSecretEnv: config.jwtSecretEnv || "JWT_SECRET", tokenExpiry: config.tokenExpiry || "24h" } } : {}),
|
|
767
|
+
...(provider === "swa" ? { swa: { allowedProviders: normalizeSwaProviders(allowedProviders), roleSource: "swa-roles" } } : {}),
|
|
768
|
+
authorization: { defaultPolicy: provider === "none" ? "anonymous" : "authenticated" },
|
|
769
|
+
};
|
|
770
|
+
session.writeFile(jsonPath, JSON.stringify(value, null, 2) + "\n", extensionMeta);
|
|
771
|
+
console.log(` Updated: swallowkit.config.json`);
|
|
772
|
+
return;
|
|
773
|
+
}
|
|
745
774
|
const configPath = path.join(cwd, "swallowkit.config.js");
|
|
746
775
|
if (!session.fileExists(configPath)) {
|
|
747
776
|
console.warn(" swallowkit.config.js not found. Please add auth config manually.");
|
|
@@ -786,7 +815,8 @@ function updateConfigWithAuth(cwd: string, provider: AuthProvider, config: Custo
|
|
|
786
815
|
provider: '${provider}',
|
|
787
816
|
${providerSettings}
|
|
788
817
|
authorization: {
|
|
789
|
-
|
|
818
|
+
// Disabled auth has no scheme to authenticate against; 'authenticated' would fail validateConfig.
|
|
819
|
+
defaultPolicy: '${provider === "none" ? "anonymous" : "authenticated"}',
|
|
790
820
|
},
|
|
791
821
|
},
|
|
792
822
|
`;
|
|
@@ -821,7 +851,7 @@ function updateEnvironmentFiles(cwd: string, session: FileOperationSession): voi
|
|
|
821
851
|
}
|
|
822
852
|
}
|
|
823
853
|
|
|
824
|
-
|
|
854
|
+
function installAuthDependenciesSync(cwd: string, backendLanguage: BackendLanguage, provider: "mysql" | "postgres" | "sqlserver" = "mysql", session: FileOperationSession): void {
|
|
825
855
|
if (backendLanguage === "typescript") {
|
|
826
856
|
const funcPkgPath = path.join(cwd, "functions", "package.json");
|
|
827
857
|
if (session.fileExists(funcPkgPath)) {
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Command } from "commander";
|
|
2
|
+
import { ensureSwallowKitProject } from "../../core/config";
|
|
3
|
+
import {
|
|
4
|
+
MCP_CONFIG_PATH,
|
|
5
|
+
MCP_LATEST,
|
|
6
|
+
lookupPublishedLatestVersion,
|
|
7
|
+
readMcpConfigVersion,
|
|
8
|
+
resolveMcpPinVersion,
|
|
9
|
+
writeMcpConfigVersion,
|
|
10
|
+
} from "../../core/project/mcp-config";
|
|
11
|
+
import { resolveProjectSwallowKit } from "../../mcp/version-selection";
|
|
12
|
+
import { parseSemver } from "../../utils/semver";
|
|
13
|
+
import { getSwallowKitVersion } from "../../version";
|
|
14
|
+
|
|
15
|
+
export interface ConfigureMcpResult {
|
|
16
|
+
previousVersion: string | null;
|
|
17
|
+
version: string;
|
|
18
|
+
reason: string;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export function configureMcp(
|
|
22
|
+
options: { version?: string; cwd?: string },
|
|
23
|
+
lookupLatest: (packageName: string) => string | null = lookupPublishedLatestVersion
|
|
24
|
+
): ConfigureMcpResult {
|
|
25
|
+
const cwd = options.cwd ?? process.cwd();
|
|
26
|
+
const requested = (options.version ?? "auto").trim();
|
|
27
|
+
const previousVersion = readMcpConfigVersion(cwd);
|
|
28
|
+
|
|
29
|
+
let decision: { version: string; reason: string };
|
|
30
|
+
if (requested === "auto") {
|
|
31
|
+
const projectVersion = resolveProjectSwallowKit(cwd)?.version ?? getSwallowKitVersion();
|
|
32
|
+
decision = resolveMcpPinVersion(projectVersion, lookupLatest("swallowkit"));
|
|
33
|
+
} else if (requested === MCP_LATEST) {
|
|
34
|
+
decision = { version: MCP_LATEST, reason: "Explicitly requested latest." };
|
|
35
|
+
} else if (parseSemver(requested)) {
|
|
36
|
+
decision = { version: requested, reason: "Explicitly pinned version." };
|
|
37
|
+
} else {
|
|
38
|
+
throw new Error(`--version must be "auto", "latest", or a semantic version (got "${requested}").`);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
writeMcpConfigVersion(cwd, decision.version);
|
|
42
|
+
return { previousVersion, ...decision };
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
export const configureMcpCommand = new Command("configure-mcp")
|
|
46
|
+
.description(`Select the SwallowKit MCP version used by ${MCP_CONFIG_PATH} (auto: latest unless the project is newer)`)
|
|
47
|
+
.option("--version <version>", "auto | latest | <semver>", "auto")
|
|
48
|
+
.action((options: { version?: string }) => {
|
|
49
|
+
ensureSwallowKitProject("configure-mcp");
|
|
50
|
+
const result = configureMcp({ version: options.version });
|
|
51
|
+
console.log(`${MCP_CONFIG_PATH}: SWALLOWKIT_MCP_VERSION ${result.previousVersion ?? "(unset)"} -> ${result.version}`);
|
|
52
|
+
console.log(`Reason: ${result.reason}`);
|
|
53
|
+
console.log("Restart the MCP server (or reload your agent) to apply the change.");
|
|
54
|
+
});
|
package/src/cli/commands/dev.ts
CHANGED
|
@@ -19,15 +19,15 @@ import {
|
|
|
19
19
|
import { BackendLanguage } from '../../types';
|
|
20
20
|
import { detectFromProject, getCommands } from '../../utils/package-manager';
|
|
21
21
|
import {
|
|
22
|
-
buildProjectLocalUvEnv,
|
|
23
22
|
buildProjectLocalUvInstallerEnv,
|
|
24
23
|
buildUvPipInstallArgs,
|
|
25
|
-
|
|
24
|
+
ensureUvVirtualEnvironment,
|
|
26
25
|
getProjectLocalUvInstallerCommand,
|
|
27
26
|
getProjectLocalUvPaths,
|
|
28
27
|
getPythonProjectRoot,
|
|
29
28
|
} from '../../utils/python-uv';
|
|
30
29
|
import { ConnectorMockServer } from '../../core/mock/connector-mock-server';
|
|
30
|
+
import { buildReactDevConfigSource } from '../../utils/react-dev';
|
|
31
31
|
|
|
32
32
|
export interface DevOptions {
|
|
33
33
|
port?: string;
|
|
@@ -65,8 +65,8 @@ function normalizeParsedDevOptions(options: ParsedDevActionOptions): DevOptions
|
|
|
65
65
|
};
|
|
66
66
|
}
|
|
67
67
|
|
|
68
|
-
export function buildFunctionsStartArgs(functionsPort: string): string[] {
|
|
69
|
-
return ['start', '--port', functionsPort];
|
|
68
|
+
export function buildFunctionsStartArgs(functionsPort: string, backendLanguage: BackendLanguage = 'typescript'): string[] {
|
|
69
|
+
return [...(backendLanguage === 'csharp' ? [] : ['start']), '--port', functionsPort];
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
export function parseCoreToolsVersion(output: string): string | null {
|
|
@@ -105,15 +105,15 @@ export function buildFunctionsCoreToolsCommand(
|
|
|
105
105
|
|
|
106
106
|
return {
|
|
107
107
|
command: 'npm',
|
|
108
|
-
argsPrefix: ['exec', '--yes', NPM_CORE_TOOLS_PACKAGE, '--'],
|
|
109
|
-
label: `npm
|
|
108
|
+
argsPrefix: ['exec', '--yes', '--package', NPM_CORE_TOOLS_PACKAGE, '--', 'dotnet', 'run', '--no-launch-profile', '--'],
|
|
109
|
+
label: `dotnet run with npm ${NPM_CORE_TOOLS_PACKAGE} (${reason})`,
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
|
|
113
113
|
return {
|
|
114
|
-
command: 'func',
|
|
115
|
-
argsPrefix: [],
|
|
116
|
-
label: installedVersion ? `func ${installedVersion}` : 'func',
|
|
114
|
+
command: backendLanguage === 'csharp' ? 'dotnet' : 'func',
|
|
115
|
+
argsPrefix: backendLanguage === 'csharp' ? ['run', '--no-launch-profile', '--'] : [],
|
|
116
|
+
label: backendLanguage === 'csharp' ? 'dotnet run' : installedVersion ? `func ${installedVersion}` : 'func',
|
|
117
117
|
};
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -138,8 +138,8 @@ export function buildSwaStartArgs(host: string | undefined, nextPort: string, sw
|
|
|
138
138
|
];
|
|
139
139
|
}
|
|
140
140
|
|
|
141
|
-
export function buildReactDevArgs(pm: string, port: string, host = 'localhost'): string[] {
|
|
142
|
-
const args = ['vite', '--port', port, '--host', host, '--strictPort'];
|
|
141
|
+
export function buildReactDevArgs(pm: string, port: string, host = 'localhost', configPath?: string): string[] {
|
|
142
|
+
const args = ['vite', '--port', port, '--host', host, '--strictPort', ...(configPath ? ['--config', configPath] : [])];
|
|
143
143
|
return pm === 'pnpm' ? ['exec', ...args] : args;
|
|
144
144
|
}
|
|
145
145
|
|
|
@@ -270,7 +270,7 @@ async function checkCommand(
|
|
|
270
270
|
}
|
|
271
271
|
|
|
272
272
|
async function resolveProjectLocalUvCommand(projectRoot: string): Promise<{ command: string; env: NodeJS.ProcessEnv }> {
|
|
273
|
-
const uvEnv =
|
|
273
|
+
const uvEnv = { ...process.env };
|
|
274
274
|
const { localUvExecutable } = getProjectLocalUvPaths(projectRoot);
|
|
275
275
|
|
|
276
276
|
if (await checkCommand('uv', ['--version'], { shell: false })) {
|
|
@@ -471,22 +471,8 @@ async function bridgePythonCoreToolsForWindowsArm64(
|
|
|
471
471
|
async function preparePythonFunctionsEnvironment(functionsDir: string): Promise<NodeJS.ProcessEnv> {
|
|
472
472
|
const projectRoot = getPythonProjectRoot(functionsDir);
|
|
473
473
|
const { command: uvCommand, env: uvEnv } = await resolveProjectLocalUvCommand(projectRoot);
|
|
474
|
-
const { venvDir
|
|
475
|
-
const
|
|
476
|
-
cwd: functionsDir,
|
|
477
|
-
env: uvEnv,
|
|
478
|
-
shell: false,
|
|
479
|
-
});
|
|
480
|
-
|
|
481
|
-
if (!hasUsableVirtualEnv) {
|
|
482
|
-
const venvArgs = buildUvVenvArgs('.venv');
|
|
483
|
-
if (fs.existsSync(venvDir)) {
|
|
484
|
-
venvArgs.push('--clear');
|
|
485
|
-
}
|
|
486
|
-
|
|
487
|
-
console.log('📦 Creating Python virtual environment with uv...');
|
|
488
|
-
await runCommand(uvCommand, venvArgs, functionsDir, 'python virtual environment setup', uvEnv, false);
|
|
489
|
-
}
|
|
474
|
+
const { venvDir } = getPythonVirtualEnvPaths(functionsDir);
|
|
475
|
+
const pythonExecutable = await ensureUvVirtualEnvironment(uvCommand, venvDir, functionsDir, uvEnv);
|
|
490
476
|
|
|
491
477
|
console.log('📦 Installing Python Azure Functions dependencies with uv...');
|
|
492
478
|
await runCommand(
|
|
@@ -538,7 +524,7 @@ export async function assertDevPortAvailable(port: number, host: string): Promis
|
|
|
538
524
|
}
|
|
539
525
|
|
|
540
526
|
function stopDevProcesses(processes: ChildProcess[]): void {
|
|
541
|
-
const active = processes.filter(child => child.pid && !child.killed);
|
|
527
|
+
const active = processes.filter(child => child.pid && !child.killed && child.exitCode === null && child.signalCode === null);
|
|
542
528
|
if (process.platform === 'win32' && active.length) {
|
|
543
529
|
// Windows shell termination alone leaves Vite, Core Tools, and SWA running.
|
|
544
530
|
const ids = active.map(child => child.pid).join(',');
|
|
@@ -721,6 +707,14 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
721
707
|
const functionsBaseUrl = buildFunctionsBaseUrl(options.host, functionsPort);
|
|
722
708
|
let functionsReadinessPromise: Promise<boolean> | null = null;
|
|
723
709
|
let functionsReady = !!options.noFunctions;
|
|
710
|
+
let reactDevConfigDir: string | undefined;
|
|
711
|
+
const cleanupReactDevConfig = () => {
|
|
712
|
+
if (reactDevConfigDir) {
|
|
713
|
+
fs.rmSync(reactDevConfigDir, { recursive: true, force: true });
|
|
714
|
+
reactDevConfigDir = undefined;
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
process.once('exit', cleanupReactDevConfig);
|
|
724
718
|
|
|
725
719
|
// Cleanup processes on Ctrl+C
|
|
726
720
|
process.on('SIGINT', async () => {
|
|
@@ -939,7 +933,7 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
939
933
|
|
|
940
934
|
// Azure Functions を起動
|
|
941
935
|
const functionsCommand = functionsCoreToolsCommand ?? buildFunctionsCoreToolsCommand(backendLanguage, installedCoreToolsVersion);
|
|
942
|
-
const funcProcess = spawn(functionsCommand.command, [...functionsCommand.argsPrefix, ...buildFunctionsStartArgs(functionsPort)], {
|
|
936
|
+
const funcProcess = spawn(functionsCommand.command, [...functionsCommand.argsPrefix, ...buildFunctionsStartArgs(functionsPort, backendLanguage)], {
|
|
943
937
|
cwd: functionsDir,
|
|
944
938
|
shell: true,
|
|
945
939
|
stdio: 'pipe', // Always pipe to capture output
|
|
@@ -987,6 +981,8 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
987
981
|
console.error('⚠️ Azure Functions startup error:', error.message);
|
|
988
982
|
console.log('💡 Please ensure Azure Functions Core Tools is installed');
|
|
989
983
|
console.log(` ${pmCmd.addGlobal} azure-functions-core-tools@4`);
|
|
984
|
+
stopDevProcesses(processes);
|
|
985
|
+
process.exit(1);
|
|
990
986
|
});
|
|
991
987
|
|
|
992
988
|
funcProcess.on('close', (code) => {
|
|
@@ -997,6 +993,8 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
997
993
|
console.log(' Reinstall a matching Core Tools v4 package (Windows users should prefer the official x64/x86 MSI for their machine).');
|
|
998
994
|
console.log(' SwallowKit local Python dev uses functions/.venv and requirements.txt, but Core Tools still needs its own bundled Python worker.');
|
|
999
995
|
}
|
|
996
|
+
stopDevProcesses(processes);
|
|
997
|
+
process.exit(code || 1);
|
|
1000
998
|
}
|
|
1001
999
|
});
|
|
1002
1000
|
|
|
@@ -1083,7 +1081,17 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
1083
1081
|
}
|
|
1084
1082
|
|
|
1085
1083
|
// 5. Start Next.js development server
|
|
1086
|
-
|
|
1084
|
+
let reactDevConfigPath: string | undefined;
|
|
1085
|
+
if (react) {
|
|
1086
|
+
const stateDir = path.join(process.cwd(), '.swallowkit');
|
|
1087
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
1088
|
+
reactDevConfigDir = fs.mkdtempSync(path.join(stateDir, 'vite-dev-'));
|
|
1089
|
+
reactDevConfigPath = path.join(reactDevConfigDir, 'config.mjs');
|
|
1090
|
+
fs.writeFileSync(reactDevConfigPath, buildReactDevConfigSource());
|
|
1091
|
+
}
|
|
1092
|
+
const nextArgs = react
|
|
1093
|
+
? buildReactDevArgs(pm, port, options.host, reactDevConfigPath && path.relative(process.cwd(), reactDevConfigPath))
|
|
1094
|
+
: buildNextDevArgs(pm, port);
|
|
1087
1095
|
|
|
1088
1096
|
// Ensure .env.local points to bffTargetPort so Next.js reads the correct backend URL.
|
|
1089
1097
|
// When --mock-connectors is active, bffTargetPort = mock port (7072); otherwise = Functions port (7071).
|
|
@@ -1141,6 +1149,7 @@ async function startDevEnvironment(options: DevOptions) {
|
|
|
1141
1149
|
|
|
1142
1150
|
nextProcess.on('error', (error) => {
|
|
1143
1151
|
console.error(`❌ ${frontendLabel} startup error:`, error.message);
|
|
1152
|
+
stopDevProcesses(processes);
|
|
1144
1153
|
process.exit(1);
|
|
1145
1154
|
});
|
|
1146
1155
|
|