From 673240b37d417d53bcbdc53491ce3f82d9a2c187 Mon Sep 17 00:00:00 2001 From: Kris McGinnes Date: Mon, 23 Feb 2026 18:04:43 -0600 Subject: [PATCH] Add branded types for RDF namespace and prefix identifiers - Add types.ts with IriNamespace, IriLocalValue, IriParts, RdfPrefix, GeneratedPrefix, and NormalizedIriNamespace branded types - Apply branded types to PrefixTypeConfig (prefix, uri fields) - Add branded type casts to existing code and tests - Update steering docs with branded type table and backward compat testing guidance --- .kiro/steering/structure.md | 24 +++--- .kiro/steering/testing.md | 83 +++++++++++++++++++ .../src/core/ConfigurationProvider/types.ts | 5 +- .../core/StateProvider/displayEdge.test.ts | 6 +- .../core/StateProvider/displayVertex.test.ts | 14 ++-- .../src/core/StateProvider/schema.test.ts | 10 ++- .../src/hooks/useTextTransform.test.ts | 6 +- .../src/modules/Namespaces/UserPrefixes.tsx | 7 +- .../src/utils/rdf/generatePrefixes.test.ts | 31 ++++--- .../src/utils/rdf/generatePrefixes.ts | 27 +++--- .../graph-explorer/src/utils/rdf/index.ts | 8 ++ .../src/utils/rdf/replacePrefixes.test.ts | 15 ++-- .../src/utils/rdf/replacePrefixes.ts | 14 ++-- .../graph-explorer/src/utils/rdf/types.ts | 24 ++++++ .../src/utils/saveConfigurationToFile.test.ts | 9 +- .../src/utils/testing/randomData.ts | 6 +- 16 files changed, 223 insertions(+), 66 deletions(-) create mode 100644 packages/graph-explorer/src/utils/rdf/types.ts diff --git a/.kiro/steering/structure.md b/.kiro/steering/structure.md index 64cf6678b..165eac1fe 100644 --- a/.kiro/steering/structure.md +++ b/.kiro/steering/structure.md @@ -118,16 +118,20 @@ complete over time. The project uses branded types from `@/utils` for type safety. These prevent accidental mixing of similar types at compile time. -| Type | Creator Function | Location | -| ------------------ | ---------------------------- | --------------------------------------- | -| `VertexId` | `createVertexId()` | `@/core/entities/vertex` | -| `VertexType` | `createVertexType()` | `@/core/entities/vertex` | -| `EdgeId` | `createEdgeId()` | `@/core/entities/edge` | -| `EdgeType` | `createEdgeType()` | `@/core/entities/edge` | -| `EdgeConnectionId` | `createEdgeConnectionId()` | `@/core/StateProvider/edgeConnectionId` | -| `ConfigurationId` | `createNewConfigurationId()` | `@/core/ConfigurationProvider/types` | -| `RenderedVertexId` | `toRenderedVertexId()` | `@/core/StateProvider/renderedEntities` | -| `RenderedEdgeId` | `toRenderedEdgeId()` | `@/core/StateProvider/renderedEntities` | +| Type | Creator Function | Location | +| ------------------------ | ---------------------------- | --------------------------------------- | +| `VertexId` | `createVertexId()` | `@/core/entities/vertex` | +| `VertexType` | `createVertexType()` | `@/core/entities/vertex` | +| `EdgeId` | `createEdgeId()` | `@/core/entities/edge` | +| `EdgeType` | `createEdgeType()` | `@/core/entities/edge` | +| `EdgeConnectionId` | `createEdgeConnectionId()` | `@/core/StateProvider/edgeConnectionId` | +| `ConfigurationId` | `createNewConfigurationId()` | `@/core/ConfigurationProvider/types` | +| `RenderedVertexId` | `toRenderedVertexId()` | `@/core/StateProvider/renderedEntities` | +| `RenderedEdgeId` | `toRenderedEdgeId()` | `@/core/StateProvider/renderedEntities` | +| `IriNamespace` | `as IriNamespace` | `@/utils/rdf` | +| `IriLocalValue` | `as IriLocalValue` | `@/utils/rdf` | +| `RdfPrefix` | `as RdfPrefix` | `@/utils/rdf` | +| `NormalizedIriNamespace` | `as NormalizedIriNamespace` | `@/utils/rdf` | Always use the appropriate branded type instead of `string` when working with these identifiers. diff --git a/.kiro/steering/testing.md b/.kiro/steering/testing.md index 8f13f63b6..82e5e4aff 100644 --- a/.kiro/steering/testing.md +++ b/.kiro/steering/testing.md @@ -487,3 +487,86 @@ test("should handle errors gracefully", async () => { await expect(functionUnderTest(mockFetch)).rejects.toThrow("Test error"); }); ``` + +## Persistent Storage Backward Compatibility + +Graph Explorer persists state to IndexedDB via localforage (managed through +Jotai atoms). When a type used in persistent storage changes shape — for +example, a property is added, removed, or renamed — previously stored data will +still be loaded with the old shape. This can silently break logic that assumes +the new shape. + +### Requirements + +Any type or object that is persisted through Jotai and localforage **must** have +tests that exercise the old storage shape alongside the new one. These tests +verify that: + +1. Data in the old shape is accepted without errors +2. Logic that consumes the data produces correct results with both shapes +3. Old and new shapes can coexist (e.g., a mix of old and new entries in an + array) + +### Test Structure + +Group backward-compatibility tests in a dedicated `describe` block with a clear +comment block explaining: + +- What the old shape looked like +- Why the tests exist +- A warning not to delete or weaken them without confirming migration + +```typescript +/** + * BACKWARD COMPATIBILITY — PERSISTED DATA + * + * is persisted to IndexedDB via localforage. Older versions stored + * . That property/shape has been changed to + * , but previously persisted data may still contain + * the old form. These tests verify that continues to work correctly + * when given data in the old shape. + * + * DO NOT delete or weaken these tests without confirming that all persisted + * data has been migrated or that the old shape is no longer in the wild. + */ +describe("backward compatibility: ", () => { + it("should handle data in the old shape", () => { + // Use `as TypeName` to bypass compile-time checks and simulate + // the old shape that TypeScript no longer allows. + const legacyData = { + ...currentFields, + removedField: "old value", + } as TypeName; + + const result = functionUnderTest(legacyData); + expect(result).toEqual(expectedOutput); + }); + + it("should handle a mix of old and new shapes", () => { + const legacy = { ...oldShape } as TypeName; + const current = { ...newShape }; + const result = functionUnderTest([legacy, current]); + expect(result).toEqual(expectedOutput); + }); +}); +``` + +### Key Persisted Types + +These types are stored in IndexedDB and require backward-compatibility tests +when modified: + +- `SchemaStorageModel` — vertex/edge configs, prefixes, edge connections +- `PrefixTypeConfig` — RDF namespace prefix definitions +- `VertexTypeConfig` / `EdgeTypeConfig` — schema type configurations +- `RawConfiguration` — connection and schema configuration +- User preferences (`VertexPreferencesStorageModel`, + `EdgePreferencesStorageModel`) + +### When to Add These Tests + +- Removing a property from a persisted type +- Renaming a property on a persisted type +- Changing the type of a property (e.g., `string[]` → `Set`) +- Adding a required property (old data will not have it) +- Changing the semantics of an existing property diff --git a/packages/graph-explorer/src/core/ConfigurationProvider/types.ts b/packages/graph-explorer/src/core/ConfigurationProvider/types.ts index 7bed71c7e..97c705b43 100644 --- a/packages/graph-explorer/src/core/ConfigurationProvider/types.ts +++ b/packages/graph-explorer/src/core/ConfigurationProvider/types.ts @@ -7,6 +7,7 @@ import type { VertexPreferencesStorageModel, } from "@/core/StateProvider/userPreferences"; import type { Branded } from "@/utils"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; import type { EdgeType, VertexType } from "../entities"; import type { SchemaStorageModel } from "../StateProvider"; @@ -85,11 +86,11 @@ export type EdgeTypeConfig = { } & EdgePreferencesStorageModel; export type PrefixTypeConfig = { - prefix: string; + prefix: RdfPrefix; /** * Full URI for the prefix */ - uri: string; + uri: IriNamespace; /** * Internal purpose only. * Mark as true after inferring from the schema. diff --git a/packages/graph-explorer/src/core/StateProvider/displayEdge.test.ts b/packages/graph-explorer/src/core/StateProvider/displayEdge.test.ts index f4328b0dc..6040fafcd 100644 --- a/packages/graph-explorer/src/core/StateProvider/displayEdge.test.ts +++ b/packages/graph-explorer/src/core/StateProvider/displayEdge.test.ts @@ -2,6 +2,8 @@ import type { QueryEngine } from "@shared/types"; import { createRandomDate, createRandomName } from "@shared/utils/testing"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import { getDisplayValueForScalar } from "@/connector/entities"; import { activeConfigurationAtom, @@ -160,8 +162,8 @@ describe("useDisplayEdgeFromEdge", () => { const schema = createRandomSchema(); schema.prefixes = [ { - prefix: "example-class", - uri: "http://www.example.com/class#", + prefix: "example-class" as RdfPrefix, + uri: "http://www.example.com/class#" as IriNamespace, }, ]; diff --git a/packages/graph-explorer/src/core/StateProvider/displayVertex.test.ts b/packages/graph-explorer/src/core/StateProvider/displayVertex.test.ts index a4355c654..c82e1ff54 100644 --- a/packages/graph-explorer/src/core/StateProvider/displayVertex.test.ts +++ b/packages/graph-explorer/src/core/StateProvider/displayVertex.test.ts @@ -2,6 +2,8 @@ import type { QueryEngine } from "@shared/types"; import { createRandomDate, createRandomName } from "@shared/utils/testing"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import { getDisplayValueForScalar } from "@/connector/entities"; import { activeConfigurationAtom, @@ -112,8 +114,8 @@ describe("useDisplayVertexFromVertex", () => { const schema = createRandomSchema(); schema.prefixes = [ { - prefix: "example-class", - uri: "http://www.example.com/class#", + prefix: "example-class" as RdfPrefix, + uri: "http://www.example.com/class#" as IriNamespace, }, ]; @@ -186,12 +188,12 @@ describe("useDisplayVertexFromVertex", () => { const schema = createRandomSchema(); schema.prefixes = [ { - prefix: "example", - uri: "http://www.example.com/resources#", + prefix: "example" as RdfPrefix, + uri: "http://www.example.com/resources#" as IriNamespace, }, { - prefix: "example-class", - uri: "http://www.example.com/class#", + prefix: "example-class" as RdfPrefix, + uri: "http://www.example.com/class#" as IriNamespace, }, ]; diff --git a/packages/graph-explorer/src/core/StateProvider/schema.test.ts b/packages/graph-explorer/src/core/StateProvider/schema.test.ts index ac23b7bfb..08be4081b 100644 --- a/packages/graph-explorer/src/core/StateProvider/schema.test.ts +++ b/packages/graph-explorer/src/core/StateProvider/schema.test.ts @@ -1,6 +1,8 @@ import { createArray, createRandomName } from "@shared/utils/testing"; import { useAtomValue } from "jotai"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import { activeConfigurationAtom, configurationAtom, @@ -273,14 +275,14 @@ describe("schema", () => { expect(result.prefixes).toBeDefined(); expect(result.prefixes).toEqual([ { - prefix: "ver", - uri: "http://abcdefg.com/vertex#", + prefix: "ver" as RdfPrefix, + uri: "http://abcdefg.com/vertex#" as IriNamespace, __inferred: true, __matches: new Set(schema.vertices.map(v => v.type)), }, { - prefix: "edg", - uri: "http://abcdefg.com/edge#", + prefix: "edg" as RdfPrefix, + uri: "http://abcdefg.com/edge#" as IriNamespace, __inferred: true, __matches: new Set(schema.edges.map(e => e.type)), }, diff --git a/packages/graph-explorer/src/hooks/useTextTransform.test.ts b/packages/graph-explorer/src/hooks/useTextTransform.test.ts index 20f4c08e7..8f005fb82 100644 --- a/packages/graph-explorer/src/hooks/useTextTransform.test.ts +++ b/packages/graph-explorer/src/hooks/useTextTransform.test.ts @@ -1,5 +1,7 @@ import { vi } from "vitest"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import { activeConfigurationAtom, type AppStore, @@ -21,8 +23,8 @@ function initializeConfigWithPrefix(store: AppStore) { config.connection!.queryEngine = "sparql"; schema.prefixes = [ { - prefix: "rdf", - uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + prefix: "rdf" as RdfPrefix, + uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" as IriNamespace, }, ]; store.set(configurationAtom, new Map([[config.id, config]])); diff --git a/packages/graph-explorer/src/modules/Namespaces/UserPrefixes.tsx b/packages/graph-explorer/src/modules/Namespaces/UserPrefixes.tsx index fd9ee1fab..148c568b9 100644 --- a/packages/graph-explorer/src/modules/Namespaces/UserPrefixes.tsx +++ b/packages/graph-explorer/src/modules/Namespaces/UserPrefixes.tsx @@ -2,6 +2,8 @@ import { useAtomCallback } from "jotai/utils"; import { useCallback, useState } from "react"; import { Virtuoso } from "react-virtuoso"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import { AddIcon, Button, @@ -228,7 +230,10 @@ function EditPrefixModal({ ...(activeSchema || {}), vertices: activeSchema?.vertices || [], edges: activeSchema?.edges || [], - prefixes: [...(activeSchema?.prefixes || []), { prefix, uri }], + prefixes: [ + ...(activeSchema?.prefixes || []), + { prefix: prefix as RdfPrefix, uri: uri as IriNamespace }, + ], }); return updatedSchemas; diff --git a/packages/graph-explorer/src/utils/rdf/generatePrefixes.test.ts b/packages/graph-explorer/src/utils/rdf/generatePrefixes.test.ts index 57570a2df..80726acfc 100644 --- a/packages/graph-explorer/src/utils/rdf/generatePrefixes.test.ts +++ b/packages/graph-explorer/src/utils/rdf/generatePrefixes.test.ts @@ -1,3 +1,6 @@ +import type { PrefixTypeConfig } from "@/core"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import generatePrefixes, { generateHashPrefix, generatePrefix, @@ -5,15 +8,15 @@ import generatePrefixes, { describe("generatePrefixes", () => { it("should return null when nothing is updated", () => { - const existing = [ + const existing: PrefixTypeConfig[] = [ { - prefix: "owl", - uri: "https://www.w3.org/2002/07/owl#", + prefix: "owl" as RdfPrefix, + uri: "https://www.w3.org/2002/07/owl#" as IriNamespace, __matches: new Set(["https://www.w3.org/2002/07/owl#ObjectProperty"]), }, { - prefix: "rdf", - uri: "https://www.w3.org/2000/01/rdf-schema#", + prefix: "rdf" as RdfPrefix, + uri: "https://www.w3.org/2000/01/rdf-schema#" as IriNamespace, __matches: new Set([ "https://www.w3.org/2000/01/rdf-schema#subClassOf", ]), @@ -111,12 +114,18 @@ describe("generatePrefixes", () => { "http://www.example.com/location/resource#Manchester", ]), [ - { prefix: "owl", uri: "https://www.w3.org/2002/07/owl#" }, - { prefix: "dbr", uri: "https://dbpedia.org/resource/" }, + { + prefix: "owl" as RdfPrefix, + uri: "https://www.w3.org/2002/07/owl#" as IriNamespace, + }, + { + prefix: "dbr" as RdfPrefix, + uri: "https://dbpedia.org/resource/" as IriNamespace, + }, { __inferred: true, - prefix: "loc-r", - uri: "http://www.example.com/location/resource#", + prefix: "loc-r" as RdfPrefix, + uri: "http://www.example.com/location/resource#" as IriNamespace, __matches: new Set([ "http://www.example.com/location/resource#London", "http://www.example.com/location/resource#Manchester", @@ -169,8 +178,8 @@ describe("generatePrefixes", () => { [ { __inferred: true, - prefix: "ent", - uri: "http://secretspyorg/entity/", + prefix: "ent" as RdfPrefix, + uri: "http://secretspyorg/entity/" as IriNamespace, __matches: new Set(["http://SecretSpyOrg/entity/quantity"]), }, ], diff --git a/packages/graph-explorer/src/utils/rdf/generatePrefixes.ts b/packages/graph-explorer/src/utils/rdf/generatePrefixes.ts index d56f063e5..3e2d4e768 100644 --- a/packages/graph-explorer/src/utils/rdf/generatePrefixes.ts +++ b/packages/graph-explorer/src/utils/rdf/generatePrefixes.ts @@ -1,10 +1,15 @@ import type { PrefixTypeConfig } from "@/core"; +import type { IriNamespace, RdfPrefix } from "./types"; + import commonPrefixes from "./common-prefixes.json"; // Create a map of the common prefixes const commonPrefixesMap = toPrefixTypeConfigMap( - Object.entries(commonPrefixes).map(([prefix, uri]) => ({ prefix, uri })), + Object.entries(commonPrefixes).map(([prefix, uri]) => ({ + prefix: prefix as RdfPrefix, + uri: uri as IriNamespace, + })), ); /** Helper function to create a map of prefix configs from an array of configs. */ @@ -79,8 +84,8 @@ export function generateHashPrefix( return { __inferred: true, - uri: url.href.replace(url.hash, "#"), - prefix, + uri: url.href.replace(url.hash, "#") as IriNamespace, + prefix: prefix as RdfPrefix, }; } @@ -95,8 +100,8 @@ export function generatePrefix(url: URL): Omit { const prefix = prefixFromHost(url.host); return { __inferred: true, - uri: url.origin + "/", - prefix, + uri: (url.origin + "/") as IriNamespace, + prefix: prefix as RdfPrefix, }; } @@ -113,8 +118,8 @@ export function generatePrefix(url: URL): Omit { return { __inferred: true, - uri: uriChunks.join("/") + "/", - prefix, + uri: (uriChunks.join("/") + "/") as IriNamespace, + prefix: prefix as RdfPrefix, }; } @@ -126,8 +131,8 @@ export function generatePrefix(url: URL): Omit { const prefix = prefixFromHost(url.host); return { __inferred: true, - uri: url.origin + "/", - prefix, + uri: (url.origin + "/") as IriNamespace, + prefix: prefix as RdfPrefix, }; } @@ -135,8 +140,8 @@ export function generatePrefix(url: URL): Omit { uriChunks.length = uriChunks.length - 1; return { __inferred: true, - uri: uriChunks.join("/") + "/", - prefix: filteredPaths[0].substring(0, 3), + uri: (uriChunks.join("/") + "/") as IriNamespace, + prefix: filteredPaths[0].substring(0, 3) as RdfPrefix, }; } diff --git a/packages/graph-explorer/src/utils/rdf/index.ts b/packages/graph-explorer/src/utils/rdf/index.ts index ae5fadf7f..6535943c5 100644 --- a/packages/graph-explorer/src/utils/rdf/index.ts +++ b/packages/graph-explorer/src/utils/rdf/index.ts @@ -1,2 +1,10 @@ export { default as replacePrefixes } from "./replacePrefixes"; export { default as generatePrefixes } from "./generatePrefixes"; +export type { + GeneratedPrefix, + IriLocalValue, + IriNamespace, + IriParts, + NormalizedIriNamespace, + RdfPrefix, +} from "./types"; diff --git a/packages/graph-explorer/src/utils/rdf/replacePrefixes.test.ts b/packages/graph-explorer/src/utils/rdf/replacePrefixes.test.ts index 27376c4e3..1d9609d1c 100644 --- a/packages/graph-explorer/src/utils/rdf/replacePrefixes.test.ts +++ b/packages/graph-explorer/src/utils/rdf/replacePrefixes.test.ts @@ -1,3 +1,5 @@ +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + import replacePrefixes from "./replacePrefixes"; test("should do nothing when no URI is provided", () => { @@ -12,7 +14,10 @@ test("should replace using common prefixes", () => { test("should replace using custom prefixes", () => { const result = replacePrefixes("http://example.com/foo/bar", [ - { prefix: "foo", uri: "http://example.com/foo/" }, + { + prefix: "foo" as RdfPrefix, + uri: "http://example.com/foo/" as IriNamespace, + }, ]); expect(result).toBe("foo:bar"); }); @@ -20,8 +25,8 @@ test("should replace using custom prefixes", () => { test("should use generated prefixes", () => { const result = replacePrefixes("http://foo.com/foo/bar", [ { - prefix: "foo", - uri: "http://foo.com/foo/", + prefix: "foo" as RdfPrefix, + uri: "http://foo.com/foo/" as IriNamespace, __inferred: true, __matches: new Set(["http://foo.com/foo/bar"]), }, @@ -32,8 +37,8 @@ test("should use generated prefixes", () => { test("should prefer common prefixes over generated prefixes", () => { const result = replacePrefixes("http://example.com/foo/bar", [ { - prefix: "foo", - uri: "http://example.com/foo/", + prefix: "foo" as RdfPrefix, + uri: "http://example.com/foo/" as IriNamespace, __inferred: true, __matches: new Set(["http://example.com/foo/bar"]), }, diff --git a/packages/graph-explorer/src/utils/rdf/replacePrefixes.ts b/packages/graph-explorer/src/utils/rdf/replacePrefixes.ts index 0f08c21c3..c0ac6b1ba 100644 --- a/packages/graph-explorer/src/utils/rdf/replacePrefixes.ts +++ b/packages/graph-explorer/src/utils/rdf/replacePrefixes.ts @@ -1,13 +1,15 @@ import type { PrefixTypeConfig } from "@/core"; +import type { IriNamespace, RdfPrefix } from "./types"; + import commonPrefixes from "./common-prefixes.json"; -const commonPrefixesConfig = Object.entries(commonPrefixes).map( - ([prefix, uri]) => ({ - prefix, - uri, - }), -); +const commonPrefixesConfig: PrefixTypeConfig[] = Object.entries( + commonPrefixes, +).map(([prefix, uri]) => ({ + prefix: prefix as RdfPrefix, + uri: uri as IriNamespace, +})); const replacePrefixes = ( uri?: string, diff --git a/packages/graph-explorer/src/utils/rdf/types.ts b/packages/graph-explorer/src/utils/rdf/types.ts new file mode 100644 index 000000000..5538935fd --- /dev/null +++ b/packages/graph-explorer/src/utils/rdf/types.ts @@ -0,0 +1,24 @@ +import type { Branded } from "@/utils"; + +/** The namespace portion of an IRI, including the trailing `#` or `/`. */ +export type IriNamespace = Branded; + +/** The local value after the namespace separator in an IRI. */ +export type IriLocalValue = Branded; + +/** The namespace and local value components of a split IRI. */ +export type IriParts = { + namespace: IriNamespace; + value: IriLocalValue; +}; + +/** A short prefix name derived from an IRI namespace. */ +export type RdfPrefix = Branded; + +/** The result of generating a prefix from an IRI, combining the split parts with the derived prefix name. */ +export type GeneratedPrefix = IriParts & { + prefix: RdfPrefix; +}; + +/** A lowercase, trimmed namespace used as a map key for case-insensitive lookups. */ +export type NormalizedIriNamespace = Branded; diff --git a/packages/graph-explorer/src/utils/saveConfigurationToFile.test.ts b/packages/graph-explorer/src/utils/saveConfigurationToFile.test.ts index 471311ec1..e160a59b6 100644 --- a/packages/graph-explorer/src/utils/saveConfigurationToFile.test.ts +++ b/packages/graph-explorer/src/utils/saveConfigurationToFile.test.ts @@ -2,6 +2,7 @@ import * as fileSaver from "file-saver"; import { describe, expect, it, vi } from "vitest"; import type { ConfigurationContextProps } from "@/core"; +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; import { createEdgeType, createVertexType } from "@/core"; @@ -177,13 +178,13 @@ describe("saveConfigurationToFile", () => { edges: [], prefixes: [ { - prefix: "rdf", - uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#", + prefix: "rdf" as RdfPrefix, + uri: "http://www.w3.org/1999/02/22-rdf-syntax-ns#" as IriNamespace, __matches: new Set(["http://www.w3.org/1999/02/22-rdf-syntax-ns#"]), }, { - prefix: "rdfs", - uri: "http://www.w3.org/2000/01/rdf-schema#", + prefix: "rdfs" as RdfPrefix, + uri: "http://www.w3.org/2000/01/rdf-schema#" as IriNamespace, __matches: new Set(["http://www.w3.org/2000/01/rdf-schema#"]), }, ], diff --git a/packages/graph-explorer/src/utils/testing/randomData.ts b/packages/graph-explorer/src/utils/testing/randomData.ts index bbd7dd1ed..8c4e75694 100644 --- a/packages/graph-explorer/src/utils/testing/randomData.ts +++ b/packages/graph-explorer/src/utils/testing/randomData.ts @@ -172,10 +172,12 @@ export function createRandomVertexTypeConfigForRdf(): VertexTypeConfig { }; } +import type { IriNamespace, RdfPrefix } from "@/utils/rdf"; + export function createRandomPrefixTypeConfig(): PrefixTypeConfig { return { - prefix: createRandomName("prefix"), - uri: createRandomUrlString(), + prefix: createRandomName("prefix") as RdfPrefix, + uri: createRandomUrlString() as IriNamespace, }; }