glossarist 0.2.0 → 0.2.1
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/package.json
CHANGED
|
@@ -37,8 +37,7 @@ export class ConceptCollection {
|
|
|
37
37
|
|
|
38
38
|
byStatus(status) {
|
|
39
39
|
return new ConceptCollection(this[_items].filter(c => {
|
|
40
|
-
|
|
41
|
-
return langs.length > 0 && c.localization(langs[0])?.entryStatus === status;
|
|
40
|
+
return c.languages.some(lang => c.localization(lang)?.entryStatus === status);
|
|
42
41
|
}));
|
|
43
42
|
}
|
|
44
43
|
|
package/src/index.d.ts
CHANGED
|
@@ -26,7 +26,7 @@ export { ConceptCollection } from './concept-collection';
|
|
|
26
26
|
export { ManagedConceptCollection } from './managed-concept-collection';
|
|
27
27
|
|
|
28
28
|
// Validators
|
|
29
|
-
export { validateConcept, validateRegister, createConceptValidator, ValidationError, ValidationRule, RegisterValidator } from './validators/index';
|
|
29
|
+
export { validateConcept, validateRegister, validateGcrPackage, createConceptValidator, ValidationError, ValidationRule, ValidationResult, RegisterValidator, GcrValidator } from './validators/index';
|
|
30
30
|
|
|
31
31
|
// UUID
|
|
32
32
|
export { conceptUuid, localizedConceptUuid, uuidV5 } from './uuid';
|
package/src/index.js
CHANGED
|
@@ -5,7 +5,7 @@ export { writeConcept, writeConcepts } from './concept-writer.js';
|
|
|
5
5
|
export { createGcr, GcrWriter } from './gcr-writer.js';
|
|
6
6
|
export { ConceptCollection } from './concept-collection.js';
|
|
7
7
|
export { ManagedConceptCollection } from './managed-concept-collection.js';
|
|
8
|
-
export { validateConcept, validateRegister, createConceptValidator, ValidationError, ValidationRule, RegisterValidator } from './validators/index.js';
|
|
8
|
+
export { validateConcept, validateRegister, validateGcrPackage, createConceptValidator, ValidationError, ValidationRule, ValidationResult, RegisterValidator, GcrValidator } from './validators/index.js';
|
|
9
9
|
export { conceptUuid, localizedConceptUuid, uuidV5 } from './uuid.js';
|
|
10
10
|
export { ReferenceResolver, Reference, referenceResolver } from './reference-resolver.js';
|
|
11
11
|
export { V1Reader, migrateV1ToV2 } from './v1-reader.js';
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import yaml from 'js-yaml';
|
|
2
|
+
import { DATASET_ASSETS } from '../dataset-asset.js';
|
|
3
|
+
import { ValidationResult } from './validation-result.js';
|
|
4
|
+
|
|
5
|
+
export class GcrValidator {
|
|
6
|
+
async validate(pkg) {
|
|
7
|
+
const result = new ValidationResult();
|
|
8
|
+
await this._validateMetadata(pkg, result);
|
|
9
|
+
await this._validateConcepts(pkg, result);
|
|
10
|
+
await this._validateAssets(pkg, result);
|
|
11
|
+
return result;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
async _validateMetadata(pkg, result) {
|
|
15
|
+
const raw = await pkg._readText('metadata.yaml');
|
|
16
|
+
if (!raw) {
|
|
17
|
+
result.addError('metadata.yaml is missing');
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
let meta;
|
|
22
|
+
try {
|
|
23
|
+
meta = yaml.load(raw);
|
|
24
|
+
} catch (e) {
|
|
25
|
+
result.addError(`metadata.yaml: invalid YAML: ${e.message}`);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (!meta.shortname) result.addError('metadata.yaml missing shortname');
|
|
30
|
+
if (!meta.version) result.addError('metadata.yaml missing version');
|
|
31
|
+
if (meta.concept_count == null) result.addError('metadata.yaml missing concept_count');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async _validateConcepts(pkg, result) {
|
|
35
|
+
const ids = await pkg.conceptIds();
|
|
36
|
+
if (ids.length === 0) {
|
|
37
|
+
result.addError('No concept files found in concepts/');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
async _validateAssets(pkg, result) {
|
|
42
|
+
for (const asset of DATASET_ASSETS) {
|
|
43
|
+
if (asset.type === 'file') {
|
|
44
|
+
await this._validateFileAsset(pkg, asset.path, result);
|
|
45
|
+
} else if (asset.type === 'directory') {
|
|
46
|
+
await this._validateDirectoryAsset(pkg, asset.path, result);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
async _validateFileAsset(pkg, path, result) {
|
|
52
|
+
const raw = await pkg._readText(path);
|
|
53
|
+
if (!raw) return;
|
|
54
|
+
try {
|
|
55
|
+
yaml.load(raw);
|
|
56
|
+
} catch (e) {
|
|
57
|
+
result.addError(`${path}: invalid YAML at line ${e.mark?.line ?? '?'}: ${e.message}`);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
async _validateDirectoryAsset(pkg, dirPath, result) {
|
|
62
|
+
let hasFiles = false;
|
|
63
|
+
let hasEntries = false;
|
|
64
|
+
pkg._zip.forEach((relativePath, entry) => {
|
|
65
|
+
if (relativePath.startsWith(`${dirPath}/`)) {
|
|
66
|
+
hasEntries = true;
|
|
67
|
+
if (!entry.dir) hasFiles = true;
|
|
68
|
+
}
|
|
69
|
+
});
|
|
70
|
+
if (hasEntries && !hasFiles) {
|
|
71
|
+
result.addWarning(`${dirPath}/ directory exists but is empty`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
}
|
package/src/validators/index.js
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
export { ValidationError } from './validation-error.js';
|
|
2
2
|
export { ValidationRule } from './validation-rule.js';
|
|
3
|
+
export { ValidationResult } from './validation-result.js';
|
|
3
4
|
export { ConceptValidator, LanguageCodeRule, DesignationTypeRule, EntryStatusRule } from './concept-validator.js';
|
|
4
5
|
export { RegisterValidator } from './register-validator.js';
|
|
6
|
+
export { GcrValidator } from './gcr-validator.js';
|
|
5
7
|
|
|
6
8
|
import { ConceptValidator, LanguageCodeRule, DesignationTypeRule, EntryStatusRule } from './concept-validator.js';
|
|
7
9
|
import { RegisterValidator } from './register-validator.js';
|
|
10
|
+
import { GcrValidator } from './gcr-validator.js';
|
|
8
11
|
|
|
9
12
|
const _default = new ConceptValidator()
|
|
10
13
|
.addRule(new LanguageCodeRule())
|
|
@@ -22,3 +25,7 @@ export function createConceptValidator() {
|
|
|
22
25
|
export function validateRegister(register) {
|
|
23
26
|
return new RegisterValidator().validate(register);
|
|
24
27
|
}
|
|
28
|
+
|
|
29
|
+
export async function validateGcrPackage(pkg) {
|
|
30
|
+
return new GcrValidator().validate(pkg);
|
|
31
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class ValidationResult {
|
|
2
|
+
constructor() {
|
|
3
|
+
this.errors = [];
|
|
4
|
+
this.warnings = [];
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
get valid() {
|
|
8
|
+
return this.errors.length === 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
addError(message) {
|
|
12
|
+
this.errors.push(message);
|
|
13
|
+
return this;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
addWarning(message) {
|
|
17
|
+
this.warnings.push(message);
|
|
18
|
+
return this;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
merge(other) {
|
|
22
|
+
for (const e of other.errors) this.errors.push(e);
|
|
23
|
+
for (const w of other.warnings) this.warnings.push(w);
|
|
24
|
+
return this;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
toJSON() {
|
|
28
|
+
return {
|
|
29
|
+
valid: this.valid,
|
|
30
|
+
errors: [...this.errors],
|
|
31
|
+
warnings: [...this.warnings],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
}
|