glossarist 0.4.42 → 0.4.44
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 +1 -1
- package/src/{compiled-format.js → compiled-format.ts} +1 -0
- package/src/{concept-collection.js → concept-collection.ts} +1 -0
- package/src/{concept-diff.js → concept-diff.ts} +1 -0
- package/src/{concept-parser.js → concept-parser.ts} +1 -0
- package/src/{concept-reader.js → concept-reader.ts} +1 -0
- package/src/{concept-serializer.js → concept-serializer.ts} +1 -0
- package/src/{concept-writer.js → concept-writer.ts} +1 -0
- package/src/{dataset-asset.js → dataset-asset.ts} +1 -0
- package/src/diff/change.ts +175 -0
- package/src/diff/{collection-diff.js → collection-diff.ts} +1 -0
- package/src/diff/{concept-diff.js → concept-diff.ts} +1 -0
- package/src/diff/{diff-patch.js → diff-patch.ts} +1 -0
- package/src/diff/{diff-renderer.js → diff-renderer.ts} +1 -0
- package/src/diff/{index.js → index.ts} +1 -0
- package/src/diff/list-diff.ts +231 -0
- package/src/{entity-directory.js → entity-directory.ts} +1 -0
- package/src/errors.ts +24 -0
- package/src/{gcr-reader.js → gcr-reader.ts} +1 -0
- package/src/{gcr-writer.js → gcr-writer.ts} +1 -0
- package/src/{index.js → index.ts} +1 -0
- package/src/{managed-concept-collection.js → managed-concept-collection.ts} +1 -0
- package/src/migration/hyperedge-migrator.ts +104 -0
- package/src/models/concept.ts +1 -1
- package/src/rdf/{agents-emitter.js → agents-emitter.ts} +1 -0
- package/src/rdf/{bibliography-emitter.js → bibliography-emitter.ts} +1 -0
- package/src/rdf/{bnode-id.js → bnode-id.ts} +1 -0
- package/src/rdf/{build-activity-emitter.js → build-activity-emitter.ts} +1 -0
- package/src/rdf/{curie.js → curie.ts} +1 -0
- package/src/rdf/{dataset-emitter.js → dataset-emitter.ts} +1 -0
- package/src/rdf/{deterministic-id.js → deterministic-id.ts} +1 -0
- package/src/rdf/{document-writer.js → document-writer.ts} +1 -0
- package/src/rdf/{gloss-concept.js → gloss-concept.ts} +1 -0
- package/src/rdf/{gloss-designation.js → gloss-designation.ts} +1 -0
- package/src/rdf/{gloss-detailed-definition.js → gloss-detailed-definition.ts} +1 -0
- package/src/rdf/{gloss-generic-hyperedge.js → gloss-generic-hyperedge.ts} +1 -0
- package/src/rdf/{gloss-localized-concept.js → gloss-localized-concept.ts} +1 -0
- package/src/rdf/{gloss-non-verbal-rep.js → gloss-non-verbal-rep.ts} +1 -0
- package/src/rdf/{gloss-partitive-member.js → gloss-partitive-member.ts} +1 -0
- package/src/rdf/{gloss-partitive-relation.js → gloss-partitive-relation.ts} +1 -0
- package/src/rdf/{gloss-source.js → gloss-source.ts} +1 -0
- package/src/rdf/{group-emitter.js → group-emitter.ts} +1 -0
- package/src/rdf/{image-variant-emitter.js → image-variant-emitter.ts} +1 -0
- package/src/rdf/{index.js → index.ts} +1 -0
- package/src/rdf/{normalize-enum.js → normalize-enum.ts} +1 -0
- package/src/rdf/{prefixes.js → prefixes.ts} +1 -0
- package/src/rdf/{provenance-emitter.js → provenance-emitter.ts} +1 -0
- package/src/rdf/{sections-builder.js → sections-builder.ts} +1 -0
- package/src/rdf/{shacl-entry.js → shacl-entry.ts} +1 -0
- package/src/rdf/{shacl.js → shacl.ts} +1 -0
- package/src/rdf/{terms.js → terms.ts} +1 -0
- package/src/rdf/{version-emitter.js → version-emitter.ts} +1 -0
- package/src/rdf/{vocabulary-emitter.js → vocabulary-emitter.ts} +1 -0
- package/src/rdf/{write-turtle-sync.js → write-turtle-sync.ts} +1 -0
- package/src/{reference-mention.js → reference-mention.ts} +1 -0
- package/src/{reference-resolver.js → reference-resolver.ts} +1 -0
- package/src/{render-classification.js → render-classification.ts} +1 -0
- package/src/{sort.js → sort.ts} +1 -4
- package/src/transforms/concept-to-gloss.transform.ts +81 -0
- package/src/{uuid.js → uuid.ts} +11 -7
- package/src/{v1-reader.js → v1-reader.ts} +1 -0
- package/src/validators/{asset-index.js → asset-index.ts} +1 -0
- package/src/validators/{binary-has-part-redundancy-rule.js → binary-has-part-redundancy-rule.ts} +1 -0
- package/src/validators/{concept-validator.js → concept-validator.ts} +1 -0
- package/src/validators/{delimiting-coherence-rule.js → delimiting-coherence-rule.ts} +1 -0
- package/src/validators/{external-concept-shape-rule.js → external-concept-shape-rule.ts} +1 -0
- package/src/validators/{gcr-validator.js → gcr-validator.ts} +1 -0
- package/src/validators/{hyperedge-coherence-rule.js → hyperedge-coherence-rule.ts} +1 -0
- package/src/validators/{index.js → index.ts} +1 -0
- package/src/validators/{partitive-relation-coherence-rule.js → partitive-relation-coherence-rule.ts} +1 -0
- package/src/validators/{ref-keys.js → ref-keys.ts} +1 -0
- package/src/validators/{register-validator.js → register-validator.ts} +1 -0
- package/src/validators/{relationship-type-rule.js → relationship-type-rule.ts} +1 -0
- package/src/validators/{sourced-from-locality-rule.js → sourced-from-locality-rule.ts} +1 -0
- package/src/validators/{v3-rules.js → v3-rules.ts} +1 -0
- package/src/validators/{validation-error.js → validation-error.ts} +1 -0
- package/src/validators/{validation-result.js → validation-result.ts} +1 -0
- package/src/validators/{validation-rule.js → validation-rule.ts} +1 -0
- package/src/diff/change.js +0 -139
- package/src/diff/list-diff.js +0 -227
- package/src/errors.js +0 -42
- package/src/migration/hyperedge-migrator.js +0 -119
- package/src/transforms/concept-to-gloss.transform.js +0 -77
- /package/src/rdf/{predicates.js → predicates.ts} +0 -0
- /package/src/transforms/{index.js → index.ts} +0 -0
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Designation → RDF quads. Mirrors glossarist-ruby's
|
|
2
3
|
// `Rdf::GlossDesignation` + the per-subtype classes (GlossExpression,
|
|
3
4
|
// GlossAbbreviation, etc.). The ontology class for each subtype is
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// DetailedDefinition → RDF quads. Mirrors glossarist-ruby's
|
|
2
3
|
// `Rdf::GlossDetailedDefinition`. Used for definitions, notes, examples,
|
|
3
4
|
// and annotations — they all share the same shape (content + optional
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// ConceptSource → RDF quads. Mirrors glossarist-ruby's
|
|
2
3
|
// `Rdf::GlossConceptSource` + `Rdf::GlossCitation`. Sources are reified
|
|
3
4
|
// resources linked from their parent (concept or localized concept or
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Helpers for normalizing enumeration values that get interpolated into
|
|
2
3
|
// URIs. Source data may contain compound forms ("preferred/admitted") or
|
|
3
4
|
// path-like values that must be reduced to a single local name before
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Re-export prefix map and predicate constants generated from the vendored
|
|
2
3
|
// concept-model JSON-LD context. Downstream code should never duplicate
|
|
3
4
|
// prefix bindings — always import from here.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Node-only SHACL validator entry. Separated from glossarist/rdf so that
|
|
2
3
|
// browser bundles can import RDF emitters/writers without pulling in
|
|
3
4
|
// node:fs/promises, node:path, node:url.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// SHACL validator wrapper. Loads vendored concept-model shapes once and
|
|
2
3
|
// validates any RDFJS Dataset against them. Mirrors the mechanics of
|
|
3
4
|
// glossarist-ruby's `Glossarist::Validation::ShaclValidator`.
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Vocabulary graph emitter — emits SKOS ConceptSchemes for the
|
|
2
3
|
// enumeration IRIs that glossarist emits in instance data
|
|
3
4
|
// (gloss:status/*, gloss:entstatus/*, gloss:norm/*, gloss:srcstatus/*,
|
package/src/{sort.js → sort.ts}
RENAMED
|
@@ -3,11 +3,8 @@ const DIGIT_RE = /^\d+$/;
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* Natural sort comparator for concept IDs like "3.1.1.1", "551-12-39".
|
|
6
|
-
* @param {string} a
|
|
7
|
-
* @param {string} b
|
|
8
|
-
* @returns {number}
|
|
9
6
|
*/
|
|
10
|
-
export function naturalSort(a, b) {
|
|
7
|
+
export function naturalSort(a: string, b: string): number {
|
|
11
8
|
const pa = a.match(NATURAL_SORT_RE) || [];
|
|
12
9
|
const pb = b.match(NATURAL_SORT_RE) || [];
|
|
13
10
|
for (let i = 0; i < Math.max(pa.length, pb.length); i++) {
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
// ConceptToGlossTransform — converts a Concept model into RDF.
|
|
2
|
+
//
|
|
3
|
+
// Usage:
|
|
4
|
+
// const xform = new ConceptToGlossTransform({ registerId: 'iso-6709', uriBase: 'https://example.org' });
|
|
5
|
+
// const ttl = await xform.toTurtle(concept);
|
|
6
|
+
|
|
7
|
+
import { conceptToQuads } from '../rdf/gloss-concept.js';
|
|
8
|
+
import {
|
|
9
|
+
collectQuads,
|
|
10
|
+
writeTurtle,
|
|
11
|
+
writeNTriples,
|
|
12
|
+
writeJsonld,
|
|
13
|
+
} from '../rdf/document-writer.js';
|
|
14
|
+
|
|
15
|
+
type QuadLike = unknown;
|
|
16
|
+
type ConceptLike = { registerId?: string; id?: string | number } & Record<string, unknown>;
|
|
17
|
+
|
|
18
|
+
interface WriterEntry {
|
|
19
|
+
write: (quads: QuadLike[] | QuadLike, transform: ConceptToGlossTransform) => Promise<unknown>;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const WRITERS: Readonly<Record<string, WriterEntry>> = Object.freeze({
|
|
23
|
+
turtle: { write: (quads) => writeTurtle(quads as QuadLike[]) },
|
|
24
|
+
ntriples: { write: (quads) => writeNTriples(quads as QuadLike[]) },
|
|
25
|
+
jsonld: { write: (quads, t) => writeJsonld(quads as QuadLike[], t._jsonldOpts() as never) },
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
export class ConceptToGlossTransform {
|
|
29
|
+
readonly registerId: string | undefined;
|
|
30
|
+
readonly uriBase: string;
|
|
31
|
+
readonly jsonldContext: unknown;
|
|
32
|
+
|
|
33
|
+
constructor(options: { registerId?: string; uriBase?: string; jsonldContext?: unknown } = {}) {
|
|
34
|
+
this.registerId = options.registerId;
|
|
35
|
+
this.uriBase = (options.uriBase ?? '').replace(/\/+$/, '');
|
|
36
|
+
if (!this.uriBase) {
|
|
37
|
+
throw new Error(
|
|
38
|
+
'ConceptToGlossTransform requires options.uriBase — the deployment canonical URI root.',
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
this.jsonldContext = options.jsonldContext;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
toTurtle(target: ConceptLike): Promise<unknown> { return this._serialize(target, 'turtle'); }
|
|
45
|
+
toTurtleAll(targets: Iterable<ConceptLike>): Promise<unknown> { return this._serialize(targets, 'turtle'); }
|
|
46
|
+
toJsonld(target: ConceptLike): Promise<unknown> { return this._serialize(target, 'jsonld'); }
|
|
47
|
+
toJsonldAll(targets: Iterable<ConceptLike>): Promise<unknown> { return this._serialize(targets, 'jsonld'); }
|
|
48
|
+
toNTriples(target: ConceptLike): Promise<unknown> { return this._serialize(target, 'ntriples'); }
|
|
49
|
+
toNTriplesAll(targets: Iterable<ConceptLike>): Promise<unknown> { return this._serialize(targets, 'ntriples'); }
|
|
50
|
+
|
|
51
|
+
async _serialize(target: ConceptLike | Iterable<ConceptLike>, format: string): Promise<unknown> {
|
|
52
|
+
const writer = WRITERS[format];
|
|
53
|
+
if (!writer) throw new Error(`Unknown serialization format: ${format}`);
|
|
54
|
+
const quads = this._collect(target);
|
|
55
|
+
return writer.write(quads, this);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
_collect(target: ConceptLike | Iterable<ConceptLike>): QuadLike[] {
|
|
59
|
+
if (target && typeof (target as Iterable<ConceptLike>)[Symbol.iterator] === 'function') {
|
|
60
|
+
const quads: QuadLike[] = [];
|
|
61
|
+
for (const concept of target as Iterable<ConceptLike>) {
|
|
62
|
+
for (const q of conceptToQuads(concept as never, this._optsFor(concept))) {
|
|
63
|
+
quads.push(q);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return quads;
|
|
67
|
+
}
|
|
68
|
+
return collectQuads(conceptToQuads(target as never, this._optsFor(target as ConceptLike)));
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
_optsFor(concept: ConceptLike): { registerId: string; uriBase: string } {
|
|
72
|
+
return {
|
|
73
|
+
registerId: this.registerId ?? concept.registerId ?? 'glossary',
|
|
74
|
+
uriBase: this.uriBase,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
_jsonldOpts(): { context?: unknown } {
|
|
79
|
+
return this.jsonldContext ? { context: this.jsonldContext } : {};
|
|
80
|
+
}
|
|
81
|
+
}
|
package/src/{uuid.js → uuid.ts}
RENAMED
|
@@ -2,27 +2,31 @@ import { createHash } from 'crypto';
|
|
|
2
2
|
|
|
3
3
|
const NAMESPACE_UUID = '6ba7b810-9dad-11d1-80b4-00c04fd430c8';
|
|
4
4
|
|
|
5
|
-
export function uuidV5(namespace, name) {
|
|
5
|
+
export function uuidV5(namespace: string, name: string): string {
|
|
6
6
|
const ns = _parseUuid(namespace);
|
|
7
7
|
const hash = createHash('sha1').update(ns).update(name, 'utf8').digest();
|
|
8
|
-
hash[6] = (hash[6] & 0x0f) | 0x50;
|
|
9
|
-
hash[8] = (hash[8] & 0x3f) | 0x80;
|
|
8
|
+
hash[6] = ((hash[6] ?? 0) & 0x0f) | 0x50;
|
|
9
|
+
hash[8] = ((hash[8] ?? 0) & 0x3f) | 0x80;
|
|
10
10
|
return _formatUuid(hash);
|
|
11
11
|
}
|
|
12
12
|
|
|
13
|
-
export function conceptUuid(conceptId, namespace = NAMESPACE_UUID) {
|
|
13
|
+
export function conceptUuid(conceptId: string, namespace: string = NAMESPACE_UUID): string {
|
|
14
14
|
return uuidV5(namespace, conceptId);
|
|
15
15
|
}
|
|
16
16
|
|
|
17
|
-
export function localizedConceptUuid(
|
|
17
|
+
export function localizedConceptUuid(
|
|
18
|
+
conceptId: string,
|
|
19
|
+
languageCode: string,
|
|
20
|
+
namespace: string = NAMESPACE_UUID,
|
|
21
|
+
): string {
|
|
18
22
|
return uuidV5(namespace, `${conceptId}:${languageCode}`);
|
|
19
23
|
}
|
|
20
24
|
|
|
21
|
-
function _parseUuid(str) {
|
|
25
|
+
function _parseUuid(str: string): Buffer {
|
|
22
26
|
return Buffer.from(str.replace(/-/g, ''), 'hex');
|
|
23
27
|
}
|
|
24
28
|
|
|
25
|
-
function _formatUuid(hash) {
|
|
29
|
+
function _formatUuid(hash: Buffer): string {
|
|
26
30
|
const h = hash.toString('hex');
|
|
27
31
|
return [h.slice(0, 8), h.slice(8, 12), h.slice(12, 16), h.slice(16, 20), h.slice(20, 32)].join('-');
|
|
28
32
|
}
|
package/src/validators/{binary-has-part-redundancy-rule.js → binary-has-part-redundancy-rule.ts}
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Warns when binary `has_part` / `is_part_of` edges duplicate
|
|
2
3
|
// PartitiveHyperedge members, or when a concept has many binary
|
|
3
4
|
// has_part edges that should be consolidated into a PartitiveHyperedge.
|
package/src/validators/{partitive-relation-coherence-rule.js → partitive-relation-coherence-rule.ts}
RENAMED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Deprecated. This rule has been generalized and renamed to
|
|
2
3
|
// HyperedgeCoherenceRule (see ./hyperedge-coherence-rule.js). The
|
|
3
4
|
// new rule is type-blind — it validates every AbstractHyperedge
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
import { ValidationRule } from './validation-rule.js';
|
|
2
3
|
import { RELATIONSHIP_TYPES } from '../models/related-concept.js';
|
|
3
4
|
import { DESIGNATION_RELATIONSHIP_TYPES } from '../models/designation-relationship.js';
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
// @ts-nocheck — TEMPORARY during TS migration. TODO(Phase 2e): remove and type fully.
|
|
1
2
|
// Validates that every ConceptSource#sourced_from Citation includes a
|
|
2
3
|
// locality. Per concept-model commit 9c065df ("sourced_from citations
|
|
3
4
|
// must include locality"), a sourced_from entry without a locality is
|
package/src/diff/change.js
DELETED
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { GlossaristModel } from '../models/base.js';
|
|
2
|
-
import { TextDiff } from './text-diff.js';
|
|
3
|
-
|
|
4
|
-
export const CHANGE_ADDED = 'added';
|
|
5
|
-
export const CHANGE_REMOVED = 'removed';
|
|
6
|
-
export const CHANGE_CHANGED = 'changed';
|
|
7
|
-
export const CHANGE_MATCHED = 'matched';
|
|
8
|
-
|
|
9
|
-
function serializeValue(v) {
|
|
10
|
-
if (v == null) return null;
|
|
11
|
-
if (v instanceof GlossaristModel) return v.toJSON();
|
|
12
|
-
if (Array.isArray(v)) return v.map(serializeValue);
|
|
13
|
-
if (typeof v === 'object') {
|
|
14
|
-
const out = {};
|
|
15
|
-
for (const [k, val] of Object.entries(v)) out[k] = serializeValue(val);
|
|
16
|
-
return out;
|
|
17
|
-
}
|
|
18
|
-
return v;
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
export class Change extends GlossaristModel {
|
|
22
|
-
constructor(data = {}) {
|
|
23
|
-
super();
|
|
24
|
-
this.path = data.path ?? null;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
get type() {
|
|
28
|
-
throw new Error(`${this.constructor.name} must override type getter`);
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
static fromJSON(data) {
|
|
32
|
-
return deserializeChange(data);
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export class Added extends Change {
|
|
37
|
-
constructor(data = {}) {
|
|
38
|
-
super(data);
|
|
39
|
-
this.value = data.value ?? null;
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
get type() { return CHANGE_ADDED; }
|
|
43
|
-
|
|
44
|
-
toJSON() {
|
|
45
|
-
const obj = { type: CHANGE_ADDED };
|
|
46
|
-
if (this.path != null) obj.path = this.path;
|
|
47
|
-
obj.value = serializeValue(this.value);
|
|
48
|
-
return obj;
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
static fromJSON(data) {
|
|
52
|
-
return new Added(data);
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export class Removed extends Change {
|
|
57
|
-
constructor(data = {}) {
|
|
58
|
-
super(data);
|
|
59
|
-
this.value = data.value ?? null;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
get type() { return CHANGE_REMOVED; }
|
|
63
|
-
|
|
64
|
-
toJSON() {
|
|
65
|
-
const obj = { type: CHANGE_REMOVED };
|
|
66
|
-
if (this.path != null) obj.path = this.path;
|
|
67
|
-
obj.value = serializeValue(this.value);
|
|
68
|
-
return obj;
|
|
69
|
-
}
|
|
70
|
-
|
|
71
|
-
static fromJSON(data) {
|
|
72
|
-
return new Removed(data);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
export class Changed extends Change {
|
|
77
|
-
constructor(data = {}) {
|
|
78
|
-
super(data);
|
|
79
|
-
this.oldValue = data.oldValue ?? data.old_value ?? null;
|
|
80
|
-
this.newValue = data.newValue ?? data.new_value ?? null;
|
|
81
|
-
this._textDiff = data.textDiff ?? (data.text_diff ? TextDiff.fromJSON(data.text_diff) : null);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get type() { return CHANGE_CHANGED; }
|
|
85
|
-
|
|
86
|
-
get textDiff() {
|
|
87
|
-
return this._textDiff;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
toJSON() {
|
|
91
|
-
const obj = { type: CHANGE_CHANGED };
|
|
92
|
-
if (this.path != null) obj.path = this.path;
|
|
93
|
-
obj.old_value = serializeValue(this.oldValue);
|
|
94
|
-
obj.new_value = serializeValue(this.newValue);
|
|
95
|
-
if (this._textDiff) obj.text_diff = this._textDiff.toJSON();
|
|
96
|
-
return obj;
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
static fromJSON(data) {
|
|
100
|
-
return new Changed(data);
|
|
101
|
-
}
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// Matched is for set-membership records that exist in both sides of a
|
|
105
|
-
// comparison but have no directionality — used by ConceptCollectionDiff
|
|
106
|
-
// to track which concepts were paired by id, distinct from those that
|
|
107
|
-
// were genuinely Added or Removed. Distinct from Added because the data
|
|
108
|
-
// has a different semantic meaning; conflating them caused type drift
|
|
109
|
-
// in round 1 (TODO.hyperedges-v2/08).
|
|
110
|
-
export class Matched extends Change {
|
|
111
|
-
constructor(data = {}) {
|
|
112
|
-
super(data);
|
|
113
|
-
this.value = data.value ?? null;
|
|
114
|
-
}
|
|
115
|
-
|
|
116
|
-
get type() { return CHANGE_MATCHED; }
|
|
117
|
-
|
|
118
|
-
toJSON() {
|
|
119
|
-
const obj = { type: CHANGE_MATCHED };
|
|
120
|
-
if (this.path != null) obj.path = this.path;
|
|
121
|
-
obj.value = serializeValue(this.value);
|
|
122
|
-
return obj;
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
static fromJSON(data) {
|
|
126
|
-
return new Matched(data);
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
export function deserializeChange(data) {
|
|
131
|
-
switch (data?.type) {
|
|
132
|
-
case CHANGE_ADDED: return Added.fromJSON(data);
|
|
133
|
-
case CHANGE_REMOVED: return Removed.fromJSON(data);
|
|
134
|
-
case CHANGE_CHANGED: return Changed.fromJSON(data);
|
|
135
|
-
case CHANGE_MATCHED: return Matched.fromJSON(data);
|
|
136
|
-
default:
|
|
137
|
-
throw new Error(`Unknown change type: ${data?.type}`);
|
|
138
|
-
}
|
|
139
|
-
}
|