@domainlang/language 0.1.82 → 0.4.0
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.md +18 -18
- package/out/domain-lang-module.d.ts +2 -0
- package/out/domain-lang-module.js +11 -3
- package/out/domain-lang-module.js.map +1 -1
- package/out/generated/ast.d.ts +8 -19
- package/out/generated/ast.js +1 -10
- package/out/generated/ast.js.map +1 -1
- package/out/generated/grammar.d.ts +1 -1
- package/out/generated/grammar.js +28 -123
- package/out/generated/grammar.js.map +1 -1
- package/out/generated/module.d.ts +1 -1
- package/out/generated/module.js +1 -1
- package/out/index.d.ts +3 -0
- package/out/index.js +5 -0
- package/out/index.js.map +1 -1
- package/out/lsp/domain-lang-code-actions.d.ts +55 -0
- package/out/lsp/domain-lang-code-actions.js +143 -0
- package/out/lsp/domain-lang-code-actions.js.map +1 -0
- package/out/lsp/domain-lang-workspace-manager.d.ts +21 -0
- package/out/lsp/domain-lang-workspace-manager.js +93 -0
- package/out/lsp/domain-lang-workspace-manager.js.map +1 -0
- package/out/lsp/hover/domain-lang-hover.js +0 -4
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/lsp/manifest-diagnostics.d.ts +82 -0
- package/out/lsp/manifest-diagnostics.js +230 -0
- package/out/lsp/manifest-diagnostics.js.map +1 -0
- package/out/sdk/index.d.ts +1 -1
- package/out/sdk/loader-node.d.ts +7 -3
- package/out/sdk/loader-node.js +24 -9
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/types.d.ts +0 -21
- package/out/services/dependency-analyzer.d.ts +3 -39
- package/out/services/dependency-analyzer.js +22 -47
- package/out/services/dependency-analyzer.js.map +1 -1
- package/out/services/dependency-resolver.d.ts +68 -45
- package/out/services/dependency-resolver.js +243 -43
- package/out/services/dependency-resolver.js.map +1 -1
- package/out/services/git-url-resolver.browser.d.ts +4 -12
- package/out/services/git-url-resolver.browser.js +5 -1
- package/out/services/git-url-resolver.browser.js.map +1 -1
- package/out/services/git-url-resolver.d.ts +22 -56
- package/out/services/git-url-resolver.js +70 -36
- package/out/services/git-url-resolver.js.map +1 -1
- package/out/services/governance-validator.d.ts +1 -37
- package/out/services/governance-validator.js +4 -10
- package/out/services/governance-validator.js.map +1 -1
- package/out/services/import-resolver.d.ts +65 -6
- package/out/services/import-resolver.js +223 -5
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/performance-optimizer.d.ts +1 -1
- package/out/services/semver.d.ts +98 -0
- package/out/services/semver.js +195 -0
- package/out/services/semver.js.map +1 -0
- package/out/services/types.d.ts +340 -0
- package/out/services/types.js +46 -0
- package/out/services/types.js.map +1 -0
- package/out/services/workspace-manager.d.ts +57 -10
- package/out/services/workspace-manager.js +187 -21
- package/out/services/workspace-manager.js.map +1 -1
- package/out/syntaxes/domain-lang.monarch.js +1 -1
- package/out/syntaxes/domain-lang.monarch.js.map +1 -1
- package/out/utils/import-utils.d.ts +4 -12
- package/out/utils/import-utils.js +35 -135
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +103 -0
- package/out/validation/constants.js +141 -2
- package/out/validation/constants.js.map +1 -1
- package/out/validation/domain.js +46 -1
- package/out/validation/domain.js.map +1 -1
- package/out/validation/import.d.ts +46 -22
- package/out/validation/import.js +187 -85
- package/out/validation/import.js.map +1 -1
- package/out/validation/manifest.d.ts +144 -0
- package/out/validation/manifest.js +327 -0
- package/out/validation/manifest.js.map +1 -0
- package/out/validation/maps.js +10 -6
- package/out/validation/maps.js.map +1 -1
- package/out/validation/metadata.js +5 -1
- package/out/validation/metadata.js.map +1 -1
- package/package.json +8 -6
- package/src/domain-lang-module.ts +18 -6
- package/src/domain-lang.langium +7 -12
- package/src/generated/ast.ts +7 -20
- package/src/generated/grammar.ts +28 -123
- package/src/generated/module.ts +1 -1
- package/src/index.ts +7 -0
- package/src/lsp/domain-lang-code-actions.ts +189 -0
- package/src/lsp/domain-lang-workspace-manager.ts +104 -0
- package/src/lsp/hover/domain-lang-hover.ts +0 -2
- package/src/lsp/manifest-diagnostics.ts +290 -0
- package/src/sdk/index.ts +0 -2
- package/src/sdk/loader-node.ts +29 -9
- package/src/sdk/types.ts +0 -23
- package/src/services/dependency-analyzer.ts +24 -84
- package/src/services/dependency-resolver.ts +301 -84
- package/src/services/git-url-resolver.browser.ts +9 -14
- package/src/services/git-url-resolver.ts +86 -93
- package/src/services/governance-validator.ts +5 -47
- package/src/services/import-resolver.ts +270 -8
- package/src/services/performance-optimizer.ts +1 -1
- package/src/services/semver.ts +213 -0
- package/src/services/types.ts +415 -0
- package/src/services/workspace-manager.ts +237 -46
- package/src/syntaxes/domain-lang.monarch.ts +1 -1
- package/src/utils/import-utils.ts +38 -160
- package/src/validation/constants.ts +182 -2
- package/src/validation/domain.ts +54 -1
- package/src/validation/import.ts +228 -104
- package/src/validation/manifest.ts +439 -0
- package/src/validation/maps.ts +10 -6
- package/src/validation/metadata.ts +5 -1
|
@@ -1,16 +1,224 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { URI } from 'langium';
|
|
1
4
|
/**
|
|
2
|
-
* ImportResolver resolves import statements using
|
|
5
|
+
* ImportResolver resolves import statements using manifest-centric rules (PRS-010).
|
|
6
|
+
*
|
|
7
|
+
* Import Types (PRS-010):
|
|
8
|
+
* - Local relative: ./path, ../path → Directory-first resolution
|
|
9
|
+
* - Path aliases: @/path, @alias/path → Configurable in model.yaml paths section
|
|
10
|
+
* - External: owner/package → Manifest dependencies
|
|
11
|
+
*
|
|
12
|
+
* Directory-First Resolution:
|
|
13
|
+
* - ./types → ./types/index.dlang → ./types.dlang
|
|
14
|
+
* - Module entry defaults to index.dlang (no model.yaml required)
|
|
3
15
|
*/
|
|
4
16
|
export class ImportResolver {
|
|
5
17
|
constructor(services) {
|
|
6
18
|
this.workspaceManager = services.imports.WorkspaceManager;
|
|
7
19
|
}
|
|
8
20
|
/**
|
|
9
|
-
* Resolve an import
|
|
21
|
+
* Resolve an import specifier relative to a Langium document.
|
|
10
22
|
*/
|
|
11
|
-
async
|
|
12
|
-
const
|
|
13
|
-
return
|
|
23
|
+
async resolveForDocument(document, specifier) {
|
|
24
|
+
const baseDir = path.dirname(document.uri.fsPath);
|
|
25
|
+
return this.resolveFrom(baseDir, specifier);
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Resolve an import specifier from a base directory (non-LSP contexts).
|
|
29
|
+
*/
|
|
30
|
+
async resolveFrom(baseDir, specifier) {
|
|
31
|
+
await this.workspaceManager.initialize(baseDir);
|
|
32
|
+
// Local relative paths (./path or ../path) - directory-first resolution
|
|
33
|
+
if (specifier.startsWith('./') || specifier.startsWith('../')) {
|
|
34
|
+
const resolved = path.resolve(baseDir, specifier);
|
|
35
|
+
return this.resolveLocalPath(resolved, specifier);
|
|
36
|
+
}
|
|
37
|
+
// Path aliases (@/path or @alias/path)
|
|
38
|
+
if (specifier.startsWith('@')) {
|
|
39
|
+
return this.resolvePathAlias(specifier);
|
|
40
|
+
}
|
|
41
|
+
// External dependency via manifest (owner/package format)
|
|
42
|
+
return this.resolveExternalDependency(specifier);
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Resolves a path alias import.
|
|
46
|
+
*
|
|
47
|
+
* @param specifier - Import specifier starting with @ (e.g., "@/lib", "@shared/types")
|
|
48
|
+
*/
|
|
49
|
+
async resolvePathAlias(specifier) {
|
|
50
|
+
const aliases = await this.workspaceManager.getPathAliases();
|
|
51
|
+
const root = this.workspaceManager.getWorkspaceRoot();
|
|
52
|
+
// Find matching alias
|
|
53
|
+
const aliasMatch = this.findMatchingAlias(specifier, aliases);
|
|
54
|
+
if (aliasMatch) {
|
|
55
|
+
const { alias: _alias, targetPath, remainder } = aliasMatch;
|
|
56
|
+
const manifestPath = await this.workspaceManager.getManifestPath();
|
|
57
|
+
const manifestDir = manifestPath ? path.dirname(manifestPath) : root;
|
|
58
|
+
const resolvedBase = path.resolve(manifestDir, targetPath);
|
|
59
|
+
const resolved = remainder ? path.join(resolvedBase, remainder) : resolvedBase;
|
|
60
|
+
return this.resolveLocalPath(resolved, specifier);
|
|
61
|
+
}
|
|
62
|
+
// Default: @/ maps to workspace root (implicit)
|
|
63
|
+
if (specifier.startsWith('@/')) {
|
|
64
|
+
const relativePath = specifier.slice(2);
|
|
65
|
+
const resolved = path.join(root, relativePath);
|
|
66
|
+
return this.resolveLocalPath(resolved, specifier);
|
|
67
|
+
}
|
|
68
|
+
throw new Error(`Unknown path alias '${specifier.split('/')[0]}' in import '${specifier}'.\n` +
|
|
69
|
+
`Hint: Define it in model.yaml paths section:\n` +
|
|
70
|
+
` paths:\n` +
|
|
71
|
+
` "${specifier.split('/')[0]}": "./some/path"`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Finds the longest matching alias for a specifier.
|
|
75
|
+
*/
|
|
76
|
+
findMatchingAlias(specifier, aliases) {
|
|
77
|
+
if (!aliases) {
|
|
78
|
+
return undefined;
|
|
79
|
+
}
|
|
80
|
+
// Sort by length descending to match most specific alias first
|
|
81
|
+
const sortedAliases = Object.entries(aliases)
|
|
82
|
+
.sort(([a], [b]) => b.length - a.length);
|
|
83
|
+
for (const [alias, targetPath] of sortedAliases) {
|
|
84
|
+
// Exact match
|
|
85
|
+
if (specifier === alias) {
|
|
86
|
+
return { alias, targetPath, remainder: '' };
|
|
87
|
+
}
|
|
88
|
+
// Prefix match (alias + /)
|
|
89
|
+
if (specifier.startsWith(`${alias}/`)) {
|
|
90
|
+
return { alias, targetPath, remainder: specifier.slice(alias.length + 1) };
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
return undefined;
|
|
94
|
+
}
|
|
95
|
+
/**
|
|
96
|
+
* Resolves an external dependency via manifest.
|
|
97
|
+
*
|
|
98
|
+
* NEW FORMAT (PRS-010): Import specifier is owner/package format.
|
|
99
|
+
*/
|
|
100
|
+
async resolveExternalDependency(specifier) {
|
|
101
|
+
const manifest = await this.workspaceManager.getManifest();
|
|
102
|
+
if (!manifest) {
|
|
103
|
+
throw new Error(`External dependency '${specifier}' requires model.yaml.\n` +
|
|
104
|
+
`Hint: Create model.yaml and add the dependency:\n` +
|
|
105
|
+
` dependencies:\n` +
|
|
106
|
+
` ${specifier}:\n` +
|
|
107
|
+
` ref: v1.0.0`);
|
|
108
|
+
}
|
|
109
|
+
const lock = await this.workspaceManager.getLockFile();
|
|
110
|
+
if (!lock) {
|
|
111
|
+
throw new Error(`Dependency '${specifier}' not installed.\n` +
|
|
112
|
+
`Hint: Run 'dlang install' to fetch dependencies and generate model.lock.`);
|
|
113
|
+
}
|
|
114
|
+
const mapped = await this.workspaceManager.resolveDependencyImport(specifier);
|
|
115
|
+
if (!mapped) {
|
|
116
|
+
throw new Error(`Dependency '${specifier}' not found in model.yaml.\n` +
|
|
117
|
+
`Hint: Add it to your dependencies:\n` +
|
|
118
|
+
` dependencies:\n` +
|
|
119
|
+
` ${specifier}:\n` +
|
|
120
|
+
` ref: v1.0.0`);
|
|
121
|
+
}
|
|
122
|
+
const git = await this.workspaceManager.getGitResolver();
|
|
123
|
+
return git.resolve(mapped, { allowNetwork: false });
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Resolves a local path using directory-first resolution.
|
|
127
|
+
*
|
|
128
|
+
* Per PRS-010 (updated design):
|
|
129
|
+
* - If path ends with .dlang → direct file import
|
|
130
|
+
* - If no extension → directory-first:
|
|
131
|
+
* 1. Try ./path/index.dlang (module default, no model.yaml required)
|
|
132
|
+
* 2. Try ./path.dlang (file fallback)
|
|
133
|
+
*/
|
|
134
|
+
async resolveLocalPath(resolved, original) {
|
|
135
|
+
const ext = path.extname(resolved);
|
|
136
|
+
if (ext === '.dlang') {
|
|
137
|
+
// Direct file import
|
|
138
|
+
await assertFileExists(resolved, original);
|
|
139
|
+
return URI.file(resolved);
|
|
140
|
+
}
|
|
141
|
+
if (ext && ext !== '.dlang') {
|
|
142
|
+
throw new Error(`Invalid file extension '${ext}' in import '${original}'.\n` +
|
|
143
|
+
`Hint: DomainLang files must use the .dlang extension.`);
|
|
144
|
+
}
|
|
145
|
+
// No extension → directory-first resolution
|
|
146
|
+
return this.resolveDirectoryFirst(resolved, original);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Directory-first resolution: ./types → ./types/index.dlang → ./types.dlang
|
|
150
|
+
*
|
|
151
|
+
* Module entry defaults to index.dlang without requiring model.yaml.
|
|
152
|
+
* If the directory has model.yaml with custom entry, use that.
|
|
153
|
+
*/
|
|
154
|
+
async resolveDirectoryFirst(resolved, original) {
|
|
155
|
+
// Step 1: Check if directory exists with index.dlang (or custom entry)
|
|
156
|
+
const isDirectory = await this.isDirectory(resolved);
|
|
157
|
+
if (isDirectory) {
|
|
158
|
+
// Check for model.yaml to get custom entry point
|
|
159
|
+
const moduleManifestPath = path.join(resolved, 'model.yaml');
|
|
160
|
+
const entryPoint = await this.readModuleEntry(moduleManifestPath);
|
|
161
|
+
const entryFile = path.join(resolved, entryPoint);
|
|
162
|
+
if (await this.fileExists(entryFile)) {
|
|
163
|
+
return URI.file(entryFile);
|
|
164
|
+
}
|
|
165
|
+
// Directory exists but no entry file
|
|
166
|
+
throw new Error(`Module '${original}' is missing its entry file.\n` +
|
|
167
|
+
`Expected: ${resolved}/${entryPoint}\n` +
|
|
168
|
+
`Hint: Create '${entryPoint}' in the module directory, or specify a custom entry in model.yaml:\n` +
|
|
169
|
+
` model:\n` +
|
|
170
|
+
` entry: main.dlang`);
|
|
171
|
+
}
|
|
172
|
+
// Step 2: Try .dlang file fallback
|
|
173
|
+
const fileWithExt = `${resolved}.dlang`;
|
|
174
|
+
if (await this.fileExists(fileWithExt)) {
|
|
175
|
+
return URI.file(fileWithExt);
|
|
176
|
+
}
|
|
177
|
+
// Neither directory nor file found
|
|
178
|
+
throw new Error(`Cannot resolve import '${original}'.\n` +
|
|
179
|
+
`Tried:\n` +
|
|
180
|
+
` • ${resolved}/index.dlang (directory module)\n` +
|
|
181
|
+
` • ${resolved}.dlang (file)\n` +
|
|
182
|
+
`Hint: Check that the path is correct and the file exists.`);
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Reads the entry point from a module's model.yaml.
|
|
186
|
+
* Defaults to index.dlang if no manifest or no entry specified.
|
|
187
|
+
*/
|
|
188
|
+
async readModuleEntry(manifestPath) {
|
|
189
|
+
try {
|
|
190
|
+
const content = await fs.readFile(manifestPath, 'utf-8');
|
|
191
|
+
const YAML = await import('yaml');
|
|
192
|
+
const manifest = YAML.parse(content);
|
|
193
|
+
return manifest?.model?.entry ?? 'index.dlang';
|
|
194
|
+
}
|
|
195
|
+
catch {
|
|
196
|
+
return 'index.dlang';
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Checks if a path is a directory.
|
|
201
|
+
*/
|
|
202
|
+
async isDirectory(targetPath) {
|
|
203
|
+
try {
|
|
204
|
+
const stat = await fs.stat(targetPath);
|
|
205
|
+
return stat.isDirectory();
|
|
206
|
+
}
|
|
207
|
+
catch {
|
|
208
|
+
return false;
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Checks if a file exists.
|
|
213
|
+
*/
|
|
214
|
+
async fileExists(filePath) {
|
|
215
|
+
try {
|
|
216
|
+
await fs.access(filePath);
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
catch {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
14
222
|
}
|
|
15
223
|
/**
|
|
16
224
|
* Get the current lock file (if loaded).
|
|
@@ -19,4 +227,14 @@ export class ImportResolver {
|
|
|
19
227
|
return this.workspaceManager.getLockFile();
|
|
20
228
|
}
|
|
21
229
|
}
|
|
230
|
+
async function assertFileExists(filePath, original) {
|
|
231
|
+
try {
|
|
232
|
+
await fs.access(filePath);
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
throw new Error(`Import file not found: '${original}'.\\n` +
|
|
236
|
+
`Resolved path: ${filePath}\\n` +
|
|
237
|
+
`Hint: Check that the file exists and the path is correct.`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
22
240
|
//# sourceMappingURL=import-resolver.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/services/import-resolver.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"import-resolver.js","sourceRoot":"","sources":["../../src/services/import-resolver.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Versioning Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized SemVer parsing, comparison, and validation for the dependency system.
|
|
5
|
+
* All version-related logic should use these utilities to ensure consistency.
|
|
6
|
+
*
|
|
7
|
+
* Supported formats:
|
|
8
|
+
* - "1.0.0" or "v1.0.0" (tags)
|
|
9
|
+
* - "1.0.0-alpha.1" (pre-release)
|
|
10
|
+
* - "main", "develop" (branches)
|
|
11
|
+
* - "abc123def" (commit SHAs, 7-40 hex chars)
|
|
12
|
+
*/
|
|
13
|
+
import type { SemVer, RefType, ParsedRef } from './types.js';
|
|
14
|
+
/**
|
|
15
|
+
* Parses a version string into SemVer components.
|
|
16
|
+
* Returns undefined if not a valid SemVer.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* parseSemVer("v1.2.3") // { major: 1, minor: 2, patch: 3, original: "v1.2.3" }
|
|
20
|
+
* parseSemVer("1.0.0-alpha") // { major: 1, minor: 0, patch: 0, prerelease: "alpha", ... }
|
|
21
|
+
* parseSemVer("main") // undefined (not SemVer)
|
|
22
|
+
*/
|
|
23
|
+
export declare function parseSemVer(version: string): SemVer | undefined;
|
|
24
|
+
/**
|
|
25
|
+
* Detects the type of a git ref based on its format.
|
|
26
|
+
*
|
|
27
|
+
* @example
|
|
28
|
+
* detectRefType("v1.0.0") // 'tag'
|
|
29
|
+
* detectRefType("1.2.3") // 'tag'
|
|
30
|
+
* detectRefType("main") // 'branch'
|
|
31
|
+
* detectRefType("abc123def") // 'commit'
|
|
32
|
+
*/
|
|
33
|
+
export declare function detectRefType(ref: string): RefType;
|
|
34
|
+
/**
|
|
35
|
+
* Parses a ref string into a structured ParsedRef with type and optional SemVer.
|
|
36
|
+
*/
|
|
37
|
+
export declare function parseRef(ref: string): ParsedRef;
|
|
38
|
+
/**
|
|
39
|
+
* Compares two SemVer versions.
|
|
40
|
+
* Returns: negative if a < b, positive if a > b, zero if equal.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* compareSemVer(parse("1.0.0"), parse("2.0.0")) // negative (a < b)
|
|
44
|
+
* compareSemVer(parse("1.5.0"), parse("1.2.0")) // positive (a > b)
|
|
45
|
+
* compareSemVer(parse("1.0.0-alpha"), parse("1.0.0")) // negative (prerelease < release)
|
|
46
|
+
*/
|
|
47
|
+
export declare function compareSemVer(a: SemVer, b: SemVer): number;
|
|
48
|
+
/**
|
|
49
|
+
* Picks the latest from a list of SemVer refs.
|
|
50
|
+
* Returns the ref string (with original 'v' prefix if present).
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* pickLatestSemVer(["v1.0.0", "v1.5.0", "v1.2.0"]) // "v1.5.0"
|
|
54
|
+
*/
|
|
55
|
+
export declare function pickLatestSemVer(refs: string[]): string | undefined;
|
|
56
|
+
/**
|
|
57
|
+
* Sorts version strings in descending order (newest first).
|
|
58
|
+
* Non-SemVer refs are sorted lexicographically at the end.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* sortVersionsDescending(["v1.0.0", "v2.0.0", "v1.5.0"]) // ["v2.0.0", "v1.5.0", "v1.0.0"]
|
|
62
|
+
*/
|
|
63
|
+
export declare function sortVersionsDescending(versions: string[]): string[];
|
|
64
|
+
/**
|
|
65
|
+
* Checks if a version/ref is a pre-release.
|
|
66
|
+
*
|
|
67
|
+
* Pre-release identifiers: alpha, beta, rc, pre, dev, snapshot
|
|
68
|
+
*
|
|
69
|
+
* @example
|
|
70
|
+
* isPreRelease("v1.0.0") // false
|
|
71
|
+
* isPreRelease("v1.0.0-alpha") // true
|
|
72
|
+
* isPreRelease("v1.0.0-rc.1") // true
|
|
73
|
+
*/
|
|
74
|
+
export declare function isPreRelease(ref: string): boolean;
|
|
75
|
+
/**
|
|
76
|
+
* Checks if two SemVer versions are compatible (same major version).
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* areSameMajor(parse("1.0.0"), parse("1.5.0")) // true
|
|
80
|
+
* areSameMajor(parse("1.0.0"), parse("2.0.0")) // false
|
|
81
|
+
*/
|
|
82
|
+
export declare function areSameMajor(a: SemVer, b: SemVer): boolean;
|
|
83
|
+
/**
|
|
84
|
+
* Gets the major version number from a ref string.
|
|
85
|
+
* Returns undefined if not a valid SemVer.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getMajorVersion(ref: string): number | undefined;
|
|
88
|
+
/**
|
|
89
|
+
* Filters refs to only stable versions (excludes pre-releases).
|
|
90
|
+
*
|
|
91
|
+
* @example
|
|
92
|
+
* filterStableVersions(["v1.0.0", "v1.1.0-alpha", "v1.2.0"]) // ["v1.0.0", "v1.2.0"]
|
|
93
|
+
*/
|
|
94
|
+
export declare function filterStableVersions(refs: string[]): string[];
|
|
95
|
+
/**
|
|
96
|
+
* Filters refs to only SemVer tags (excludes branches and commits).
|
|
97
|
+
*/
|
|
98
|
+
export declare function filterSemVerTags(refs: string[]): string[];
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Versioning Utilities
|
|
3
|
+
*
|
|
4
|
+
* Centralized SemVer parsing, comparison, and validation for the dependency system.
|
|
5
|
+
* All version-related logic should use these utilities to ensure consistency.
|
|
6
|
+
*
|
|
7
|
+
* Supported formats:
|
|
8
|
+
* - "1.0.0" or "v1.0.0" (tags)
|
|
9
|
+
* - "1.0.0-alpha.1" (pre-release)
|
|
10
|
+
* - "main", "develop" (branches)
|
|
11
|
+
* - "abc123def" (commit SHAs, 7-40 hex chars)
|
|
12
|
+
*/
|
|
13
|
+
// ============================================================================
|
|
14
|
+
// Parsing
|
|
15
|
+
// ============================================================================
|
|
16
|
+
/**
|
|
17
|
+
* Parses a version string into SemVer components.
|
|
18
|
+
* Returns undefined if not a valid SemVer.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* parseSemVer("v1.2.3") // { major: 1, minor: 2, patch: 3, original: "v1.2.3" }
|
|
22
|
+
* parseSemVer("1.0.0-alpha") // { major: 1, minor: 0, patch: 0, prerelease: "alpha", ... }
|
|
23
|
+
* parseSemVer("main") // undefined (not SemVer)
|
|
24
|
+
*/
|
|
25
|
+
export function parseSemVer(version) {
|
|
26
|
+
// Strip leading 'v' if present
|
|
27
|
+
const normalized = version.startsWith('v') ? version.slice(1) : version;
|
|
28
|
+
// Match semver pattern: major.minor.patch[-prerelease]
|
|
29
|
+
const match = normalized.match(/^(\d+)\.(\d+)\.(\d+)(?:-(.+))?$/);
|
|
30
|
+
if (!match)
|
|
31
|
+
return undefined;
|
|
32
|
+
return {
|
|
33
|
+
major: parseInt(match[1], 10),
|
|
34
|
+
minor: parseInt(match[2], 10),
|
|
35
|
+
patch: parseInt(match[3], 10),
|
|
36
|
+
preRelease: match[4],
|
|
37
|
+
original: version,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Detects the type of a git ref based on its format.
|
|
42
|
+
*
|
|
43
|
+
* @example
|
|
44
|
+
* detectRefType("v1.0.0") // 'tag'
|
|
45
|
+
* detectRefType("1.2.3") // 'tag'
|
|
46
|
+
* detectRefType("main") // 'branch'
|
|
47
|
+
* detectRefType("abc123def") // 'commit'
|
|
48
|
+
*/
|
|
49
|
+
export function detectRefType(ref) {
|
|
50
|
+
// Commit SHA: 7-40 hex characters
|
|
51
|
+
if (/^[0-9a-f]{7,40}$/i.test(ref)) {
|
|
52
|
+
return 'commit';
|
|
53
|
+
}
|
|
54
|
+
// Tags typically start with 'v' followed by semver
|
|
55
|
+
if (/^v?\d+\.\d+\.\d+/.test(ref)) {
|
|
56
|
+
return 'tag';
|
|
57
|
+
}
|
|
58
|
+
// Everything else is treated as a branch
|
|
59
|
+
return 'branch';
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Parses a ref string into a structured ParsedRef with type and optional SemVer.
|
|
63
|
+
*/
|
|
64
|
+
export function parseRef(ref) {
|
|
65
|
+
const type = detectRefType(ref);
|
|
66
|
+
const semver = type === 'tag' ? parseSemVer(ref) : undefined;
|
|
67
|
+
return { original: ref, type, semver };
|
|
68
|
+
}
|
|
69
|
+
// ============================================================================
|
|
70
|
+
// Comparison
|
|
71
|
+
// ============================================================================
|
|
72
|
+
/**
|
|
73
|
+
* Compares two SemVer versions.
|
|
74
|
+
* Returns: negative if a < b, positive if a > b, zero if equal.
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* compareSemVer(parse("1.0.0"), parse("2.0.0")) // negative (a < b)
|
|
78
|
+
* compareSemVer(parse("1.5.0"), parse("1.2.0")) // positive (a > b)
|
|
79
|
+
* compareSemVer(parse("1.0.0-alpha"), parse("1.0.0")) // negative (prerelease < release)
|
|
80
|
+
*/
|
|
81
|
+
export function compareSemVer(a, b) {
|
|
82
|
+
if (a.major !== b.major)
|
|
83
|
+
return a.major - b.major;
|
|
84
|
+
if (a.minor !== b.minor)
|
|
85
|
+
return a.minor - b.minor;
|
|
86
|
+
if (a.patch !== b.patch)
|
|
87
|
+
return a.patch - b.patch;
|
|
88
|
+
// Pre-release versions are lower than release versions
|
|
89
|
+
if (a.preRelease && !b.preRelease)
|
|
90
|
+
return -1;
|
|
91
|
+
if (!a.preRelease && b.preRelease)
|
|
92
|
+
return 1;
|
|
93
|
+
if (a.preRelease && b.preRelease) {
|
|
94
|
+
return a.preRelease.localeCompare(b.preRelease);
|
|
95
|
+
}
|
|
96
|
+
return 0;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Picks the latest from a list of SemVer refs.
|
|
100
|
+
* Returns the ref string (with original 'v' prefix if present).
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* pickLatestSemVer(["v1.0.0", "v1.5.0", "v1.2.0"]) // "v1.5.0"
|
|
104
|
+
*/
|
|
105
|
+
export function pickLatestSemVer(refs) {
|
|
106
|
+
const parsed = refs
|
|
107
|
+
.map(ref => ({ ref, semver: parseSemVer(ref) }))
|
|
108
|
+
.filter((item) => item.semver !== undefined);
|
|
109
|
+
if (parsed.length === 0)
|
|
110
|
+
return undefined;
|
|
111
|
+
parsed.sort((a, b) => compareSemVer(b.semver, a.semver)); // Descending
|
|
112
|
+
return parsed[0].ref;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* Sorts version strings in descending order (newest first).
|
|
116
|
+
* Non-SemVer refs are sorted lexicographically at the end.
|
|
117
|
+
*
|
|
118
|
+
* @example
|
|
119
|
+
* sortVersionsDescending(["v1.0.0", "v2.0.0", "v1.5.0"]) // ["v2.0.0", "v1.5.0", "v1.0.0"]
|
|
120
|
+
*/
|
|
121
|
+
export function sortVersionsDescending(versions) {
|
|
122
|
+
return [...versions].sort((a, b) => {
|
|
123
|
+
const semverA = parseSemVer(a);
|
|
124
|
+
const semverB = parseSemVer(b);
|
|
125
|
+
// Both are SemVer - compare semantically
|
|
126
|
+
if (semverA && semverB) {
|
|
127
|
+
return compareSemVer(semverB, semverA); // Descending
|
|
128
|
+
}
|
|
129
|
+
// SemVer comes before non-SemVer
|
|
130
|
+
if (semverA && !semverB)
|
|
131
|
+
return -1;
|
|
132
|
+
if (!semverA && semverB)
|
|
133
|
+
return 1;
|
|
134
|
+
// Both non-SemVer - lexicographic
|
|
135
|
+
return b.localeCompare(a);
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
// ============================================================================
|
|
139
|
+
// Validation
|
|
140
|
+
// ============================================================================
|
|
141
|
+
/**
|
|
142
|
+
* Checks if a version/ref is a pre-release.
|
|
143
|
+
*
|
|
144
|
+
* Pre-release identifiers: alpha, beta, rc, pre, dev, snapshot
|
|
145
|
+
*
|
|
146
|
+
* @example
|
|
147
|
+
* isPreRelease("v1.0.0") // false
|
|
148
|
+
* isPreRelease("v1.0.0-alpha") // true
|
|
149
|
+
* isPreRelease("v1.0.0-rc.1") // true
|
|
150
|
+
*/
|
|
151
|
+
export function isPreRelease(ref) {
|
|
152
|
+
const semver = parseSemVer(ref);
|
|
153
|
+
if (semver?.preRelease) {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
// Also check for common pre-release patterns without proper SemVer
|
|
157
|
+
const clean = ref.replace(/^v/, '');
|
|
158
|
+
return /-(alpha|beta|rc|pre|dev|snapshot)/i.test(clean);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Checks if two SemVer versions are compatible (same major version).
|
|
162
|
+
*
|
|
163
|
+
* @example
|
|
164
|
+
* areSameMajor(parse("1.0.0"), parse("1.5.0")) // true
|
|
165
|
+
* areSameMajor(parse("1.0.0"), parse("2.0.0")) // false
|
|
166
|
+
*/
|
|
167
|
+
export function areSameMajor(a, b) {
|
|
168
|
+
return a.major === b.major;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Gets the major version number from a ref string.
|
|
172
|
+
* Returns undefined if not a valid SemVer.
|
|
173
|
+
*/
|
|
174
|
+
export function getMajorVersion(ref) {
|
|
175
|
+
return parseSemVer(ref)?.major;
|
|
176
|
+
}
|
|
177
|
+
// ============================================================================
|
|
178
|
+
// Filtering
|
|
179
|
+
// ============================================================================
|
|
180
|
+
/**
|
|
181
|
+
* Filters refs to only stable versions (excludes pre-releases).
|
|
182
|
+
*
|
|
183
|
+
* @example
|
|
184
|
+
* filterStableVersions(["v1.0.0", "v1.1.0-alpha", "v1.2.0"]) // ["v1.0.0", "v1.2.0"]
|
|
185
|
+
*/
|
|
186
|
+
export function filterStableVersions(refs) {
|
|
187
|
+
return refs.filter(ref => !isPreRelease(ref));
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Filters refs to only SemVer tags (excludes branches and commits).
|
|
191
|
+
*/
|
|
192
|
+
export function filterSemVerTags(refs) {
|
|
193
|
+
return refs.filter(ref => detectRefType(ref) === 'tag' && parseSemVer(ref) !== undefined);
|
|
194
|
+
}
|
|
195
|
+
//# sourceMappingURL=semver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semver.js","sourceRoot":"","sources":["../../src/services/semver.ts"],"names":[],"mappings":"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"}
|