@nesso-how/vocab-learning 0.1.0-alpha.41 → 0.2.0-beta.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 +12 -1
- package/dist/document.d.ts +22 -2
- package/dist/document.js +82 -17
- package/dist/index.d.ts +2 -8
- package/dist/index.js +2 -8
- package/dist/vocabularyIdentity.d.ts +7 -0
- package/dist/vocabularyIdentity.js +11 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -37,8 +37,9 @@ const freshNode = defaultConceptReviewFields()
|
|
|
37
37
|
import { deserialize, serialize, type NessoGraphDocument } from '@nesso-how/vocab-learning'
|
|
38
38
|
|
|
39
39
|
const json = serialize({
|
|
40
|
+
vocabulary: { id: '@nesso-how/vocab-learning', version: '0.1.0' },
|
|
40
41
|
name: 'My graph',
|
|
41
|
-
concepts: [{ id: 'n1', label: 'Idea', x: 0, y: 0, data: { elaboration: { ... } } }],
|
|
42
|
+
concepts: [{ id: 'n1', label: 'Idea', x: 0, y: 0, data: { elaboration: { definition: '...' } } }],
|
|
42
43
|
relations: [{ id: 'e1', source: 'n1', target: 'n2', type: 'causes' }],
|
|
43
44
|
})
|
|
44
45
|
const doc: NessoGraphDocument = deserialize(json)
|
|
@@ -48,6 +49,16 @@ const doc: NessoGraphDocument = deserialize(json)
|
|
|
48
49
|
|
|
49
50
|
Relation types reference: [Relation types](https://nesso.how/docs/reference/relation-types/).
|
|
50
51
|
|
|
52
|
+
## Persisted vocabulary compatibility
|
|
53
|
+
|
|
54
|
+
Learning-vocabulary documents must declare
|
|
55
|
+
`@nesso-how/vocab-learning` and a supported normative vocabulary version.
|
|
56
|
+
The first protected baseline is vocabulary `0.1.0` with definition-only
|
|
57
|
+
concept elaboration.
|
|
58
|
+
|
|
59
|
+
Removed alpha-only `examples`, `notes`, and image fields are not migrated or
|
|
60
|
+
discarded. Documents containing them are rejected.
|
|
61
|
+
|
|
51
62
|
## License
|
|
52
63
|
|
|
53
64
|
MIT
|
package/dist/document.d.ts
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
import type { NessoGraphDocument, NessoGraphDocumentInput } from './graphDocument.js';
|
|
2
|
-
/**
|
|
2
|
+
/**
|
|
3
|
+
* Strict post-migration document shape validation.
|
|
4
|
+
* Rejects: missing/foreign vocabulary, newer vocabulary versions, non-current
|
|
5
|
+
* vocabulary versions (older versions should be migrated before calling this),
|
|
6
|
+
* extra elaboration keys, and unknown relation types.
|
|
7
|
+
*/
|
|
8
|
+
export declare function validateNessoDocument<M extends Record<string, unknown>>(doc: NessoGraphDocument<M>): NessoGraphDocument<M>;
|
|
9
|
+
/**
|
|
10
|
+
* Parse a Nesso graph document envelope without vocabulary-level validation.
|
|
11
|
+
* Validates JSON structure and schema format only; vocabulary identity, version,
|
|
12
|
+
* elaboration shape, and relation types are NOT checked. Callers must run
|
|
13
|
+
* {@link validateNessoDocument} (or equivalent checks) before the document
|
|
14
|
+
* reaches the store.
|
|
15
|
+
*/
|
|
16
|
+
export declare function deserializeEnvelope<M extends Record<string, unknown> = Record<string, unknown>>(json: string): NessoGraphDocument<M>;
|
|
17
|
+
/** Serialize a Nesso Learning Vocabulary graph document to JSON. Always injects the current vocabulary metadata. */
|
|
3
18
|
export declare function serialize<M extends Record<string, unknown>>(doc: NessoGraphDocumentInput<M>): string;
|
|
4
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* Parse and strictly validate a Nesso Learning Vocabulary graph document.
|
|
21
|
+
* This is the convenience entry point that does envelope parsing + full
|
|
22
|
+
* validation. Use {@link deserializeEnvelope} + manual checks when vocabulary
|
|
23
|
+
* migration must run between parsing and validation.
|
|
24
|
+
*/
|
|
5
25
|
export declare function deserialize<M extends Record<string, unknown> = Record<string, unknown>>(json: string): NessoGraphDocument<M>;
|
package/dist/document.js
CHANGED
|
@@ -4,40 +4,105 @@
|
|
|
4
4
|
// and adds validation (elaboration shape, known `relation.type` ids).
|
|
5
5
|
import { deserialize as deserializeSchema, serialize as serializeSchema } from '@nesso-how/schema';
|
|
6
6
|
import { RELATION_TYPES } from './relationTypes.js';
|
|
7
|
+
import { VOCABULARY } from './vocabularyIdentity.js';
|
|
7
8
|
const VALID_RELATION_TYPES = new Set(Object.keys(RELATION_TYPES));
|
|
8
9
|
function asRecord(value) {
|
|
9
10
|
return typeof value === 'object' && value !== null ? value : null;
|
|
10
11
|
}
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
/** Compare two semver strings. Returns positive if a > b, negative if a < b, 0 if equal. */
|
|
13
|
+
function compareVersions(a, b) {
|
|
14
|
+
const pa = a.split('.').map(Number);
|
|
15
|
+
const pb = b.split('.').map(Number);
|
|
16
|
+
for (let i = 0; i < 3; i++) {
|
|
17
|
+
const na = pa[i] ?? 0;
|
|
18
|
+
const nb = pb[i] ?? 0;
|
|
19
|
+
if (Number.isNaN(na) || Number.isNaN(nb))
|
|
20
|
+
return 0;
|
|
21
|
+
if (na > nb)
|
|
22
|
+
return 1;
|
|
23
|
+
if (na < nb)
|
|
24
|
+
return -1;
|
|
25
|
+
}
|
|
26
|
+
return 0;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Validate vocabulary identity: ensures a vocabulary is declared, its id matches
|
|
30
|
+
* the learning vocabulary, and its version is not newer than current (forward guard).
|
|
31
|
+
* Older versions pass through so the normalizer can migrate them.
|
|
32
|
+
*/
|
|
33
|
+
function validateVocabularyIdentity(vocabulary) {
|
|
34
|
+
if (vocabulary === undefined) {
|
|
35
|
+
throw new Error('Graph document must declare a vocabulary');
|
|
15
36
|
}
|
|
16
|
-
if (
|
|
17
|
-
throw new Error(`
|
|
37
|
+
if (vocabulary.id !== VOCABULARY.id) {
|
|
38
|
+
throw new Error(`Unsupported graph vocabulary: ${vocabulary.id}`);
|
|
39
|
+
}
|
|
40
|
+
// Forward guard: reject documents from a newer vocabulary version.
|
|
41
|
+
if (compareVersions(vocabulary.version, VOCABULARY.version) > 0) {
|
|
42
|
+
throw new Error(`Unsupported learning vocabulary version: ${vocabulary.version}`);
|
|
18
43
|
}
|
|
19
44
|
}
|
|
20
|
-
function
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
45
|
+
function validateElaboration(value) {
|
|
46
|
+
const elab = asRecord(value);
|
|
47
|
+
if (!elab ||
|
|
48
|
+
typeof elab.definition !== 'string' ||
|
|
49
|
+
Object.keys(elab).length !== 1 ||
|
|
50
|
+
!Object.hasOwn(elab, 'definition')) {
|
|
51
|
+
throw new Error('Concept elaboration must contain only definition');
|
|
26
52
|
}
|
|
53
|
+
}
|
|
54
|
+
function validateRelations(doc) {
|
|
27
55
|
for (let i = 0; i < doc.relations.length; i++) {
|
|
28
56
|
const rel = doc.relations[i];
|
|
29
57
|
if (rel.type !== undefined && !VALID_RELATION_TYPES.has(rel.type)) {
|
|
30
58
|
throw new Error(`Invalid Nesso graph document: unknown relation type "${rel.type}" at relations[${i}]`);
|
|
31
59
|
}
|
|
32
60
|
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* Strict post-migration document shape validation.
|
|
64
|
+
* Rejects: missing/foreign vocabulary, newer vocabulary versions, non-current
|
|
65
|
+
* vocabulary versions (older versions should be migrated before calling this),
|
|
66
|
+
* extra elaboration keys, and unknown relation types.
|
|
67
|
+
*/
|
|
68
|
+
export function validateNessoDocument(doc) {
|
|
69
|
+
validateVocabularyIdentity(doc.vocabulary);
|
|
70
|
+
// After migration the version must match exactly.
|
|
71
|
+
if (doc.vocabulary.version !== VOCABULARY.version) {
|
|
72
|
+
throw new Error(`Unsupported learning vocabulary version: ${doc.vocabulary.version}`);
|
|
73
|
+
}
|
|
74
|
+
for (let i = 0; i < doc.concepts.length; i++) {
|
|
75
|
+
const data = doc.concepts[i].data;
|
|
76
|
+
if (data?.elaboration !== undefined) {
|
|
77
|
+
validateElaboration(data.elaboration);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
validateRelations(doc);
|
|
33
81
|
return doc;
|
|
34
82
|
}
|
|
35
|
-
/**
|
|
83
|
+
/**
|
|
84
|
+
* Parse a Nesso graph document envelope without vocabulary-level validation.
|
|
85
|
+
* Validates JSON structure and schema format only; vocabulary identity, version,
|
|
86
|
+
* elaboration shape, and relation types are NOT checked. Callers must run
|
|
87
|
+
* {@link validateNessoDocument} (or equivalent checks) before the document
|
|
88
|
+
* reaches the store.
|
|
89
|
+
*/
|
|
90
|
+
export function deserializeEnvelope(json) {
|
|
91
|
+
return deserializeSchema(json);
|
|
92
|
+
}
|
|
93
|
+
/** Serialize a Nesso Learning Vocabulary graph document to JSON. Always injects the current vocabulary metadata. */
|
|
36
94
|
export function serialize(doc) {
|
|
37
|
-
return serializeSchema(
|
|
95
|
+
return serializeSchema({
|
|
96
|
+
...doc,
|
|
97
|
+
vocabulary: VOCABULARY,
|
|
98
|
+
});
|
|
38
99
|
}
|
|
39
|
-
/**
|
|
100
|
+
/**
|
|
101
|
+
* Parse and strictly validate a Nesso Learning Vocabulary graph document.
|
|
102
|
+
* This is the convenience entry point that does envelope parsing + full
|
|
103
|
+
* validation. Use {@link deserializeEnvelope} + manual checks when vocabulary
|
|
104
|
+
* migration must run between parsing and validation.
|
|
105
|
+
*/
|
|
40
106
|
export function deserialize(json) {
|
|
41
|
-
|
|
42
|
-
return validateNessoDocument(doc);
|
|
107
|
+
return validateNessoDocument(deserializeEnvelope(json));
|
|
43
108
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,12 +1,6 @@
|
|
|
1
1
|
export type { ConceptElaboration, NessoConceptData, NessoRelationData, NessoGraphDocument, NessoGraphDocumentInput, } from './graphDocument.js';
|
|
2
|
-
|
|
3
|
-
export declare const VOCABULARY: {
|
|
4
|
-
readonly id: "@nesso-how/vocab-learning";
|
|
5
|
-
readonly name: "Nesso Learning Vocabulary";
|
|
6
|
-
readonly domain: "learning";
|
|
7
|
-
readonly version: "0.1.0";
|
|
8
|
-
};
|
|
2
|
+
export { VOCABULARY } from './vocabularyIdentity.js';
|
|
9
3
|
export { defaultConceptReviewFields, type ConceptNodeData, type LearningNodeParams, } from './nodeParams.js';
|
|
10
4
|
export { RELATION_CATEGORIES, RELATION_TYPES, RELATION_TYPE_VALUES, isPrimaryRelationType, type Cardinality, type GlyphKind, type Polarity, type RelationCategory, type RelationTypeDef, type RelationTypeName, type Transitivity, } from './relationTypes.js';
|
|
11
5
|
export { CategoryPalette, GLYPH_PATHS, PALETTES } from './visual.js';
|
|
12
|
-
export { deserialize, serialize } from './document.js';
|
|
6
|
+
export { deserialize, deserializeEnvelope, serialize, validateNessoDocument } from './document.js';
|
package/dist/index.js
CHANGED
|
@@ -2,14 +2,8 @@
|
|
|
2
2
|
//
|
|
3
3
|
// Public entry point for `@nesso-how/vocab-learning`. Re-exports the split modules
|
|
4
4
|
// below; import from here unless you need a specific submodule in-package.
|
|
5
|
-
|
|
6
|
-
export const VOCABULARY = {
|
|
7
|
-
id: '@nesso-how/vocab-learning',
|
|
8
|
-
name: 'Nesso Learning Vocabulary',
|
|
9
|
-
domain: 'learning',
|
|
10
|
-
version: '0.1.0',
|
|
11
|
-
};
|
|
5
|
+
export { VOCABULARY } from './vocabularyIdentity.js';
|
|
12
6
|
export { defaultConceptReviewFields, } from './nodeParams.js';
|
|
13
7
|
export { RELATION_CATEGORIES, RELATION_TYPES, RELATION_TYPE_VALUES, isPrimaryRelationType, } from './relationTypes.js';
|
|
14
8
|
export { GLYPH_PATHS, PALETTES } from './visual.js';
|
|
15
|
-
export { deserialize, serialize } from './document.js';
|
|
9
|
+
export { deserialize, deserializeEnvelope, serialize, validateNessoDocument } from './document.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** OKG vocabulary identity — version bumps only on normative vocabulary changes, not npm releases. */
|
|
2
|
+
export declare const VOCABULARY: {
|
|
3
|
+
readonly id: "@nesso-how/vocab-learning";
|
|
4
|
+
readonly name: "Nesso Learning Vocabulary";
|
|
5
|
+
readonly domain: "learning";
|
|
6
|
+
readonly version: "0.1.0";
|
|
7
|
+
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
//
|
|
3
|
+
// Vocabulary identity constant shared between document validation and the public API.
|
|
4
|
+
// Extracted to avoid a circular dependency: both index.ts and document.ts import it.
|
|
5
|
+
/** OKG vocabulary identity — version bumps only on normative vocabulary changes, not npm releases. */
|
|
6
|
+
export const VOCABULARY = {
|
|
7
|
+
id: '@nesso-how/vocab-learning',
|
|
8
|
+
name: 'Nesso Learning Vocabulary',
|
|
9
|
+
domain: 'learning',
|
|
10
|
+
version: '0.1.0',
|
|
11
|
+
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nesso-how/vocab-learning",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0-beta.0",
|
|
4
4
|
"description": "Nesso Learning Vocabulary — graph vocabulary (relation types, node params, palettes) shared across app and MCP",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
}
|
|
23
23
|
},
|
|
24
24
|
"dependencies": {
|
|
25
|
-
"@nesso-how/schema": "0.
|
|
25
|
+
"@nesso-how/schema": "0.2.0-beta.0"
|
|
26
26
|
},
|
|
27
27
|
"devDependencies": {
|
|
28
28
|
"typescript": "~5.8.3"
|