swallowkit 1.1.2 → 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 +61 -7
- package/README.md +61 -7
- package/dist/cli/commands/add-auth.d.ts.map +1 -1
- package/dist/cli/commands/add-auth.js +103 -27
- 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 +5 -2
- package/dist/cli/commands/dev.d.ts.map +1 -1
- package/dist/cli/commands/dev.js +143 -67
- package/dist/cli/commands/dev.js.map +1 -1
- package/dist/cli/commands/init.d.ts +14 -7
- package/dist/cli/commands/init.d.ts.map +1 -1
- package/dist/cli/commands/init.js +149 -170
- 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 +5 -1
- package/dist/cli/commands/scaffold.d.ts.map +1 -1
- package/dist/cli/commands/scaffold.js +123 -18
- 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 +49 -8
- package/dist/cli/index.js.map +1 -1
- package/dist/core/config.d.ts +2 -1
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +19 -0
- package/dist/core/config.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 +2 -1
- package/dist/core/project/agent-instructions.d.ts.map +1 -1
- package/dist/core/project/agent-instructions.js +15 -0
- 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 +17 -0
- package/dist/core/project/capabilities.d.ts.map +1 -1
- package/dist/core/project/capabilities.js +45 -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/manifest.d.ts +3 -1
- package/dist/core/project/manifest.d.ts.map +1 -1
- package/dist/core/project/manifest.js +47 -25
- package/dist/core/project/manifest.js.map +1 -1
- 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 +26 -0
- package/dist/core/project/react-project.d.ts.map +1 -0
- package/dist/core/project/react-project.js +443 -0
- package/dist/core/project/react-project.js.map +1 -0
- 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/validation.d.ts.map +1 -1
- package/dist/core/project/validation.js +32 -10
- package/dist/core/project/validation.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/react-bff-generator.d.ts +10 -0
- package/dist/core/scaffold/react-bff-generator.d.ts.map +1 -0
- package/dist/core/scaffold/react-bff-generator.js +252 -0
- package/dist/core/scaffold/react-bff-generator.js.map +1 -0
- package/dist/core/scaffold/react-ui-generator.d.ts +6 -0
- package/dist/core/scaffold/react-ui-generator.d.ts.map +1 -0
- package/dist/core/scaffold/react-ui-generator.js +41 -0
- package/dist/core/scaffold/react-ui-generator.js.map +1 -0
- 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/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -2
- package/dist/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 +61 -30
- 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/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -1
- 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.d.ts +2 -2
- package/dist/utils/package-manager.d.ts.map +1 -1
- package/dist/utils/package-manager.js +6 -3
- 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 +7 -4
- package/src/__tests__/__snapshots__/boundaries.test.ts.snap +154 -0
- package/src/__tests__/agent-instructions.test.ts +6 -1
- 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 +145 -5
- 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 +838 -0
- package/src/__tests__/release-metadata.test.ts +121 -0
- package/src/__tests__/schema-analysis.test.ts +329 -0
- package/src/cli/commands/add-auth.ts +103 -29
- package/src/cli/commands/configure-mcp.ts +54 -0
- package/src/cli/commands/dev.ts +145 -73
- package/src/cli/commands/init.ts +147 -172
- package/src/cli/commands/migrations.ts +22 -0
- package/src/cli/commands/provision.ts +294 -56
- package/src/cli/commands/scaffold.ts +145 -22
- package/src/cli/index.ts +46 -10
- package/src/core/config.ts +21 -1
- 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 +17 -1
- package/src/core/project/agent-templates/AGENTS.md +113 -15
- package/src/core/project/agent-templates/CLAUDE.md +14 -1
- package/src/core/project/agent-templates/bff-routes.instructions.md +5 -3
- 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 +63 -6
- package/src/core/project/home-page.ts +114 -0
- package/src/core/project/manifest.ts +52 -27
- package/src/core/project/mcp-config.ts +84 -0
- package/src/core/project/react-project.ts +529 -0
- package/src/core/project/state.ts +70 -0
- package/src/core/project/validation.ts +32 -10
- 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/react-bff-generator.ts +292 -0
- package/src/core/scaffold/react-ui-generator.ts +51 -0
- package/src/core/scaffold/ui-generator.ts +70 -8
- package/src/core/verify/index.ts +118 -6
- package/src/index.ts +3 -1
- package/src/machine/contracts.ts +1 -0
- package/src/machine/errors.ts +4 -2
- package/src/machine/index.ts +67 -36
- package/src/mcp/index.ts +221 -31
- package/src/mcp/version-selection.ts +163 -0
- package/src/types/index.ts +4 -0
- package/src/utils/azure-cli.ts +315 -0
- package/src/utils/azure-diagnostics.ts +75 -0
- package/src/utils/package-manager.ts +7 -4
- package/src/utils/python-uv.ts +53 -33
- package/src/utils/react-dev.ts +31 -0
- package/src/utils/semver.ts +59 -0
package/dist/cli/commands/dev.js
CHANGED
|
@@ -41,6 +41,7 @@ exports.buildFunctionsCoreToolsCommand = buildFunctionsCoreToolsCommand;
|
|
|
41
41
|
exports.buildNextDevArgs = buildNextDevArgs;
|
|
42
42
|
exports.buildFunctionsBaseUrl = buildFunctionsBaseUrl;
|
|
43
43
|
exports.buildSwaStartArgs = buildSwaStartArgs;
|
|
44
|
+
exports.buildReactDevArgs = buildReactDevArgs;
|
|
44
45
|
exports.getSwaCliInstallCommand = getSwaCliInstallCommand;
|
|
45
46
|
exports.getFunctionsReadinessTimeoutMs = getFunctionsReadinessTimeoutMs;
|
|
46
47
|
exports.waitForHttpServerReady = waitForHttpServerReady;
|
|
@@ -48,6 +49,7 @@ exports.getPythonVirtualEnvPaths = getPythonVirtualEnvPaths;
|
|
|
48
49
|
exports.getCSharpFunctionsBuildArtifactPaths = getCSharpFunctionsBuildArtifactPaths;
|
|
49
50
|
exports.buildPythonFunctionsEnv = buildPythonFunctionsEnv;
|
|
50
51
|
exports.buildFunctionsCosmosEnvironment = buildFunctionsCosmosEnvironment;
|
|
52
|
+
exports.assertDevPortAvailable = assertDevPortAvailable;
|
|
51
53
|
exports.buildDevCommand = buildDevCommand;
|
|
52
54
|
const commander_1 = require("commander");
|
|
53
55
|
const child_process_1 = require("child_process");
|
|
@@ -63,6 +65,7 @@ const dev_seeds_1 = require("./dev-seeds");
|
|
|
63
65
|
const package_manager_1 = require("../../utils/package-manager");
|
|
64
66
|
const python_uv_1 = require("../../utils/python-uv");
|
|
65
67
|
const connector_mock_server_1 = require("../../core/mock/connector-mock-server");
|
|
68
|
+
const react_dev_1 = require("../../utils/react-dev");
|
|
66
69
|
const MINIMUM_CSHARP_CORE_TOOLS_VERSION = '4.6.0';
|
|
67
70
|
const NPM_CORE_TOOLS_PACKAGE = 'azure-functions-core-tools@4';
|
|
68
71
|
function normalizeParsedDevOptions(options) {
|
|
@@ -72,8 +75,8 @@ function normalizeParsedDevOptions(options) {
|
|
|
72
75
|
noSwa: options.noSwa ?? options.swa === false,
|
|
73
76
|
};
|
|
74
77
|
}
|
|
75
|
-
function buildFunctionsStartArgs(functionsPort) {
|
|
76
|
-
return ['start', '--port', functionsPort];
|
|
78
|
+
function buildFunctionsStartArgs(functionsPort, backendLanguage = 'typescript') {
|
|
79
|
+
return [...(backendLanguage === 'csharp' ? [] : ['start']), '--port', functionsPort];
|
|
77
80
|
}
|
|
78
81
|
function parseCoreToolsVersion(output) {
|
|
79
82
|
const match = output.match(/\d+\.\d+\.\d+/);
|
|
@@ -100,14 +103,14 @@ function buildFunctionsCoreToolsCommand(backendLanguage, installedVersion) {
|
|
|
100
103
|
: 'func is not installed';
|
|
101
104
|
return {
|
|
102
105
|
command: 'npm',
|
|
103
|
-
argsPrefix: ['exec', '--yes', NPM_CORE_TOOLS_PACKAGE, '--'],
|
|
104
|
-
label: `npm
|
|
106
|
+
argsPrefix: ['exec', '--yes', '--package', NPM_CORE_TOOLS_PACKAGE, '--', 'dotnet', 'run', '--no-launch-profile', '--'],
|
|
107
|
+
label: `dotnet run with npm ${NPM_CORE_TOOLS_PACKAGE} (${reason})`,
|
|
105
108
|
};
|
|
106
109
|
}
|
|
107
110
|
return {
|
|
108
|
-
command: 'func',
|
|
109
|
-
argsPrefix: [],
|
|
110
|
-
label: installedVersion ? `func ${installedVersion}` : 'func',
|
|
111
|
+
command: backendLanguage === 'csharp' ? 'dotnet' : 'func',
|
|
112
|
+
argsPrefix: backendLanguage === 'csharp' ? ['run', '--no-launch-profile', '--'] : [],
|
|
113
|
+
label: backendLanguage === 'csharp' ? 'dotnet run' : installedVersion ? `func ${installedVersion}` : 'func',
|
|
111
114
|
};
|
|
112
115
|
}
|
|
113
116
|
function buildNextDevArgs(pm, port) {
|
|
@@ -117,7 +120,7 @@ function buildNextDevArgs(pm, port) {
|
|
|
117
120
|
function buildFunctionsBaseUrl(host, functionsPort) {
|
|
118
121
|
return `http://${host || 'localhost'}:${functionsPort}`;
|
|
119
122
|
}
|
|
120
|
-
function buildSwaStartArgs(host, nextPort, swaPort) {
|
|
123
|
+
function buildSwaStartArgs(host, nextPort, swaPort, bffPort) {
|
|
121
124
|
return [
|
|
122
125
|
'start',
|
|
123
126
|
`http://${host || 'localhost'}:${nextPort}`,
|
|
@@ -125,8 +128,13 @@ function buildSwaStartArgs(host, nextPort, swaPort) {
|
|
|
125
128
|
'.',
|
|
126
129
|
'--port',
|
|
127
130
|
swaPort,
|
|
131
|
+
...(bffPort ? ['--api-devserver-url', buildFunctionsBaseUrl(host, bffPort)] : []),
|
|
128
132
|
];
|
|
129
133
|
}
|
|
134
|
+
function buildReactDevArgs(pm, port, host = 'localhost', configPath) {
|
|
135
|
+
const args = ['vite', '--port', port, '--host', host, '--strictPort', ...(configPath ? ['--config', configPath] : [])];
|
|
136
|
+
return pm === 'pnpm' ? ['exec', ...args] : args;
|
|
137
|
+
}
|
|
130
138
|
function getSwaCliInstallCommand(pm) {
|
|
131
139
|
return pm === 'pnpm'
|
|
132
140
|
? 'pnpm add -Dw @azure/static-web-apps-cli'
|
|
@@ -215,7 +223,7 @@ async function checkCommand(command, args = ['--version'], options) {
|
|
|
215
223
|
});
|
|
216
224
|
}
|
|
217
225
|
async function resolveProjectLocalUvCommand(projectRoot) {
|
|
218
|
-
const uvEnv =
|
|
226
|
+
const uvEnv = { ...process.env };
|
|
219
227
|
const { localUvExecutable } = (0, python_uv_1.getProjectLocalUvPaths)(projectRoot);
|
|
220
228
|
if (await checkCommand('uv', ['--version'], { shell: false })) {
|
|
221
229
|
return { command: 'uv', env: uvEnv };
|
|
@@ -357,20 +365,8 @@ async function bridgePythonCoreToolsForWindowsArm64(functionsDir, env) {
|
|
|
357
365
|
async function preparePythonFunctionsEnvironment(functionsDir) {
|
|
358
366
|
const projectRoot = (0, python_uv_1.getPythonProjectRoot)(functionsDir);
|
|
359
367
|
const { command: uvCommand, env: uvEnv } = await resolveProjectLocalUvCommand(projectRoot);
|
|
360
|
-
const { venvDir
|
|
361
|
-
const
|
|
362
|
-
cwd: functionsDir,
|
|
363
|
-
env: uvEnv,
|
|
364
|
-
shell: false,
|
|
365
|
-
});
|
|
366
|
-
if (!hasUsableVirtualEnv) {
|
|
367
|
-
const venvArgs = (0, python_uv_1.buildUvVenvArgs)('.venv');
|
|
368
|
-
if (fs.existsSync(venvDir)) {
|
|
369
|
-
venvArgs.push('--clear');
|
|
370
|
-
}
|
|
371
|
-
console.log('📦 Creating Python virtual environment with uv...');
|
|
372
|
-
await runCommand(uvCommand, venvArgs, functionsDir, 'python virtual environment setup', uvEnv, false);
|
|
373
|
-
}
|
|
368
|
+
const { venvDir } = getPythonVirtualEnvPaths(functionsDir);
|
|
369
|
+
const pythonExecutable = await (0, python_uv_1.ensureUvVirtualEnvironment)(uvCommand, venvDir, functionsDir, uvEnv);
|
|
374
370
|
console.log('📦 Installing Python Azure Functions dependencies with uv...');
|
|
375
371
|
await runCommand(uvCommand, (0, python_uv_1.buildUvPipInstallArgs)(pythonExecutable, 'requirements.txt'), functionsDir, 'python dependency installation', uvEnv, false);
|
|
376
372
|
const pythonEnv = buildPythonFunctionsEnv(uvEnv, functionsDir);
|
|
@@ -398,20 +394,45 @@ async function checkCosmosDBEmulator() {
|
|
|
398
394
|
socket.connect(8081, 'localhost');
|
|
399
395
|
});
|
|
400
396
|
}
|
|
397
|
+
async function assertDevPortAvailable(port, host) {
|
|
398
|
+
await new Promise((resolve, reject) => {
|
|
399
|
+
const server = net.createServer();
|
|
400
|
+
server.once('error', error => reject(new Error(`Development port ${port} on ${host} is unavailable: ${error.message}`)));
|
|
401
|
+
server.listen({ port, host, exclusive: true }, () => server.close(error => error ? reject(error) : resolve()));
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
function stopDevProcesses(processes) {
|
|
405
|
+
const active = processes.filter(child => child.pid && !child.killed && child.exitCode === null && child.signalCode === null);
|
|
406
|
+
if (process.platform === 'win32' && active.length) {
|
|
407
|
+
// Windows shell termination alone leaves Vite, Core Tools, and SWA running.
|
|
408
|
+
const ids = active.map(child => child.pid).join(',');
|
|
409
|
+
const result = (0, child_process_1.spawnSync)('powershell.exe', ['-NoProfile', '-NonInteractive', '-Command',
|
|
410
|
+
`$all = @(Get-CimInstance Win32_Process); function Stop-OwnedTree([int]$id) { foreach ($child in ($all | Where-Object ParentProcessId -eq $id)) { Stop-OwnedTree $child.ProcessId }; Stop-Process -Id $id -Force -ErrorAction SilentlyContinue }; foreach ($id in @(${ids})) { Stop-OwnedTree $id }`,
|
|
411
|
+
], { windowsHide: true, encoding: 'utf8' });
|
|
412
|
+
if (result.error || result.status !== 0) {
|
|
413
|
+
console.error('❌ Could not stop all development subprocesses:', result.error?.message || result.stderr);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
for (const child of active)
|
|
418
|
+
child.kill();
|
|
419
|
+
}
|
|
420
|
+
}
|
|
401
421
|
function buildDevCommand(runDevEnvironment = startDevEnvironment, verifyProject = config_1.ensureSwallowKitProject) {
|
|
402
422
|
return new commander_1.Command()
|
|
403
423
|
.name('dev')
|
|
404
|
-
.description('Start SwallowKit
|
|
405
|
-
.option('-p, --port <port>', '
|
|
424
|
+
.description('Start SwallowKit frontend, BFF, and standalone Azure Functions')
|
|
425
|
+
.option('-p, --port <port>', 'Frontend dev server port', '3000')
|
|
406
426
|
.option('-f, --functions-port <port>', 'Azure Functions port', '7071')
|
|
427
|
+
.option('--bff-port <port>', 'React managed BFF Functions port', '7073')
|
|
407
428
|
.option('--host <host>', 'Host name', 'localhost')
|
|
408
429
|
.option('--open', 'Open browser automatically', false)
|
|
409
430
|
.option('--verbose', 'Show verbose logs', false)
|
|
410
431
|
.option('--no-functions', 'Skip Azure Functions startup')
|
|
411
432
|
.option('--seed-env <environment>', 'Replace Cosmos DB Emulator data from dev-seeds/<environment> before startup')
|
|
412
433
|
.option('--mock-connectors', 'Start mock server for connector models (serves Zod-generated data)', false)
|
|
413
|
-
.option('--swa-port <port>', 'SWA authentication emulator port', '4280')
|
|
414
|
-
.option('--no-swa', 'Skip
|
|
434
|
+
.option('--swa-port <port>', 'SWA routing/authentication emulator port', '4280')
|
|
435
|
+
.option('--no-swa', 'Skip SWA routing/authentication emulation (React direct access has no same-origin API)')
|
|
415
436
|
.action(async (options) => {
|
|
416
437
|
const normalizedOptions = normalizeParsedDevOptions(options);
|
|
417
438
|
// SwallowKit プロジェクトディレクトリかどうかを検証
|
|
@@ -512,17 +533,22 @@ async function startDevEnvironment(options) {
|
|
|
512
533
|
const port = options.port || '3000';
|
|
513
534
|
const functionsPort = options.functionsPort || '7071';
|
|
514
535
|
const swaPort = options.swaPort || '4280';
|
|
536
|
+
const bffPort = options.bffPort || '7073';
|
|
515
537
|
// Detect package manager from project lockfile
|
|
516
538
|
const pm = (0, package_manager_1.detectFromProject)();
|
|
517
539
|
const pmCmd = (0, package_manager_1.getCommands)(pm);
|
|
518
540
|
const backendLanguage = (0, config_1.getBackendLanguage)();
|
|
541
|
+
const react = (0, config_1.getFrontendFramework)() === 'react';
|
|
542
|
+
const frontendLabel = react ? 'React/Vite' : 'Next.js';
|
|
519
543
|
const authConfig = (0, config_1.getAuthConfig)();
|
|
520
544
|
const normalizedAuth = (0, config_1.normalizeAuthConfig)(authConfig);
|
|
521
|
-
const
|
|
545
|
+
const authSchemes = Object.values(normalizedAuth?.schemes ?? {});
|
|
546
|
+
const swaScheme = authSchemes.find(scheme => scheme.provider === 'swa');
|
|
547
|
+
const useSwaEmulator = (react || Boolean(swaScheme)) && !options.noSwa;
|
|
522
548
|
const swaCommand = useSwaEmulator ? await resolveSwaCliCommand(process.cwd()) : null;
|
|
523
549
|
if (useSwaEmulator && !swaCommand) {
|
|
524
550
|
const installCommand = getSwaCliInstallCommand(pm);
|
|
525
|
-
console.error('❌ SWA authentication requires Azure Static Web Apps CLI for local development.');
|
|
551
|
+
console.error('❌ SWA routing/authentication requires Azure Static Web Apps CLI for local development.');
|
|
526
552
|
console.error(' Install it in this project and retry:');
|
|
527
553
|
console.error(`\n ${installCommand}\n`);
|
|
528
554
|
process.exitCode = 1;
|
|
@@ -537,6 +563,14 @@ async function startDevEnvironment(options) {
|
|
|
537
563
|
const functionsBaseUrl = buildFunctionsBaseUrl(options.host, functionsPort);
|
|
538
564
|
let functionsReadinessPromise = null;
|
|
539
565
|
let functionsReady = !!options.noFunctions;
|
|
566
|
+
let reactDevConfigDir;
|
|
567
|
+
const cleanupReactDevConfig = () => {
|
|
568
|
+
if (reactDevConfigDir) {
|
|
569
|
+
fs.rmSync(reactDevConfigDir, { recursive: true, force: true });
|
|
570
|
+
reactDevConfigDir = undefined;
|
|
571
|
+
}
|
|
572
|
+
};
|
|
573
|
+
process.once('exit', cleanupReactDevConfig);
|
|
540
574
|
// Cleanup processes on Ctrl+C
|
|
541
575
|
process.on('SIGINT', async () => {
|
|
542
576
|
console.log('\n🛑 Stopping development servers...');
|
|
@@ -557,14 +591,22 @@ async function startDevEnvironment(options) {
|
|
|
557
591
|
if (mockServer) {
|
|
558
592
|
await mockServer.stop();
|
|
559
593
|
}
|
|
560
|
-
processes
|
|
561
|
-
if (proc && !proc.killed) {
|
|
562
|
-
proc.kill();
|
|
563
|
-
}
|
|
564
|
-
});
|
|
594
|
+
stopDevProcesses(processes);
|
|
565
595
|
process.exit(0);
|
|
566
596
|
});
|
|
567
597
|
try {
|
|
598
|
+
if (react) {
|
|
599
|
+
const ports = [port, bffPort, ...(!options.noFunctions ? [functionsPort] : []), ...(useSwaEmulator ? [swaPort] : []), ...(options.mockConnectors ? [String(Number(functionsPort) + 1)] : [])];
|
|
600
|
+
if (ports.some(value => !/^\d+$/.test(value) || Number(value) < 1 || Number(value) > 65535) || new Set(ports).size !== ports.length) {
|
|
601
|
+
throw new Error('Frontend, BFF, standalone Functions, mock, and SWA ports must be valid and distinct');
|
|
602
|
+
}
|
|
603
|
+
for (const value of ports)
|
|
604
|
+
await assertDevPortAvailable(Number(value), options.host || 'localhost');
|
|
605
|
+
const coreToolsVersion = await resolveInstalledCoreToolsVersion();
|
|
606
|
+
if (!coreToolsVersion || compareVersionNumbers(coreToolsVersion, '4.0.0') < 0) {
|
|
607
|
+
throw new Error('React BFF requires Azure Functions Core Tools v4. Install it explicitly before running dev.');
|
|
608
|
+
}
|
|
609
|
+
}
|
|
568
610
|
// 1. Check for Next.js project
|
|
569
611
|
const packageJsonPath = path.join(process.cwd(), 'package.json');
|
|
570
612
|
const nextConfigPathJs = path.join(process.cwd(), 'next.config.js');
|
|
@@ -572,10 +614,10 @@ async function startDevEnvironment(options) {
|
|
|
572
614
|
const nextConfigPathMjs = path.join(process.cwd(), 'next.config.mjs');
|
|
573
615
|
if (!fs.existsSync(packageJsonPath)) {
|
|
574
616
|
console.log('❌ package.json not found.');
|
|
575
|
-
console.log('💡 Please run this command in the root directory of a
|
|
617
|
+
console.log('💡 Please run this command in the root directory of a SwallowKit project.');
|
|
576
618
|
process.exit(1);
|
|
577
619
|
}
|
|
578
|
-
if (!fs.existsSync(nextConfigPathJs) && !fs.existsSync(nextConfigPathTs) && !fs.existsSync(nextConfigPathMjs)) {
|
|
620
|
+
if (!react && !fs.existsSync(nextConfigPathJs) && !fs.existsSync(nextConfigPathTs) && !fs.existsSync(nextConfigPathMjs)) {
|
|
579
621
|
console.log('⚠️ next.config file not found. Is this a Next.js project?');
|
|
580
622
|
}
|
|
581
623
|
// 2. Check if Azure Functions exists
|
|
@@ -730,7 +772,7 @@ async function startDevEnvironment(options) {
|
|
|
730
772
|
}
|
|
731
773
|
// Azure Functions を起動
|
|
732
774
|
const functionsCommand = functionsCoreToolsCommand ?? buildFunctionsCoreToolsCommand(backendLanguage, installedCoreToolsVersion);
|
|
733
|
-
const funcProcess = (0, child_process_1.spawn)(functionsCommand.command, [...functionsCommand.argsPrefix, ...buildFunctionsStartArgs(functionsPort)], {
|
|
775
|
+
const funcProcess = (0, child_process_1.spawn)(functionsCommand.command, [...functionsCommand.argsPrefix, ...buildFunctionsStartArgs(functionsPort, backendLanguage)], {
|
|
734
776
|
cwd: functionsDir,
|
|
735
777
|
shell: true,
|
|
736
778
|
stdio: 'pipe', // Always pipe to capture output
|
|
@@ -770,6 +812,8 @@ async function startDevEnvironment(options) {
|
|
|
770
812
|
console.error('⚠️ Azure Functions startup error:', error.message);
|
|
771
813
|
console.log('💡 Please ensure Azure Functions Core Tools is installed');
|
|
772
814
|
console.log(` ${pmCmd.addGlobal} azure-functions-core-tools@4`);
|
|
815
|
+
stopDevProcesses(processes);
|
|
816
|
+
process.exit(1);
|
|
773
817
|
});
|
|
774
818
|
funcProcess.on('close', (code) => {
|
|
775
819
|
if (code !== 0) {
|
|
@@ -779,6 +823,8 @@ async function startDevEnvironment(options) {
|
|
|
779
823
|
console.log(' Reinstall a matching Core Tools v4 package (Windows users should prefer the official x64/x86 MSI for their machine).');
|
|
780
824
|
console.log(' SwallowKit local Python dev uses functions/.venv and requirements.txt, but Core Tools still needs its own bundled Python worker.');
|
|
781
825
|
}
|
|
826
|
+
stopDevProcesses(processes);
|
|
827
|
+
process.exit(code || 1);
|
|
782
828
|
}
|
|
783
829
|
});
|
|
784
830
|
console.log(`⏳ Waiting for Azure Functions to accept requests at ${functionsBaseUrl}...`);
|
|
@@ -786,14 +832,14 @@ async function startDevEnvironment(options) {
|
|
|
786
832
|
}
|
|
787
833
|
else if (!hasFunctions) {
|
|
788
834
|
console.log('');
|
|
789
|
-
console.log(
|
|
835
|
+
console.log(`ℹ️ functions/ directory not found. Starting ${frontendLabel}${react ? ' and managed BFF' : ''} only.`);
|
|
790
836
|
}
|
|
791
837
|
else if (options.noFunctions) {
|
|
792
838
|
console.log('');
|
|
793
839
|
console.log('ℹ️ --no-functions specified. Skipping Azure Functions.');
|
|
794
840
|
}
|
|
795
841
|
console.log('');
|
|
796
|
-
console.log(
|
|
842
|
+
console.log(`🚀 Starting ${frontendLabel} development server...`);
|
|
797
843
|
// Mock connector server — start proxy if --mock-connectors is enabled
|
|
798
844
|
let bffTargetPort = functionsPort;
|
|
799
845
|
if (options.mockConnectors) {
|
|
@@ -857,7 +903,17 @@ async function startDevEnvironment(options) {
|
|
|
857
903
|
}
|
|
858
904
|
}
|
|
859
905
|
// 5. Start Next.js development server
|
|
860
|
-
|
|
906
|
+
let reactDevConfigPath;
|
|
907
|
+
if (react) {
|
|
908
|
+
const stateDir = path.join(process.cwd(), '.swallowkit');
|
|
909
|
+
fs.mkdirSync(stateDir, { recursive: true });
|
|
910
|
+
reactDevConfigDir = fs.mkdtempSync(path.join(stateDir, 'vite-dev-'));
|
|
911
|
+
reactDevConfigPath = path.join(reactDevConfigDir, 'config.mjs');
|
|
912
|
+
fs.writeFileSync(reactDevConfigPath, (0, react_dev_1.buildReactDevConfigSource)());
|
|
913
|
+
}
|
|
914
|
+
const nextArgs = react
|
|
915
|
+
? buildReactDevArgs(pm, port, options.host, reactDevConfigPath && path.relative(process.cwd(), reactDevConfigPath))
|
|
916
|
+
: buildNextDevArgs(pm, port);
|
|
861
917
|
// Ensure .env.local points to bffTargetPort so Next.js reads the correct backend URL.
|
|
862
918
|
// When --mock-connectors is active, bffTargetPort = mock port (7072); otherwise = Functions port (7071).
|
|
863
919
|
// Next.js may load .env.local values that override spawn env vars, so we must keep them in sync.
|
|
@@ -880,6 +936,24 @@ async function startDevEnvironment(options) {
|
|
|
880
936
|
BACKEND_FUNCTIONS_BASE_URL: bffTargetUrl,
|
|
881
937
|
FUNCTIONS_BASE_URL: bffTargetUrl,
|
|
882
938
|
};
|
|
939
|
+
if (react) {
|
|
940
|
+
await runCommand(pm, ['run', 'build'], path.join(process.cwd(), 'shared'), 'Shared schema build');
|
|
941
|
+
const bffDir = path.join(process.cwd(), 'bff');
|
|
942
|
+
await runCommand(pm, ['run', 'build'], bffDir, 'Managed BFF build');
|
|
943
|
+
const bffProcess = (0, child_process_1.spawn)('func', buildFunctionsStartArgs(bffPort), {
|
|
944
|
+
cwd: bffDir, shell: true, stdio: 'inherit', env: nextEnv,
|
|
945
|
+
});
|
|
946
|
+
processes.push(bffProcess);
|
|
947
|
+
bffProcess.on('error', error => console.error('❌ Managed BFF startup error:', error.message));
|
|
948
|
+
bffProcess.on('close', code => {
|
|
949
|
+
console.error(`⏹️ Managed BFF exited (exit code: ${code})`);
|
|
950
|
+
stopDevProcesses(processes);
|
|
951
|
+
process.exit(code || 1);
|
|
952
|
+
});
|
|
953
|
+
if (!await waitForHttpServerReady(buildFunctionsBaseUrl(options.host, bffPort))) {
|
|
954
|
+
throw new Error(`Managed BFF did not become ready on port ${bffPort}`);
|
|
955
|
+
}
|
|
956
|
+
}
|
|
883
957
|
const nextProcess = (0, child_process_1.spawn)(pm === 'pnpm' ? 'pnpm' : 'npx', nextArgs, {
|
|
884
958
|
cwd: process.cwd(),
|
|
885
959
|
shell: true,
|
|
@@ -888,22 +962,19 @@ async function startDevEnvironment(options) {
|
|
|
888
962
|
});
|
|
889
963
|
processes.push(nextProcess);
|
|
890
964
|
nextProcess.on('error', (error) => {
|
|
891
|
-
console.error(
|
|
965
|
+
console.error(`❌ ${frontendLabel} startup error:`, error.message);
|
|
966
|
+
stopDevProcesses(processes);
|
|
892
967
|
process.exit(1);
|
|
893
968
|
});
|
|
894
969
|
nextProcess.on('close', (code) => {
|
|
895
970
|
if (code !== 0) {
|
|
896
|
-
console.log(`\n⏹️
|
|
971
|
+
console.log(`\n⏹️ ${frontendLabel} exited (exit code: ${code})`);
|
|
897
972
|
}
|
|
898
|
-
// Exit all processes when
|
|
973
|
+
// Exit all owned processes when the frontend exits.
|
|
899
974
|
if (mockServer) {
|
|
900
975
|
mockServer.stop().catch(() => { });
|
|
901
976
|
}
|
|
902
|
-
processes
|
|
903
|
-
if (proc && !proc.killed) {
|
|
904
|
-
proc.kill();
|
|
905
|
-
}
|
|
906
|
-
});
|
|
977
|
+
stopDevProcesses(processes);
|
|
907
978
|
process.exit(code || 0);
|
|
908
979
|
});
|
|
909
980
|
if (functionsReadinessPromise) {
|
|
@@ -919,13 +990,13 @@ async function startDevEnvironment(options) {
|
|
|
919
990
|
let swaReady = false;
|
|
920
991
|
if (useSwaEmulator && swaCommand) {
|
|
921
992
|
const nextUrl = `http://${options.host || 'localhost'}:${port}`;
|
|
922
|
-
console.log(`⏳ Waiting for
|
|
993
|
+
console.log(`⏳ Waiting for ${frontendLabel} before starting the SWA emulator at ${nextUrl}...`);
|
|
923
994
|
const nextReady = await waitForHttpServerReady(nextUrl);
|
|
924
995
|
if (!nextReady) {
|
|
925
|
-
throw new Error(
|
|
996
|
+
throw new Error(`${frontendLabel} did not become ready at ${nextUrl}`);
|
|
926
997
|
}
|
|
927
|
-
console.log(`🔐 Starting SWA authentication emulator (port: ${swaPort})...`);
|
|
928
|
-
const swaProcess = (0, child_process_1.spawn)(swaCommand, buildSwaStartArgs(options.host, port, swaPort), {
|
|
998
|
+
console.log(`🔐 Starting SWA routing/authentication emulator (port: ${swaPort})...`);
|
|
999
|
+
const swaProcess = (0, child_process_1.spawn)(swaCommand, buildSwaStartArgs(options.host, port, swaPort, react ? bffPort : undefined), {
|
|
929
1000
|
cwd: process.cwd(),
|
|
930
1001
|
shell: true,
|
|
931
1002
|
stdio: 'inherit',
|
|
@@ -938,7 +1009,7 @@ async function startDevEnvironment(options) {
|
|
|
938
1009
|
const swaUrl = `http://${options.host || 'localhost'}:${swaPort}`;
|
|
939
1010
|
swaReady = await waitForHttpServerReady(swaUrl);
|
|
940
1011
|
if (!swaReady) {
|
|
941
|
-
throw new Error(`SWA authentication emulator did not become ready at ${swaUrl}`);
|
|
1012
|
+
throw new Error(`SWA routing/authentication emulator did not become ready at ${swaUrl}`);
|
|
942
1013
|
}
|
|
943
1014
|
}
|
|
944
1015
|
console.log('');
|
|
@@ -946,19 +1017,26 @@ async function startDevEnvironment(options) {
|
|
|
946
1017
|
console.log('');
|
|
947
1018
|
if (useSwaEmulator) {
|
|
948
1019
|
const swaUrl = `http://${options.host || 'localhost'}:${swaPort}`;
|
|
949
|
-
console.log('🔐 SWA
|
|
1020
|
+
console.log('🔐 SWA app (same-origin frontend and BFF):');
|
|
950
1021
|
console.log(` ${swaUrl}`);
|
|
951
1022
|
console.log('');
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1023
|
+
if (swaScheme) {
|
|
1024
|
+
const provider = swaScheme.swa?.allowedProviders?.[0] || 'aad';
|
|
1025
|
+
console.log('🔑 Local SWA sign-in:');
|
|
1026
|
+
console.log(` ${swaUrl}/.auth/login/${provider}`);
|
|
1027
|
+
console.log(' Enter any username and select Login.');
|
|
1028
|
+
console.log(' The "authenticated" role is added automatically.');
|
|
1029
|
+
console.log('');
|
|
1030
|
+
}
|
|
1031
|
+
if (authSchemes.some(scheme => scheme.provider === 'custom-jwt')) {
|
|
1032
|
+
console.log(`🔑 Application sign-in: ${swaUrl}/login`);
|
|
1033
|
+
console.log('');
|
|
1034
|
+
}
|
|
1035
|
+
console.log(`📱 ${frontendLabel} direct access (SWA routing/authentication is not emulated):`);
|
|
958
1036
|
console.log(` http://${options.host || 'localhost'}:${port}`);
|
|
959
1037
|
}
|
|
960
1038
|
else {
|
|
961
|
-
console.log(`📱
|
|
1039
|
+
console.log(`📱 ${frontendLabel}: http://${options.host || 'localhost'}:${port}`);
|
|
962
1040
|
}
|
|
963
1041
|
if (hasFunctions && !options.noFunctions) {
|
|
964
1042
|
console.log(`${functionsReady ? '⚡ Azure Functions' : '⏳ Azure Functions (starting)'}: ${functionsBaseUrl}`);
|
|
@@ -968,7 +1046,7 @@ async function startDevEnvironment(options) {
|
|
|
968
1046
|
}
|
|
969
1047
|
console.log('');
|
|
970
1048
|
if (hasFunctions && !options.noFunctions && functionsReady) {
|
|
971
|
-
console.log(
|
|
1049
|
+
console.log(`💡 Azure Functions and ${react ? 'managed Functions' : 'Next.js'} BFF are connected`);
|
|
972
1050
|
}
|
|
973
1051
|
else if (hasFunctions && !options.noFunctions) {
|
|
974
1052
|
console.log('💡 Azure Functions is still warming up; BFF routes can fail until the backend responds.');
|
|
@@ -979,6 +1057,8 @@ async function startDevEnvironment(options) {
|
|
|
979
1057
|
if (swaReady) {
|
|
980
1058
|
console.log('💡 Open the app through the SWA port when testing authenticated pages and CRUD APIs.');
|
|
981
1059
|
}
|
|
1060
|
+
if (react)
|
|
1061
|
+
console.log(`🔀 Managed BFF: ${buildFunctionsBaseUrl(options.host, bffPort)} (not the standalone Functions endpoint)`);
|
|
982
1062
|
console.log('');
|
|
983
1063
|
if (options.open) {
|
|
984
1064
|
const url = useSwaEmulator
|
|
@@ -995,11 +1075,7 @@ async function startDevEnvironment(options) {
|
|
|
995
1075
|
}
|
|
996
1076
|
catch (error) {
|
|
997
1077
|
console.error('❌ Failed to start development environment:', error instanceof Error ? error.message : error);
|
|
998
|
-
processes
|
|
999
|
-
if (proc && !proc.killed) {
|
|
1000
|
-
proc.kill();
|
|
1001
|
-
}
|
|
1002
|
-
});
|
|
1078
|
+
stopDevProcesses(processes);
|
|
1003
1079
|
process.exit(1);
|
|
1004
1080
|
}
|
|
1005
1081
|
}
|