@domainlang/language 0.1.20 → 0.1.82
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/out/domain-lang-module.d.ts +0 -2
- package/out/domain-lang-module.js +3 -11
- package/out/domain-lang-module.js.map +1 -1
- package/out/generated/ast.d.ts +19 -8
- package/out/generated/ast.js +10 -1
- package/out/generated/ast.js.map +1 -1
- package/out/generated/grammar.d.ts +1 -1
- package/out/generated/grammar.js +123 -28
- 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 +0 -3
- package/out/index.js +0 -5
- package/out/index.js.map +1 -1
- package/out/lsp/hover/domain-lang-hover.js +4 -0
- package/out/lsp/hover/domain-lang-hover.js.map +1 -1
- package/out/sdk/index.d.ts +1 -1
- package/out/sdk/loader-node.d.ts +3 -7
- package/out/sdk/loader-node.js +9 -24
- package/out/sdk/loader-node.js.map +1 -1
- package/out/sdk/types.d.ts +21 -0
- package/out/services/dependency-analyzer.d.ts +39 -3
- package/out/services/dependency-analyzer.js +47 -22
- package/out/services/dependency-analyzer.js.map +1 -1
- package/out/services/dependency-resolver.d.ts +45 -68
- package/out/services/dependency-resolver.js +43 -243
- package/out/services/dependency-resolver.js.map +1 -1
- package/out/services/git-url-resolver.browser.d.ts +12 -4
- package/out/services/git-url-resolver.browser.js +1 -5
- package/out/services/git-url-resolver.browser.js.map +1 -1
- package/out/services/git-url-resolver.d.ts +56 -22
- package/out/services/git-url-resolver.js +36 -70
- package/out/services/git-url-resolver.js.map +1 -1
- package/out/services/governance-validator.d.ts +37 -1
- package/out/services/governance-validator.js +10 -4
- package/out/services/governance-validator.js.map +1 -1
- package/out/services/import-resolver.d.ts +6 -65
- package/out/services/import-resolver.js +5 -223
- package/out/services/import-resolver.js.map +1 -1
- package/out/services/performance-optimizer.d.ts +1 -1
- package/out/services/workspace-manager.d.ts +10 -57
- package/out/services/workspace-manager.js +21 -187
- 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 +12 -4
- package/out/utils/import-utils.js +135 -35
- package/out/utils/import-utils.js.map +1 -1
- package/out/validation/constants.d.ts +0 -103
- package/out/validation/constants.js +1 -140
- package/out/validation/constants.js.map +1 -1
- package/out/validation/domain.js +1 -46
- package/out/validation/domain.js.map +1 -1
- package/out/validation/import.d.ts +22 -46
- package/out/validation/import.js +85 -187
- package/out/validation/import.js.map +1 -1
- package/out/validation/maps.js +6 -10
- package/out/validation/maps.js.map +1 -1
- package/out/validation/metadata.js +1 -5
- package/out/validation/metadata.js.map +1 -1
- package/package.json +6 -8
- package/src/domain-lang-module.ts +6 -18
- package/src/domain-lang.langium +12 -7
- package/src/generated/ast.ts +20 -7
- package/src/generated/grammar.ts +123 -28
- package/src/generated/module.ts +1 -1
- package/src/index.ts +0 -7
- package/src/lsp/hover/domain-lang-hover.ts +2 -0
- package/src/sdk/index.ts +2 -0
- package/src/sdk/loader-node.ts +9 -29
- package/src/sdk/types.ts +23 -0
- package/src/services/dependency-analyzer.ts +84 -24
- package/src/services/dependency-resolver.ts +84 -301
- package/src/services/git-url-resolver.browser.ts +14 -9
- package/src/services/git-url-resolver.ts +93 -86
- package/src/services/governance-validator.ts +47 -5
- package/src/services/import-resolver.ts +8 -270
- package/src/services/performance-optimizer.ts +1 -1
- package/src/services/workspace-manager.ts +46 -237
- package/src/syntaxes/domain-lang.monarch.ts +1 -1
- package/src/utils/import-utils.ts +160 -38
- package/src/validation/constants.ts +1 -181
- package/src/validation/domain.ts +1 -54
- package/src/validation/import.ts +104 -228
- package/src/validation/maps.ts +6 -10
- package/src/validation/metadata.ts +1 -5
- package/out/lsp/domain-lang-code-actions.d.ts +0 -55
- package/out/lsp/domain-lang-code-actions.js +0 -143
- package/out/lsp/domain-lang-code-actions.js.map +0 -1
- package/out/lsp/domain-lang-workspace-manager.d.ts +0 -21
- package/out/lsp/domain-lang-workspace-manager.js +0 -93
- package/out/lsp/domain-lang-workspace-manager.js.map +0 -1
- package/out/lsp/manifest-diagnostics.d.ts +0 -82
- package/out/lsp/manifest-diagnostics.js +0 -230
- package/out/lsp/manifest-diagnostics.js.map +0 -1
- package/out/services/semver.d.ts +0 -98
- package/out/services/semver.js +0 -195
- package/out/services/semver.js.map +0 -1
- package/out/services/types.d.ts +0 -340
- package/out/services/types.js +0 -46
- package/out/services/types.js.map +0 -1
- package/out/validation/manifest.d.ts +0 -144
- package/out/validation/manifest.js +0 -327
- package/out/validation/manifest.js.map +0 -1
- package/src/lsp/domain-lang-code-actions.ts +0 -189
- package/src/lsp/domain-lang-workspace-manager.ts +0 -104
- package/src/lsp/manifest-diagnostics.ts +0 -290
- package/src/services/semver.ts +0 -213
- package/src/services/types.ts +0 -415
- package/src/validation/manifest.ts +0 -439
|
@@ -13,13 +13,66 @@
|
|
|
13
13
|
import { URI } from 'langium';
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
import fs from 'node:fs/promises';
|
|
16
|
+
import os from 'node:os';
|
|
16
17
|
import { exec } from 'node:child_process';
|
|
17
18
|
import { promisify } from 'node:util';
|
|
18
19
|
import YAML from 'yaml';
|
|
19
|
-
import type { GitImportInfo, ResolvingPackage, LockFile } from './types.js';
|
|
20
20
|
|
|
21
21
|
const execAsync = promisify(exec);
|
|
22
22
|
|
|
23
|
+
/**
|
|
24
|
+
* Parsed git import with repository-level information.
|
|
25
|
+
*/
|
|
26
|
+
export interface GitImportInfo {
|
|
27
|
+
/** Original import string */
|
|
28
|
+
original: string;
|
|
29
|
+
/** Git platform (github, gitlab, bitbucket, or generic) */
|
|
30
|
+
platform: 'github' | 'gitlab' | 'bitbucket' | 'generic';
|
|
31
|
+
/** Repository owner/organization */
|
|
32
|
+
owner: string;
|
|
33
|
+
/** Repository name */
|
|
34
|
+
repo: string;
|
|
35
|
+
/** Version (tag, branch, or commit hash) */
|
|
36
|
+
version: string;
|
|
37
|
+
/** Full git repository URL */
|
|
38
|
+
repoUrl: string;
|
|
39
|
+
/** Package main entry point (from dlang.toml or default index.dlang) */
|
|
40
|
+
entryPoint: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Package metadata from model.yaml
|
|
45
|
+
*/
|
|
46
|
+
export interface PackageMetadata {
|
|
47
|
+
name?: string;
|
|
48
|
+
version?: string;
|
|
49
|
+
main?: string; // Entry point file (legacy field name for compatibility)
|
|
50
|
+
entry?: string; // Entry point file (preferred field name)
|
|
51
|
+
exports?: Record<string, string>;
|
|
52
|
+
dependencies?: Record<string, string>; // name → version constraint
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Lock file format (dlang.lock)
|
|
57
|
+
*
|
|
58
|
+
* Pins exact versions and commit hashes for all dependencies
|
|
59
|
+
* in the dependency tree. Ensures reproducible builds.
|
|
60
|
+
*/
|
|
61
|
+
export interface LockFile {
|
|
62
|
+
version: string; // Lock file format version (currently "1")
|
|
63
|
+
dependencies: Record<string, LockedDependency>; // package name → locked info
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* A single locked dependency with pinned version and commit.
|
|
68
|
+
*/
|
|
69
|
+
export interface LockedDependency {
|
|
70
|
+
version: string; // Resolved semantic version
|
|
71
|
+
resolved: string; // Full git URL
|
|
72
|
+
commit: string; // Exact commit hash (content-addressable)
|
|
73
|
+
integrity?: string; // Optional SHA-256 hash for verification
|
|
74
|
+
}
|
|
75
|
+
|
|
23
76
|
/**
|
|
24
77
|
* Parses import URLs into structured git import information.
|
|
25
78
|
*
|
|
@@ -68,10 +121,7 @@ export class GitUrlParser {
|
|
|
68
121
|
return this.parseFullUrl(importStr);
|
|
69
122
|
}
|
|
70
123
|
|
|
71
|
-
throw new Error(
|
|
72
|
-
`Invalid git import URL: '${importStr}'.\n` +
|
|
73
|
-
`Hint: Use 'owner/repo' or 'owner/repo@version' format (e.g., 'domainlang/core@v1.0.0').`
|
|
74
|
-
);
|
|
124
|
+
throw new Error(`Invalid git import URL: ${importStr}`);
|
|
75
125
|
}
|
|
76
126
|
|
|
77
127
|
/**
|
|
@@ -87,10 +137,7 @@ export class GitUrlParser {
|
|
|
87
137
|
private static parseGitHubShorthand(importStr: string): GitImportInfo {
|
|
88
138
|
const match = importStr.match(/^([a-zA-Z0-9-]+)\/([a-zA-Z0-9-_.]+)(?:@([^/]+))?$/);
|
|
89
139
|
if (!match) {
|
|
90
|
-
throw new Error(
|
|
91
|
-
`Invalid GitHub shorthand format: '${importStr}'.\n` +
|
|
92
|
-
`Hint: Use 'owner/repo' or 'owner/repo@version' format.`
|
|
93
|
-
);
|
|
140
|
+
throw new Error(`Invalid GitHub shorthand format: ${importStr}`);
|
|
94
141
|
}
|
|
95
142
|
|
|
96
143
|
const [, owner, repo, version] = match;
|
|
@@ -103,7 +150,7 @@ export class GitUrlParser {
|
|
|
103
150
|
repo,
|
|
104
151
|
version: resolvedVersion,
|
|
105
152
|
repoUrl: `https://github.com/${owner}/${repo}`,
|
|
106
|
-
entryPoint: 'index.dlang', // Default, will be resolved from
|
|
153
|
+
entryPoint: 'index.dlang', // Default, will be resolved from dlang.toml
|
|
107
154
|
};
|
|
108
155
|
}
|
|
109
156
|
|
|
@@ -184,14 +231,7 @@ export class GitUrlParser {
|
|
|
184
231
|
};
|
|
185
232
|
}
|
|
186
233
|
|
|
187
|
-
throw new Error(
|
|
188
|
-
`Unsupported git URL format: '${importStr}'.\n` +
|
|
189
|
-
`Supported formats:\n` +
|
|
190
|
-
` • owner/repo (GitHub shorthand)\n` +
|
|
191
|
-
` • owner/repo@version\n` +
|
|
192
|
-
` • https://github.com/owner/repo\n` +
|
|
193
|
-
` • https://gitlab.com/owner/repo`
|
|
194
|
-
);
|
|
234
|
+
throw new Error(`Unsupported git URL format: ${importStr}`);
|
|
195
235
|
}
|
|
196
236
|
}
|
|
197
237
|
|
|
@@ -199,25 +239,18 @@ export class GitUrlParser {
|
|
|
199
239
|
* Resolves git repository imports to local entry point files.
|
|
200
240
|
*
|
|
201
241
|
* Implements a content-addressable cache:
|
|
202
|
-
* - Cache location:
|
|
203
|
-
* - Cache key:
|
|
242
|
+
* - Cache location: ~/.dlang/cache/
|
|
243
|
+
* - Cache key: platform/owner/repo/commit-hash
|
|
204
244
|
* - Downloads entire repository on first use
|
|
205
|
-
* - Reads
|
|
245
|
+
* - Reads dlang.toml to find entry point
|
|
206
246
|
* - Returns URI to entry point file
|
|
207
247
|
*/
|
|
208
248
|
export class GitUrlResolver {
|
|
209
249
|
private cacheDir: string;
|
|
210
250
|
private lockFile?: LockFile;
|
|
211
251
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
*
|
|
215
|
-
* @param cacheDir - The cache directory path. Per PRS-010, this should be
|
|
216
|
-
* the project's `.dlang/packages/` directory for isolation
|
|
217
|
-
* and reproducibility (like node_modules).
|
|
218
|
-
*/
|
|
219
|
-
constructor(cacheDir: string) {
|
|
220
|
-
this.cacheDir = cacheDir;
|
|
252
|
+
constructor(cacheDir?: string) {
|
|
253
|
+
this.cacheDir = cacheDir || path.join(os.homedir(), '.dlang', 'cache');
|
|
221
254
|
}
|
|
222
255
|
|
|
223
256
|
/**
|
|
@@ -242,13 +275,13 @@ export class GitUrlResolver {
|
|
|
242
275
|
* 3. Resolve version to commit hash (if not locked)
|
|
243
276
|
* 4. Check cache
|
|
244
277
|
* 5. Download repository if not cached
|
|
245
|
-
* 6. Read
|
|
278
|
+
* 6. Read dlang.toml to find entry point
|
|
246
279
|
* 7. Return URI to entry point file
|
|
247
280
|
*
|
|
248
281
|
* @param importUrl - The git import URL
|
|
249
282
|
* @returns URI to the package's entry point file
|
|
250
283
|
*/
|
|
251
|
-
async resolve(importUrl: string
|
|
284
|
+
async resolve(importUrl: string): Promise<URI> {
|
|
252
285
|
const gitInfo = GitUrlParser.parse(importUrl);
|
|
253
286
|
|
|
254
287
|
// Check lock file for pinned version (handles transitive dependencies)
|
|
@@ -259,15 +292,7 @@ export class GitUrlResolver {
|
|
|
259
292
|
// Use locked commit hash (reproducible build)
|
|
260
293
|
commitHash = this.lockFile.dependencies[packageKey].commit;
|
|
261
294
|
} else {
|
|
262
|
-
//
|
|
263
|
-
if (options.allowNetwork === false) {
|
|
264
|
-
// LSP mode: cannot perform network operations
|
|
265
|
-
throw new Error(
|
|
266
|
-
`Dependency '${packageKey}' not installed.\n` +
|
|
267
|
-
`Hint: Run 'dlang install' to fetch dependencies and generate model.lock.`
|
|
268
|
-
);
|
|
269
|
-
}
|
|
270
|
-
// CLI/dev mode: resolve version via network
|
|
295
|
+
// Resolve version dynamically (development mode or missing lock)
|
|
271
296
|
commitHash = await this.resolveCommit(gitInfo);
|
|
272
297
|
}
|
|
273
298
|
|
|
@@ -275,13 +300,6 @@ export class GitUrlResolver {
|
|
|
275
300
|
const cachedPath = this.getCachePath(gitInfo, commitHash);
|
|
276
301
|
|
|
277
302
|
if (!(await this.existsInCache(cachedPath))) {
|
|
278
|
-
if (options.allowNetwork === false) {
|
|
279
|
-
throw new Error(
|
|
280
|
-
`Dependency '${packageKey}' not installed.\n` +
|
|
281
|
-
`Hint: Run 'dlang install' to fetch dependencies.`
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
|
-
|
|
285
303
|
// Download repository
|
|
286
304
|
await this.downloadRepo(gitInfo, commitHash, cachedPath);
|
|
287
305
|
}
|
|
@@ -293,8 +311,7 @@ export class GitUrlResolver {
|
|
|
293
311
|
// Verify entry point exists
|
|
294
312
|
if (!(await this.existsInCache(entryFile))) {
|
|
295
313
|
throw new Error(
|
|
296
|
-
`Entry point
|
|
297
|
-
`Hint: Ensure the package has an entry point file (default: index.dlang).`
|
|
314
|
+
`Entry point not found: ${entryPoint} in ${gitInfo.repoUrl}@${gitInfo.version}`
|
|
298
315
|
);
|
|
299
316
|
}
|
|
300
317
|
|
|
@@ -311,7 +328,8 @@ export class GitUrlResolver {
|
|
|
311
328
|
try {
|
|
312
329
|
const yamlContent = await fs.readFile(yamlPath, 'utf-8');
|
|
313
330
|
const metadata = this.parseYaml(yamlContent);
|
|
314
|
-
|
|
331
|
+
// Prefer 'entry' field, fallback to 'main' for backward compatibility
|
|
332
|
+
return metadata.entry || metadata.main || 'index.dlang';
|
|
315
333
|
} catch {
|
|
316
334
|
// No model.yaml or parse error, use default
|
|
317
335
|
return 'index.dlang';
|
|
@@ -325,17 +343,19 @@ export class GitUrlResolver {
|
|
|
325
343
|
* model:
|
|
326
344
|
* entry: index.dlang
|
|
327
345
|
*/
|
|
328
|
-
private parseYaml(content: string):
|
|
346
|
+
private parseYaml(content: string): PackageMetadata {
|
|
329
347
|
const parsed = YAML.parse(content) as {
|
|
330
348
|
model?: {
|
|
331
349
|
name?: string;
|
|
332
350
|
version?: string;
|
|
333
351
|
entry?: string;
|
|
352
|
+
main?: string;
|
|
334
353
|
};
|
|
335
354
|
};
|
|
336
355
|
|
|
337
356
|
return {
|
|
338
357
|
entry: parsed.model?.entry,
|
|
358
|
+
main: parsed.model?.main,
|
|
339
359
|
name: parsed.model?.name,
|
|
340
360
|
version: parsed.model?.version,
|
|
341
361
|
};
|
|
@@ -361,15 +381,10 @@ export class GitUrlResolver {
|
|
|
361
381
|
return gitInfo.version;
|
|
362
382
|
}
|
|
363
383
|
|
|
364
|
-
throw new Error(
|
|
365
|
-
`Could not resolve version '${gitInfo.version}' for ${gitInfo.repoUrl}.\n` +
|
|
366
|
-
`Hint: Check that the version (tag, branch, or commit) exists in the repository.`
|
|
367
|
-
);
|
|
384
|
+
throw new Error(`Could not resolve version: ${gitInfo.version}`);
|
|
368
385
|
} catch (error) {
|
|
369
386
|
throw new Error(
|
|
370
|
-
`Failed to resolve git version
|
|
371
|
-
`Error: ${error}\n` +
|
|
372
|
-
`Hint: Verify the repository URL is correct and accessible.`
|
|
387
|
+
`Failed to resolve git version ${gitInfo.version} for ${gitInfo.repoUrl}: ${error}`
|
|
373
388
|
);
|
|
374
389
|
}
|
|
375
390
|
}
|
|
@@ -377,14 +392,12 @@ export class GitUrlResolver {
|
|
|
377
392
|
/**
|
|
378
393
|
* Gets the local cache path for a git repository.
|
|
379
394
|
*
|
|
380
|
-
* Format:
|
|
381
|
-
*
|
|
382
|
-
* Per PRS-010: Project-local cache structure mirrors the Design Considerations
|
|
383
|
-
* section showing `.dlang/packages/{owner}/{repo}/{version}/` layout.
|
|
395
|
+
* Format: ~/.dlang/cache/{platform}/{owner}/{repo}/{commit-hash}/
|
|
384
396
|
*/
|
|
385
397
|
private getCachePath(gitInfo: GitImportInfo, commitHash: string): string {
|
|
386
398
|
return path.join(
|
|
387
399
|
this.cacheDir,
|
|
400
|
+
gitInfo.platform,
|
|
388
401
|
gitInfo.owner,
|
|
389
402
|
gitInfo.repo,
|
|
390
403
|
commitHash
|
|
@@ -435,9 +448,7 @@ export class GitUrlResolver {
|
|
|
435
448
|
await fs.rm(targetDir, { recursive: true, force: true });
|
|
436
449
|
const message = error instanceof Error ? error.message : String(error);
|
|
437
450
|
throw new Error(
|
|
438
|
-
`Failed to download
|
|
439
|
-
`Error: ${message}\n` +
|
|
440
|
-
`Hint: Check your network connection and verify the repository URL is correct.`
|
|
451
|
+
`Failed to download git repository ${gitInfo.repoUrl}@${gitInfo.version}: ${message}`
|
|
441
452
|
);
|
|
442
453
|
}
|
|
443
454
|
}
|
|
@@ -451,8 +462,6 @@ export class GitUrlResolver {
|
|
|
451
462
|
|
|
452
463
|
/**
|
|
453
464
|
* Gets cache statistics (size, number of cached repos, etc.).
|
|
454
|
-
*
|
|
455
|
-
* Cache structure: .dlang/packages/{owner}/{repo}/{version}/
|
|
456
465
|
*/
|
|
457
466
|
async getCacheStats(): Promise<{
|
|
458
467
|
totalSize: number;
|
|
@@ -463,24 +472,22 @@ export class GitUrlResolver {
|
|
|
463
472
|
let repoCount = 0;
|
|
464
473
|
|
|
465
474
|
try {
|
|
466
|
-
const
|
|
467
|
-
for (const
|
|
468
|
-
const
|
|
469
|
-
const
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
const versionPath = path.join(repoPath, version);
|
|
483
|
-
totalSize += await this.getDirectorySize(versionPath);
|
|
475
|
+
const platforms = await fs.readdir(this.cacheDir);
|
|
476
|
+
for (const platform of platforms) {
|
|
477
|
+
const platformPath = path.join(this.cacheDir, platform);
|
|
478
|
+
const owners = await fs.readdir(platformPath);
|
|
479
|
+
for (const owner of owners) {
|
|
480
|
+
const ownerPath = path.join(platformPath, owner);
|
|
481
|
+
const repos = await fs.readdir(ownerPath);
|
|
482
|
+
for (const repo of repos) {
|
|
483
|
+
const repoPath = path.join(ownerPath, repo);
|
|
484
|
+
const commits = await fs.readdir(repoPath);
|
|
485
|
+
repoCount += commits.length;
|
|
486
|
+
|
|
487
|
+
for (const commit of commits) {
|
|
488
|
+
const commitPath = path.join(repoPath, commit);
|
|
489
|
+
totalSize += await this.getDirectorySize(commitPath);
|
|
490
|
+
}
|
|
484
491
|
}
|
|
485
492
|
}
|
|
486
493
|
}
|
|
@@ -19,11 +19,45 @@
|
|
|
19
19
|
* ```
|
|
20
20
|
*/
|
|
21
21
|
|
|
22
|
-
import type { LockFile
|
|
22
|
+
import type { LockFile } from './git-url-resolver.js';
|
|
23
23
|
import path from 'node:path';
|
|
24
24
|
import fs from 'node:fs/promises';
|
|
25
25
|
import YAML from 'yaml';
|
|
26
|
-
|
|
26
|
+
|
|
27
|
+
export interface GovernancePolicy {
|
|
28
|
+
/** Allowed git domains (e.g., ['github.com/acme']) */
|
|
29
|
+
allowedSources?: string[];
|
|
30
|
+
/** Blocked packages or patterns */
|
|
31
|
+
blockedPackages?: string[];
|
|
32
|
+
/** Require stable versions only (no pre-release) */
|
|
33
|
+
requireStableVersions?: boolean;
|
|
34
|
+
/** Require team ownership metadata */
|
|
35
|
+
requireTeamOwnership?: boolean;
|
|
36
|
+
/** Allowed licenses */
|
|
37
|
+
allowedLicenses?: string[];
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface GovernanceMetadata {
|
|
41
|
+
/** Team responsible for the model */
|
|
42
|
+
team?: string;
|
|
43
|
+
/** Contact email */
|
|
44
|
+
contact?: string;
|
|
45
|
+
/** Business domain */
|
|
46
|
+
domain?: string;
|
|
47
|
+
/** Compliance tags */
|
|
48
|
+
compliance?: string[];
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface GovernanceViolation {
|
|
52
|
+
/** Type of violation */
|
|
53
|
+
type: 'blocked-source' | 'unstable-version' | 'missing-metadata' | 'license-violation';
|
|
54
|
+
/** Package that violates the policy */
|
|
55
|
+
packageKey: string;
|
|
56
|
+
/** Violation message */
|
|
57
|
+
message: string;
|
|
58
|
+
/** Severity: error or warning */
|
|
59
|
+
severity: 'error' | 'warning';
|
|
60
|
+
}
|
|
27
61
|
|
|
28
62
|
/**
|
|
29
63
|
* Validates dependencies against organizational governance policies.
|
|
@@ -73,11 +107,11 @@ export class GovernanceValidator {
|
|
|
73
107
|
|
|
74
108
|
// Check version stability
|
|
75
109
|
if (this.policy.requireStableVersions) {
|
|
76
|
-
if (
|
|
110
|
+
if (this.isPreReleaseVersion(locked.version)) {
|
|
77
111
|
violations.push({
|
|
78
112
|
type: 'unstable-version',
|
|
79
113
|
packageKey,
|
|
80
|
-
message: `Pre-release
|
|
114
|
+
message: `Pre-release version not allowed: ${locked.version}`,
|
|
81
115
|
severity: 'error',
|
|
82
116
|
});
|
|
83
117
|
}
|
|
@@ -136,7 +170,7 @@ export class GovernanceValidator {
|
|
|
136
170
|
lines.push('Dependencies:');
|
|
137
171
|
|
|
138
172
|
for (const [packageKey, locked] of Object.entries(lockFile.dependencies)) {
|
|
139
|
-
lines.push(` - ${packageKey}@${locked.
|
|
173
|
+
lines.push(` - ${packageKey}@${locked.version}`);
|
|
140
174
|
lines.push(` Source: ${locked.resolved}`);
|
|
141
175
|
lines.push(` Commit: ${locked.commit}`);
|
|
142
176
|
}
|
|
@@ -154,6 +188,14 @@ export class GovernanceValidator {
|
|
|
154
188
|
|
|
155
189
|
return lines.join('\n');
|
|
156
190
|
}
|
|
191
|
+
|
|
192
|
+
/**
|
|
193
|
+
* Checks if a version is a pre-release.
|
|
194
|
+
*/
|
|
195
|
+
private isPreReleaseVersion(version: string): boolean {
|
|
196
|
+
const clean = version.replace(/^v/, '');
|
|
197
|
+
return /-(alpha|beta|rc|pre|dev|snapshot)/.test(clean);
|
|
198
|
+
}
|
|
157
199
|
}
|
|
158
200
|
|
|
159
201
|
/**
|