@domainlang/cli 0.5.2 → 0.7.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 +16 -16
- package/out/dependency-commands.d.ts +1 -1
- package/out/dependency-commands.js +52 -24
- package/out/dependency-commands.js.map +1 -1
- package/out/main.d.ts +1 -1
- package/out/main.js +1 -1
- package/out/main.js.map +1 -1
- package/out/services/dependency-analyzer.d.ts +59 -0
- package/out/services/dependency-analyzer.js +260 -0
- package/out/services/dependency-analyzer.js.map +1 -0
- package/out/services/dependency-resolver.d.ts +148 -0
- package/out/services/dependency-resolver.js +448 -0
- package/out/services/dependency-resolver.js.map +1 -0
- package/out/services/git-url-resolver.d.ts +158 -0
- package/out/services/git-url-resolver.js +408 -0
- package/out/services/git-url-resolver.js.map +1 -0
- package/out/services/governance-validator.d.ts +56 -0
- package/out/services/governance-validator.js +171 -0
- package/out/services/governance-validator.js.map +1 -0
- package/out/services/index.d.ts +12 -0
- package/out/services/index.js +13 -0
- package/out/services/index.js.map +1 -0
- 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 +58 -0
- package/out/services/types.js +8 -0
- package/out/services/types.js.map +1 -0
- package/package.json +4 -3
- package/src/dependency-commands.ts +59 -24
- package/src/main.ts +1 -1
- package/src/services/dependency-analyzer.ts +329 -0
- package/src/services/dependency-resolver.ts +546 -0
- package/src/services/git-url-resolver.ts +504 -0
- package/src/services/governance-validator.ts +226 -0
- package/src/services/index.ts +13 -0
- package/src/services/semver.ts +213 -0
- package/src/services/types.ts +81 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI Services Index
|
|
3
|
+
*
|
|
4
|
+
* Exports all CLI-only services for package management.
|
|
5
|
+
* These services contain network operations and should never be used in LSP.
|
|
6
|
+
*/
|
|
7
|
+
export * from './types.js';
|
|
8
|
+
export * from './semver.js';
|
|
9
|
+
export * from './git-url-resolver.js';
|
|
10
|
+
export * from './dependency-resolver.js';
|
|
11
|
+
export * from './dependency-analyzer.js';
|
|
12
|
+
export * from './governance-validator.js';
|
|
13
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/services/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,uBAAuB,CAAC;AACtC,cAAc,0BAA0B,CAAC;AACzC,cAAc,0BAA0B,CAAC;AACzC,cAAc,2BAA2B,CAAC"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Semantic Versioning Utilities (CLI-only)
|
|
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 (CLI-only)
|
|
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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"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types for CLI-only package management services.
|
|
3
|
+
*
|
|
4
|
+
* These types support git-based dependency resolution and governance
|
|
5
|
+
* that only runs in the CLI context (never in LSP).
|
|
6
|
+
*/
|
|
7
|
+
import type { RefType } from '@domainlang/language';
|
|
8
|
+
export type { LockFile, LockedDependency, ModelManifest, DependencySpec, ExtendedDependencySpec, PathAliases, GovernancePolicy, GovernanceMetadata, GovernanceViolation, DependencyTreeNode, ReverseDependency, VersionPolicy, SemVer, RefType, ParsedRef, } from '@domainlang/language';
|
|
9
|
+
/**
|
|
10
|
+
* Parsed git import URL information.
|
|
11
|
+
*/
|
|
12
|
+
export interface GitImportInfo {
|
|
13
|
+
/** Original import string */
|
|
14
|
+
original: string;
|
|
15
|
+
/** Detected platform (github, gitlab, bitbucket, generic) */
|
|
16
|
+
platform: 'github' | 'gitlab' | 'bitbucket' | 'generic';
|
|
17
|
+
/** Repository owner/organization */
|
|
18
|
+
owner: string;
|
|
19
|
+
/** Repository name */
|
|
20
|
+
repo: string;
|
|
21
|
+
/** Version/tag/branch/commit */
|
|
22
|
+
version: string;
|
|
23
|
+
/** Full repository URL without version */
|
|
24
|
+
repoUrl: string;
|
|
25
|
+
/** Entry point file (default: index.dlang) */
|
|
26
|
+
entryPoint: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Package configuration during dependency resolution.
|
|
30
|
+
*/
|
|
31
|
+
export interface ResolvingPackage {
|
|
32
|
+
name?: string;
|
|
33
|
+
version?: string;
|
|
34
|
+
entry?: string;
|
|
35
|
+
dependencies?: Record<string, string>;
|
|
36
|
+
overrides?: Record<string, string>;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Dependency graph for resolution.
|
|
40
|
+
*/
|
|
41
|
+
export interface DependencyGraph {
|
|
42
|
+
nodes: Record<string, DependencyGraphNode>;
|
|
43
|
+
root: string;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Node in the dependency graph.
|
|
47
|
+
*/
|
|
48
|
+
export interface DependencyGraphNode {
|
|
49
|
+
packageKey: string;
|
|
50
|
+
refConstraint: string;
|
|
51
|
+
constraints?: Set<string>;
|
|
52
|
+
repoUrl?: string;
|
|
53
|
+
dependencies: Record<string, string>;
|
|
54
|
+
dependents: string[];
|
|
55
|
+
resolvedRef?: string;
|
|
56
|
+
refType?: RefType;
|
|
57
|
+
commitHash?: string;
|
|
58
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/services/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@domainlang/cli",
|
|
3
3
|
"displayName": "DomainLang CLI",
|
|
4
4
|
"description": "Command-line interface for DomainLang - validate, analyze, and manage Domain-Driven Design models",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.7.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"author": "larsbaunwall",
|
|
8
8
|
"license": "Apache-2.0",
|
|
@@ -38,13 +38,14 @@
|
|
|
38
38
|
"src"
|
|
39
39
|
],
|
|
40
40
|
"bin": {
|
|
41
|
-
"
|
|
41
|
+
"dlang": "./bin/cli.js"
|
|
42
42
|
},
|
|
43
43
|
"scripts": {
|
|
44
44
|
"clean": "shx rm -fr *.tsbuildinfo out",
|
|
45
45
|
"build": "tsc -b tsconfig.json",
|
|
46
46
|
"build:clean": "npm run clean && npm run build",
|
|
47
|
-
"test": "vitest run"
|
|
47
|
+
"test": "vitest run",
|
|
48
|
+
"test:coverage": "vitest run --coverage"
|
|
48
49
|
},
|
|
49
50
|
"dependencies": {
|
|
50
51
|
"@domainlang/language": "0.1.0",
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { WorkspaceManager
|
|
1
|
+
import { WorkspaceManager } from '@domainlang/language';
|
|
2
|
+
import { DependencyAnalyzer, GovernanceValidator, loadGovernancePolicy, GitUrlResolver, DependencyResolver } from './services/index.js';
|
|
2
3
|
import path from 'node:path';
|
|
3
4
|
import fs from 'node:fs/promises';
|
|
4
5
|
import os from 'node:os';
|
|
@@ -25,7 +26,7 @@ export async function listModels(workspaceRoot: string): Promise<void> {
|
|
|
25
26
|
await manager.initialize(workspaceRoot);
|
|
26
27
|
const lock = await manager.getLockFile();
|
|
27
28
|
if (!lock) {
|
|
28
|
-
console.log('No lock file found. Run `
|
|
29
|
+
console.log('No lock file found. Run `dlang install` to generate dependencies.');
|
|
29
30
|
return;
|
|
30
31
|
}
|
|
31
32
|
console.log('Model dependencies:');
|
|
@@ -53,9 +54,7 @@ export async function addModel(workspaceRoot: string, name: string, source: stri
|
|
|
53
54
|
}
|
|
54
55
|
|
|
55
56
|
// Add dependency
|
|
56
|
-
|
|
57
|
-
manifest.dependencies = {};
|
|
58
|
-
}
|
|
57
|
+
manifest.dependencies ??= {};
|
|
59
58
|
|
|
60
59
|
manifest.dependencies[name] = {
|
|
61
60
|
source,
|
|
@@ -67,7 +66,7 @@ export async function addModel(workspaceRoot: string, name: string, source: stri
|
|
|
67
66
|
await fs.writeFile(manifestPath, yamlContent, 'utf-8');
|
|
68
67
|
|
|
69
68
|
console.log(`Added ${name}: ${source}@${version}`);
|
|
70
|
-
console.log('Run `
|
|
69
|
+
console.log('Run `dlang install` to download dependencies.');
|
|
71
70
|
}
|
|
72
71
|
|
|
73
72
|
export async function removeModel(workspaceRoot: string, name: string): Promise<void> {
|
|
@@ -88,14 +87,14 @@ export async function removeModel(workspaceRoot: string, name: string): Promise<
|
|
|
88
87
|
await fs.writeFile(manifestPath, yamlContent, 'utf-8');
|
|
89
88
|
|
|
90
89
|
console.log(`Removed ${name}`);
|
|
91
|
-
console.log('Run `
|
|
90
|
+
console.log('Run `dlang install` to update lock file.');
|
|
92
91
|
} catch (error) {
|
|
93
92
|
console.error('Failed to remove dependency:', error);
|
|
94
93
|
}
|
|
95
94
|
}
|
|
96
95
|
|
|
97
96
|
export async function statusModels(workspaceRoot: string): Promise<void> {
|
|
98
|
-
const manager = new WorkspaceManager(
|
|
97
|
+
const manager = new WorkspaceManager();
|
|
99
98
|
await manager.initialize(workspaceRoot);
|
|
100
99
|
|
|
101
100
|
const manifestPath = await manager.getManifestPath();
|
|
@@ -125,17 +124,33 @@ export async function statusModels(workspaceRoot: string): Promise<void> {
|
|
|
125
124
|
}
|
|
126
125
|
|
|
127
126
|
if (!lock || Object.keys(lock.dependencies).length === 0) {
|
|
128
|
-
console.log('\nRun `
|
|
127
|
+
console.log('\nRun `dlang install` to lock dependencies.');
|
|
129
128
|
}
|
|
130
129
|
}
|
|
131
130
|
|
|
132
|
-
export async function updateModel(workspaceRoot: string,
|
|
133
|
-
console.log(
|
|
131
|
+
export async function updateModel(workspaceRoot: string, _name?: string): Promise<void> {
|
|
132
|
+
console.log(_name ? `Updating ${_name}...` : 'Updating all dependencies...');
|
|
134
133
|
|
|
135
|
-
//
|
|
134
|
+
// Use CLI services to regenerate the lock file
|
|
136
135
|
const manager = new WorkspaceManager();
|
|
137
136
|
await manager.initialize(workspaceRoot);
|
|
138
|
-
|
|
137
|
+
|
|
138
|
+
const manifest = await manager.getManifest();
|
|
139
|
+
if (!manifest?.dependencies) {
|
|
140
|
+
console.log('No dependencies found in model.yaml');
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Resolve dependencies using CLI services
|
|
145
|
+
const cacheDir = path.join(workspaceRoot, '.dlang', 'packages');
|
|
146
|
+
const gitResolver = new GitUrlResolver(cacheDir);
|
|
147
|
+
const resolver = new DependencyResolver(workspaceRoot, gitResolver);
|
|
148
|
+
const lock = await resolver.resolveDependencies();
|
|
149
|
+
|
|
150
|
+
// Write the lock file
|
|
151
|
+
const lockPath = path.join(workspaceRoot, 'model.lock');
|
|
152
|
+
const lockContent = JSON.stringify(lock, null, 2);
|
|
153
|
+
await fs.writeFile(lockPath, lockContent, 'utf-8');
|
|
139
154
|
|
|
140
155
|
console.log('Dependencies updated and lock file regenerated.');
|
|
141
156
|
}
|
|
@@ -143,7 +158,27 @@ export async function updateModel(workspaceRoot: string, name?: string): Promise
|
|
|
143
158
|
export async function installModels(workspaceRoot: string): Promise<void> {
|
|
144
159
|
const manager = new WorkspaceManager();
|
|
145
160
|
await manager.initialize(workspaceRoot);
|
|
146
|
-
|
|
161
|
+
|
|
162
|
+
const manifest = await manager.getManifest();
|
|
163
|
+
if (!manifest?.dependencies) {
|
|
164
|
+
console.log('No dependencies found in model.yaml');
|
|
165
|
+
return;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Check if lock file exists
|
|
169
|
+
let lock = await manager.getLockFile();
|
|
170
|
+
|
|
171
|
+
if (!lock) {
|
|
172
|
+
// Generate lock file
|
|
173
|
+
const cacheDir = path.join(workspaceRoot, '.dlang', 'packages');
|
|
174
|
+
const gitResolver = new GitUrlResolver(cacheDir);
|
|
175
|
+
const resolver = new DependencyResolver(workspaceRoot, gitResolver);
|
|
176
|
+
lock = await resolver.resolveDependencies();
|
|
177
|
+
|
|
178
|
+
const lockPath = path.join(workspaceRoot, 'model.lock');
|
|
179
|
+
const lockContent = JSON.stringify(lock, null, 2);
|
|
180
|
+
await fs.writeFile(lockPath, lockContent, 'utf-8');
|
|
181
|
+
}
|
|
147
182
|
|
|
148
183
|
const count = Object.keys(lock.dependencies).length;
|
|
149
184
|
console.log(`Dependencies installed: ${count} package(s) locked.`);
|
|
@@ -161,12 +196,12 @@ export async function cacheClear(): Promise<void> {
|
|
|
161
196
|
}
|
|
162
197
|
|
|
163
198
|
export async function showDependencyTree(workspaceRoot: string, options: { commits?: boolean } = {}): Promise<void> {
|
|
164
|
-
const manager = new WorkspaceManager(
|
|
199
|
+
const manager = new WorkspaceManager();
|
|
165
200
|
await manager.initialize(workspaceRoot);
|
|
166
201
|
const lock = await manager.getLockFile();
|
|
167
202
|
|
|
168
203
|
if (!lock || Object.keys(lock.dependencies).length === 0) {
|
|
169
|
-
console.log('No dependencies found. Run `
|
|
204
|
+
console.log('No dependencies found. Run `dlang install` first.');
|
|
170
205
|
return;
|
|
171
206
|
}
|
|
172
207
|
|
|
@@ -183,12 +218,12 @@ export async function showDependencyTree(workspaceRoot: string, options: { commi
|
|
|
183
218
|
}
|
|
184
219
|
|
|
185
220
|
export async function showImpactAnalysis(workspaceRoot: string, packageName: string): Promise<void> {
|
|
186
|
-
const manager = new WorkspaceManager(
|
|
221
|
+
const manager = new WorkspaceManager();
|
|
187
222
|
await manager.initialize(workspaceRoot);
|
|
188
223
|
const lock = await manager.getLockFile();
|
|
189
224
|
|
|
190
225
|
if (!lock) {
|
|
191
|
-
console.log('No lock file found. Run `
|
|
226
|
+
console.log('No lock file found. Run `dlang install` first.');
|
|
192
227
|
return;
|
|
193
228
|
}
|
|
194
229
|
|
|
@@ -208,12 +243,12 @@ export async function showImpactAnalysis(workspaceRoot: string, packageName: str
|
|
|
208
243
|
}
|
|
209
244
|
|
|
210
245
|
export async function validateModel(workspaceRoot: string): Promise<void> {
|
|
211
|
-
const manager = new WorkspaceManager(
|
|
246
|
+
const manager = new WorkspaceManager();
|
|
212
247
|
await manager.initialize(workspaceRoot);
|
|
213
248
|
const lock = await manager.getLockFile();
|
|
214
249
|
|
|
215
250
|
if (!lock) {
|
|
216
|
-
console.log('No lock file found. Run `
|
|
251
|
+
console.log('No lock file found. Run `dlang install` first.');
|
|
217
252
|
return;
|
|
218
253
|
}
|
|
219
254
|
|
|
@@ -233,12 +268,12 @@ export async function validateModel(workspaceRoot: string): Promise<void> {
|
|
|
233
268
|
}
|
|
234
269
|
|
|
235
270
|
export async function auditDependencies(workspaceRoot: string): Promise<void> {
|
|
236
|
-
const manager = new WorkspaceManager(
|
|
271
|
+
const manager = new WorkspaceManager();
|
|
237
272
|
await manager.initialize(workspaceRoot);
|
|
238
273
|
const lock = await manager.getLockFile();
|
|
239
274
|
|
|
240
275
|
if (!lock) {
|
|
241
|
-
console.log('No lock file found. Run `
|
|
276
|
+
console.log('No lock file found. Run `dlang install` first.');
|
|
242
277
|
return;
|
|
243
278
|
}
|
|
244
279
|
|
|
@@ -250,12 +285,12 @@ export async function auditDependencies(workspaceRoot: string): Promise<void> {
|
|
|
250
285
|
}
|
|
251
286
|
|
|
252
287
|
export async function checkCompliance(workspaceRoot: string): Promise<void> {
|
|
253
|
-
const manager = new WorkspaceManager(
|
|
288
|
+
const manager = new WorkspaceManager();
|
|
254
289
|
await manager.initialize(workspaceRoot);
|
|
255
290
|
const lock = await manager.getLockFile();
|
|
256
291
|
|
|
257
292
|
if (!lock) {
|
|
258
|
-
console.log('No lock file found. Run `
|
|
293
|
+
console.log('No lock file found. Run `dlang install` first.');
|
|
259
294
|
return;
|
|
260
295
|
}
|
|
261
296
|
|
package/src/main.ts
CHANGED