diff --git a/src/plugins/initiatives/initiative.js b/src/plugins/initiatives/initiative.js index 56ead31..38609e0 100644 --- a/src/plugins/initiatives/initiative.js +++ b/src/plugins/initiatives/initiative.js @@ -7,7 +7,7 @@ import {type TimestampMs} from "../../util/timestamp"; import {initiativeNodeType} from "./declaration"; // Composite ID, used as input for NodeAddressT. -export opaque type InitiativeId = string[]; +export opaque type InitiativeId: string[] = string[]; // Enforce that each ID has at least a sub-type and 1..n components. export function createId( diff --git a/src/plugins/initiatives/nodeEntry.js b/src/plugins/initiatives/nodeEntry.js index a620aa0..2430460 100644 --- a/src/plugins/initiatives/nodeEntry.js +++ b/src/plugins/initiatives/nodeEntry.js @@ -2,8 +2,11 @@ import {type URL} from "../../core/references"; import {type NodeWeight} from "../../core/weights"; +import {type NodeAddressT, NodeAddress} from "../../core/graph"; import {type TimestampMs, type TimestampISO} from "../../util/timestamp"; import * as Timestamp from "../../util/timestamp"; +import {type InitiativeId} from "./initiative"; +import {nodeEntryTypes} from "./declaration"; /** * Represents an "inline contribution" node. They're called entries and named @@ -47,6 +50,14 @@ export type NodeEntryJson = $Shape<{ +weight: NodeWeight | null, }>; +export function addressForNodeEntry( + field: NodeEntryField, + id: InitiativeId, + key: string +): NodeAddressT { + return NodeAddress.append(nodeEntryTypes[field].prefix, ...id, key); +} + /** * Takes a NodeEntryJson and normalizes it to a NodeEntry. * diff --git a/src/plugins/initiatives/nodeEntry.test.js b/src/plugins/initiatives/nodeEntry.test.js index 8c969e3..e3bd0ea 100644 --- a/src/plugins/initiatives/nodeEntry.test.js +++ b/src/plugins/initiatives/nodeEntry.test.js @@ -2,14 +2,54 @@ import {type TimestampMs} from "../../util/timestamp"; import * as Timestamp from "../../util/timestamp"; +import {NodeAddress} from "../../core/graph"; +import {createId} from "./initiative"; import { type NodeEntry, type NodeEntryJson, + addressForNodeEntry, normalizeNodeEntry, _titleSlug, } from "./nodeEntry"; describe("plugins/initiatives/nodeEntry", () => { + describe("addressForNodeEntry", () => { + it("should handle each field value as a different node type", () => { + const id = createId("EXAMPLE", "123"); + const addresses = [ + addressForNodeEntry("DEPENDENCY", id, "some-dependency-key"), + addressForNodeEntry("REFERENCE", id, "some-reference-key"), + addressForNodeEntry("CONTRIBUTION", id, "contrib-key"), + ]; + expect(addresses).toEqual([ + NodeAddress.fromParts([ + "sourcecred", + "initiatives", + "DEPENDENCY", + "EXAMPLE", + "123", + "some-dependency-key", + ]), + NodeAddress.fromParts([ + "sourcecred", + "initiatives", + "REFERENCE", + "EXAMPLE", + "123", + "some-reference-key", + ]), + NodeAddress.fromParts([ + "sourcecred", + "initiatives", + "CONTRIBUTION", + "EXAMPLE", + "123", + "contrib-key", + ]), + ]); + }); + }); + describe("normalizeNodeEntry", () => { it("should throw without a title", () => { const timestampMs: TimestampMs = Timestamp.fromNumber(123);