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
package/src/utils/python-uv.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
import * as path from "path";
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import { execFile } from "child_process";
|
|
4
|
+
import { promisify } from "util";
|
|
2
5
|
|
|
3
|
-
|
|
6
|
+
const execFileAsync = promisify(execFile);
|
|
7
|
+
export const DEFAULT_AZURE_PYTHON_VERSION = "3.14";
|
|
4
8
|
|
|
5
9
|
export interface ProjectLocalUvPaths {
|
|
6
10
|
stateDir: string;
|
|
7
|
-
cacheDir: string;
|
|
8
|
-
pythonInstallDir: string;
|
|
9
|
-
toolDir: string;
|
|
10
|
-
toolBinDir: string;
|
|
11
11
|
localUvInstallDir: string;
|
|
12
12
|
localUvExecutable: string;
|
|
13
13
|
}
|
|
@@ -22,10 +22,6 @@ export function getProjectLocalUvPaths(projectRoot: string): ProjectLocalUvPaths
|
|
|
22
22
|
|
|
23
23
|
return {
|
|
24
24
|
stateDir,
|
|
25
|
-
cacheDir: path.join(stateDir, "cache"),
|
|
26
|
-
pythonInstallDir: path.join(stateDir, "python"),
|
|
27
|
-
toolDir: path.join(stateDir, "tools"),
|
|
28
|
-
toolBinDir: path.join(stateDir, "tools", "bin"),
|
|
29
25
|
localUvInstallDir,
|
|
30
26
|
localUvExecutable: process.platform === "win32"
|
|
31
27
|
? path.join(localUvInstallDir, "uv.exe")
|
|
@@ -33,40 +29,26 @@ export function getProjectLocalUvPaths(projectRoot: string): ProjectLocalUvPaths
|
|
|
33
29
|
};
|
|
34
30
|
}
|
|
35
31
|
|
|
36
|
-
export function
|
|
32
|
+
export function buildProjectLocalUvInstallerEnv(
|
|
37
33
|
baseEnv: NodeJS.ProcessEnv,
|
|
38
34
|
projectRoot: string
|
|
39
35
|
): NodeJS.ProcessEnv {
|
|
40
36
|
const uvPaths = getProjectLocalUvPaths(projectRoot);
|
|
37
|
+
|
|
41
38
|
const env: NodeJS.ProcessEnv = {
|
|
42
39
|
...baseEnv,
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
UV_TOOL_DIR: uvPaths.toolDir,
|
|
46
|
-
UV_TOOL_BIN_DIR: uvPaths.toolBinDir,
|
|
47
|
-
UV_PYTHON_PREFERENCE: "only-managed",
|
|
40
|
+
UV_UNMANAGED_INSTALL: uvPaths.localUvInstallDir,
|
|
41
|
+
UV_NO_MODIFY_PATH: "1",
|
|
48
42
|
};
|
|
49
|
-
|
|
43
|
+
// Windows PowerShell must discover its own modules, not inherit PowerShell 7's.
|
|
50
44
|
if (process.platform === "win32") {
|
|
51
|
-
env
|
|
45
|
+
for (const key of Object.keys(env)) {
|
|
46
|
+
if (key.toLowerCase() === "psmodulepath") delete env[key];
|
|
47
|
+
}
|
|
52
48
|
}
|
|
53
|
-
|
|
54
49
|
return env;
|
|
55
50
|
}
|
|
56
51
|
|
|
57
|
-
export function buildProjectLocalUvInstallerEnv(
|
|
58
|
-
baseEnv: NodeJS.ProcessEnv,
|
|
59
|
-
projectRoot: string
|
|
60
|
-
): NodeJS.ProcessEnv {
|
|
61
|
-
const uvPaths = getProjectLocalUvPaths(projectRoot);
|
|
62
|
-
|
|
63
|
-
return {
|
|
64
|
-
...buildProjectLocalUvEnv(baseEnv, projectRoot),
|
|
65
|
-
UV_UNMANAGED_INSTALL: uvPaths.localUvInstallDir,
|
|
66
|
-
UV_NO_MODIFY_PATH: "1",
|
|
67
|
-
};
|
|
68
|
-
}
|
|
69
|
-
|
|
70
52
|
export function getProjectLocalUvInstallerCommand(): { command: string; args: string[] } {
|
|
71
53
|
if (process.platform === "win32") {
|
|
72
54
|
return {
|
|
@@ -87,10 +69,48 @@ export function getProjectLocalUvInstallerCommand(): { command: string; args: st
|
|
|
87
69
|
};
|
|
88
70
|
}
|
|
89
71
|
|
|
90
|
-
export function buildUvVenvArgs(venvDir: string
|
|
91
|
-
return ["venv", venvDir
|
|
72
|
+
export function buildUvVenvArgs(venvDir: string): string[] {
|
|
73
|
+
return ["venv", venvDir];
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export function getVirtualEnvPythonPath(venvDir: string): string {
|
|
77
|
+
return process.platform === "win32"
|
|
78
|
+
? path.join(venvDir, "Scripts", "python.exe")
|
|
79
|
+
: path.join(venvDir, "bin", "python");
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export async function ensureUvVirtualEnvironment(
|
|
83
|
+
uvCommand: string,
|
|
84
|
+
venvDir: string,
|
|
85
|
+
cwd: string,
|
|
86
|
+
env: NodeJS.ProcessEnv
|
|
87
|
+
): Promise<string> {
|
|
88
|
+
const pythonExecutable = getVirtualEnvPythonPath(venvDir);
|
|
89
|
+
if (!fs.existsSync(venvDir)) {
|
|
90
|
+
const { stdout, stderr } = await execFileAsync(uvCommand, buildUvVenvArgs(venvDir), { cwd, env });
|
|
91
|
+
if (env.SWALLOWKIT_MACHINE_OUTPUT !== "1") {
|
|
92
|
+
if (stdout) process.stdout.write(stdout);
|
|
93
|
+
if (stderr) process.stderr.write(stderr);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
try {
|
|
97
|
+
await execFileAsync(pythonExecutable, ["--version"], { cwd, env });
|
|
98
|
+
} catch (error) {
|
|
99
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
100
|
+
throw new Error(
|
|
101
|
+
`Cannot execute Python at ${pythonExecutable}: ${reason}\n` +
|
|
102
|
+
"The virtual environment was preserved. Check the interpreter and OS application-control policy. " +
|
|
103
|
+
"To switch Python, explicitly recreate this environment with uv and a trusted interpreter; SwallowKit will not clear it automatically."
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
return pythonExecutable;
|
|
92
107
|
}
|
|
93
108
|
|
|
94
109
|
export function buildUvPipInstallArgs(pythonExecutable: string, requirementsPath: string): string[] {
|
|
95
110
|
return ["pip", "install", "--python", pythonExecutable, "-r", requirementsPath];
|
|
96
111
|
}
|
|
112
|
+
|
|
113
|
+
export function buildPythonCodegenInstallEnv(env: NodeJS.ProcessEnv): NodeJS.ProcessEnv {
|
|
114
|
+
// Codegen reads JSON; PyYAML's optional accelerator must not require a C compiler.
|
|
115
|
+
return { ...env, PYYAML_FORCE_LIBYAML: env.PYYAML_FORCE_LIBYAML ?? "0" };
|
|
116
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
export const REACT_DEV_WATCH_DIRECTORIES = [
|
|
2
|
+
"functions",
|
|
3
|
+
"bff",
|
|
4
|
+
".uv",
|
|
5
|
+
".swallowkit",
|
|
6
|
+
"shared/dist",
|
|
7
|
+
];
|
|
8
|
+
|
|
9
|
+
export function buildReactDevWatchIgnoredSource(rootExpression: string): string {
|
|
10
|
+
return `${JSON.stringify(REACT_DEV_WATCH_DIRECTORIES)}.map(directory => \`\${${rootExpression}.replace(/\\\\/g, '/').replace(/\\/$/, '')}/\${directory}/**\`)`;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function buildReactDevConfigSource(): string {
|
|
14
|
+
return `import { defineConfig, loadConfigFromFile, mergeConfig } from 'vite';
|
|
15
|
+
|
|
16
|
+
export default defineConfig(async env => {
|
|
17
|
+
const loaded = await loadConfigFromFile(env, undefined, process.cwd());
|
|
18
|
+
const config = loaded?.config ?? {};
|
|
19
|
+
if (config.server?.watch === null) return config;
|
|
20
|
+
return mergeConfig(config, {
|
|
21
|
+
plugins: [{
|
|
22
|
+
name: 'swallowkit-dev-watch-boundaries',
|
|
23
|
+
configResolved(resolved) {
|
|
24
|
+
resolved.configFileDependencies.push(...(loaded?.dependencies ?? []));
|
|
25
|
+
},
|
|
26
|
+
}],
|
|
27
|
+
server: { watch: { ignored: ${buildReactDevWatchIgnoredSource("process.cwd()")} } },
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
`;
|
|
31
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
export interface ParsedSemver {
|
|
2
|
+
major: number;
|
|
3
|
+
minor: number;
|
|
4
|
+
patch: number;
|
|
5
|
+
prerelease: Array<string | number>;
|
|
6
|
+
}
|
|
7
|
+
|
|
8
|
+
const SEMVER_PATTERN =
|
|
9
|
+
/^v?(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*)(?:\.(?:0|[1-9]\d*|\d*[A-Za-z-][0-9A-Za-z-]*))*))?(?:\+[0-9A-Za-z-]+(?:\.[0-9A-Za-z-]+)*)?$/;
|
|
10
|
+
|
|
11
|
+
export function parseSemver(value: string | null | undefined): ParsedSemver | null {
|
|
12
|
+
const match = typeof value === "string" ? SEMVER_PATTERN.exec(value.trim()) : null;
|
|
13
|
+
if (!match) return null;
|
|
14
|
+
return {
|
|
15
|
+
major: Number(match[1]),
|
|
16
|
+
minor: Number(match[2]),
|
|
17
|
+
patch: Number(match[3]),
|
|
18
|
+
prerelease: match[4]
|
|
19
|
+
? match[4].split(".").map((identifier) => (/^\d+$/.test(identifier) ? Number(identifier) : identifier))
|
|
20
|
+
: [],
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function isPrerelease(value: string): boolean {
|
|
25
|
+
return (parseSemver(value)?.prerelease.length ?? 0) > 0;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Compares versions by SemVer 2.0 precedence. Build metadata is ignored.
|
|
30
|
+
* Returns null when either value is not a valid version.
|
|
31
|
+
*/
|
|
32
|
+
export function compareSemver(left: string, right: string): number | null {
|
|
33
|
+
const a = parseSemver(left);
|
|
34
|
+
const b = parseSemver(right);
|
|
35
|
+
if (!a || !b) return null;
|
|
36
|
+
|
|
37
|
+
for (const key of ["major", "minor", "patch"] as const) {
|
|
38
|
+
if (a[key] !== b[key]) return a[key] < b[key] ? -1 : 1;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
if (a.prerelease.length === 0 || b.prerelease.length === 0) {
|
|
42
|
+
if (a.prerelease.length === b.prerelease.length) return 0;
|
|
43
|
+
return a.prerelease.length === 0 ? 1 : -1;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const length = Math.max(a.prerelease.length, b.prerelease.length);
|
|
47
|
+
for (let index = 0; index < length; index++) {
|
|
48
|
+
const leftId = a.prerelease[index];
|
|
49
|
+
const rightId = b.prerelease[index];
|
|
50
|
+
if (leftId === undefined) return -1;
|
|
51
|
+
if (rightId === undefined) return 1;
|
|
52
|
+
if (leftId === rightId) continue;
|
|
53
|
+
if (typeof leftId === "number" && typeof rightId === "number") return leftId < rightId ? -1 : 1;
|
|
54
|
+
if (typeof leftId === "number") return -1;
|
|
55
|
+
if (typeof rightId === "number") return 1;
|
|
56
|
+
return leftId < rightId ? -1 : 1;
|
|
57
|
+
}
|
|
58
|
+
return 0;
|
|
59
|
+
}
|