@twin.org/federated-catalogue-service 0.0.3-next.3 → 0.0.3-next.5
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/dist/es/entities/dataset.js +1 -1
- package/dist/es/entities/dataset.js.map +1 -1
- package/dist/es/federatedCatalogueRoutes.js +39 -39
- package/dist/es/federatedCatalogueRoutes.js.map +1 -1
- package/dist/es/services/federatedCatalogueService.js +242 -82
- package/dist/es/services/federatedCatalogueService.js.map +1 -1
- package/dist/es/utils/datasetConverters.js +4 -4
- package/dist/es/utils/datasetConverters.js.map +1 -1
- package/dist/types/entities/dataset.d.ts +31 -31
- package/dist/types/services/federatedCatalogueService.d.ts +44 -12
- package/dist/types/utils/datasetConverters.d.ts +7 -7
- package/docs/changelog.md +29 -0
- package/docs/open-api/spec.json +708 -1850
- package/docs/reference/classes/Dataset.md +12 -12
- package/docs/reference/classes/FederatedCatalogueService.md +28 -18
- package/docs/reference/functions/datasetEntityToModel.md +4 -4
- package/docs/reference/functions/datasetModelToEntity.md +3 -3
- package/locales/en.json +5 -1
- package/package.json +3 -3
|
@@ -4,7 +4,7 @@ import { entity, property } from "@twin.org/entity";
|
|
|
4
4
|
/**
|
|
5
5
|
* Class describing a DCAT dataset for entity storage.
|
|
6
6
|
* This wrapper enables efficient database indexing and querying while preserving
|
|
7
|
-
* the full
|
|
7
|
+
* the full IDcatDataset JSON-LD structure.
|
|
8
8
|
*/
|
|
9
9
|
let Dataset = class Dataset {
|
|
10
10
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dataset.js","sourceRoot":"","sources":["../../../src/entities/dataset.ts"],"names":[],"mappings":"AAAA,gCAAgC;AAChC,uCAAuC;AACvC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAGpD;;;;GAIG;AAEI,IAAM,OAAO,GAAb,MAAM,OAAO;IACnB;;OAEG;IAEI,KAAK,CAAU;IAEtB;;OAEG;IAEI,UAAU,
|
|
1
|
+
{"version":3,"file":"dataset.js","sourceRoot":"","sources":["../../../src/entities/dataset.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport { entity, property } from \"@twin.org/entity\";\nimport type { IDcatDataset } from \"@twin.org/standards-w3c-dcat\";\n\n/**\n * Class describing a DCAT dataset for entity storage.\n * This wrapper enables efficient database indexing and querying while preserving\n * the full IDcatDataset JSON-LD structure.\n */\n@entity()\nexport class Dataset {\n\t/**\n\t * The unique identifier for the dataset (@id from JSON-LD).\n\t */\n\t@property({ type: \"string\", isPrimary: true })\n\tpublic \"@id\"!: string;\n\n\t/**\n\t * The JSON-LD context for the dataset.\n\t */\n\t@property({ type: \"object\" })\n\tpublic \"@context\"!: IDcatDataset[\"@context\"];\n\n\t/**\n\t * The type of the resource (typically \"Dataset\").\n\t */\n\t@property({ type: \"string\" })\n\tpublic \"@type\"!: IDcatDataset[\"@type\"];\n\n\t/**\n\t * A name given to the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:title\"?: IDcatDataset[\"dcterms:title\"];\n\n\t/**\n\t * A free-text account of the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:description\"?: IDcatDataset[\"dcterms:description\"];\n\n\t/**\n\t * A unique identifier of the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:identifier\"?: IDcatDataset[\"dcterms:identifier\"];\n\n\t/**\n\t * Date of formal issuance (publication) of the resource.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic \"dcterms:issued\"?: IDcatDataset[\"dcterms:issued\"];\n\n\t/**\n\t * Most recent date on which the resource was changed, updated or modified.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic \"dcterms:modified\"?: IDcatDataset[\"dcterms:modified\"];\n\n\t/**\n\t * A language of the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:language\"?: IDcatDataset[\"dcterms:language\"];\n\n\t/**\n\t * An entity responsible for making the resource available.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:publisher\"?: IDcatDataset[\"dcterms:publisher\"];\n\n\t/**\n\t * An entity responsible for producing the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:creator\"?: IDcatDataset[\"dcterms:creator\"];\n\n\t/**\n\t * Information about who can access the resource or an indication of its security status.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:accessRights\"?: IDcatDataset[\"dcterms:accessRights\"];\n\n\t/**\n\t * A legal document under which the resource is made available.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:license\"?: IDcatDataset[\"dcterms:license\"];\n\n\t/**\n\t * Information about rights held in and over the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:rights\"?: IDcatDataset[\"dcterms:rights\"];\n\n\t/**\n\t * An established standard to which the resource conforms.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:conformsTo\"?: IDcatDataset[\"dcterms:conformsTo\"];\n\n\t/**\n\t * The nature or genre of the resource.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic \"dcterms:type\"?: IDcatDataset[\"dcterms:type\"];\n\n\t/**\n\t * Relevant contact information for the catalogued resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:contactPoint\"?: IDcatDataset[\"dcat:contactPoint\"];\n\n\t/**\n\t * A keyword or tag describing the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:keyword\"?: IDcatDataset[\"dcat:keyword\"];\n\n\t/**\n\t * A main category of the resource. A resource can have multiple themes.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:theme\"?: IDcatDataset[\"dcat:theme\"];\n\n\t/**\n\t * A Web page that can be navigated to gain access to the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:landingPage\"?: IDcatDataset[\"dcat:landingPage\"];\n\n\t/**\n\t * Link to a description of a relationship with another resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:qualifiedRelation\"?: IDcatDataset[\"dcat:qualifiedRelation\"];\n\n\t/**\n\t * An ODRL conformant policy expressing the rights associated with the resource.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"odrl:hasPolicy\"?: IDcatDataset[\"odrl:hasPolicy\"];\n\n\t/**\n\t * An available distribution of the dataset.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:distribution\"?: IDcatDataset[\"dcat:distribution\"];\n\n\t/**\n\t * The frequency at which the dataset is published.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic \"dcterms:accrualPeriodicity\"?: IDcatDataset[\"dcterms:accrualPeriodicity\"];\n\n\t/**\n\t * A dataset series of which the dataset is part.\n\t */\n\t@property({ type: \"string\", optional: true })\n\tpublic \"dcat:inSeries\"?: IDcatDataset[\"dcat:inSeries\"];\n\n\t/**\n\t * The geographical area covered by the dataset.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:spatial\"?: IDcatDataset[\"dcterms:spatial\"];\n\n\t/**\n\t * Minimum spatial separation resolvable in a dataset, measured in meters.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:spatialResolutionInMeters\"?: IDcatDataset[\"dcat:spatialResolutionInMeters\"];\n\n\t/**\n\t * The temporal period that the dataset covers.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcterms:temporal\"?: IDcatDataset[\"dcterms:temporal\"];\n\n\t/**\n\t * Minimum time period resolvable in the dataset.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"dcat:temporalResolution\"?: IDcatDataset[\"dcat:temporalResolution\"];\n\n\t/**\n\t * An activity that generated, or provides the business context for, the creation of the dataset.\n\t */\n\t@property({ type: \"object\", optional: true })\n\tpublic \"prov:wasGeneratedBy\"?: IDcatDataset[\"prov:wasGeneratedBy\"];\n}\n"]}
|
|
@@ -1,8 +1,7 @@
|
|
|
1
|
-
import { ComponentFactory, Guards } from "@twin.org/core";
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
import {
|
|
5
|
-
import { DcatClasses, DcatContexts } from "@twin.org/standards-w3c-dcat";
|
|
1
|
+
import { Coerce, ComponentFactory, Guards, Is } from "@twin.org/core";
|
|
2
|
+
import { DataspaceProtocolCatalogTypes, DataspaceProtocolContexts } from "@twin.org/standards-dataspace-protocol";
|
|
3
|
+
import { DcatClasses } from "@twin.org/standards-w3c-dcat";
|
|
4
|
+
import { HeaderHelper, HeaderTypes, HttpStatusCode } from "@twin.org/web";
|
|
6
5
|
/**
|
|
7
6
|
* The source used when communicating about these routes.
|
|
8
7
|
*/
|
|
@@ -37,8 +36,8 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
37
36
|
id: "catalogRequestExample",
|
|
38
37
|
request: {
|
|
39
38
|
body: {
|
|
40
|
-
"@context": [DataspaceProtocolContexts.
|
|
41
|
-
"@type":
|
|
39
|
+
"@context": [DataspaceProtocolContexts.JsonLdContext],
|
|
40
|
+
"@type": DataspaceProtocolCatalogTypes.CatalogRequestMessage,
|
|
42
41
|
filter: [
|
|
43
42
|
{
|
|
44
43
|
"dcterms:title": "Energy Consumption Data"
|
|
@@ -51,8 +50,8 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
51
50
|
id: "catalogRequestNoFilterExample",
|
|
52
51
|
request: {
|
|
53
52
|
body: {
|
|
54
|
-
"@context": [DataspaceProtocolContexts.
|
|
55
|
-
"@type":
|
|
53
|
+
"@context": [DataspaceProtocolContexts.JsonLdContext],
|
|
54
|
+
"@type": DataspaceProtocolCatalogTypes.CatalogRequestMessage
|
|
56
55
|
}
|
|
57
56
|
}
|
|
58
57
|
}
|
|
@@ -66,23 +65,17 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
66
65
|
id: "catalogRequestResponseExample",
|
|
67
66
|
response: {
|
|
68
67
|
body: {
|
|
69
|
-
"@context": [
|
|
70
|
-
DataspaceProtocolContexts.ContextRoot,
|
|
71
|
-
{
|
|
72
|
-
dcat: DcatContexts.ContextRoot,
|
|
73
|
-
dcterms: DublinCoreContexts.ContextTerms,
|
|
74
|
-
cursor: `${FederatedCatalogueContexts.ContextRoot}cursor`
|
|
75
|
-
}
|
|
76
|
-
],
|
|
68
|
+
"@context": [DataspaceProtocolContexts.JsonLdContext],
|
|
77
69
|
"@id": "urn:x-catalog:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2",
|
|
78
|
-
"@type":
|
|
70
|
+
"@type": "Catalog",
|
|
79
71
|
participantId: "did:example:node-identity-123",
|
|
80
|
-
|
|
72
|
+
dataset: [
|
|
81
73
|
{
|
|
74
|
+
"@context": [DataspaceProtocolContexts.JsonLdContext],
|
|
82
75
|
"@id": "urn:uuid:dataset-123",
|
|
83
|
-
"@type":
|
|
84
|
-
|
|
85
|
-
|
|
76
|
+
"@type": "Dataset",
|
|
77
|
+
title: "Energy Consumption Data",
|
|
78
|
+
description: "Historical energy consumption data"
|
|
86
79
|
}
|
|
87
80
|
]
|
|
88
81
|
}
|
|
@@ -120,13 +113,7 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
120
113
|
id: "getDatasetResponseExample",
|
|
121
114
|
response: {
|
|
122
115
|
body: {
|
|
123
|
-
"@context":
|
|
124
|
-
DataspaceProtocolContexts.ContextRoot,
|
|
125
|
-
{
|
|
126
|
-
dcat: DcatContexts.ContextRoot,
|
|
127
|
-
dcterms: DublinCoreContexts.ContextTerms
|
|
128
|
-
}
|
|
129
|
-
],
|
|
116
|
+
"@context": DataspaceProtocolContexts.JsonLdContext,
|
|
130
117
|
"@id": "urn:uuid:dataset-123",
|
|
131
118
|
"@type": DcatClasses.Dataset,
|
|
132
119
|
"dcterms:title": "Energy Consumption Data",
|
|
@@ -140,6 +127,17 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
140
127
|
};
|
|
141
128
|
return [catalogRequestRoute, getDatasetRoute];
|
|
142
129
|
}
|
|
130
|
+
/**
|
|
131
|
+
* Map the DS Protocol result to an HTTP status code.
|
|
132
|
+
* @param result The result to map.
|
|
133
|
+
* @returns The mapped status code or undefined if no mapping was found or not an error.
|
|
134
|
+
*/
|
|
135
|
+
function mapCatalogError(result) {
|
|
136
|
+
if (result?.["@type"] === DataspaceProtocolCatalogTypes.CatalogError && Is.objectValue(result)) {
|
|
137
|
+
return Coerce.integer(result.code) ?? HttpStatusCode.badRequest;
|
|
138
|
+
}
|
|
139
|
+
return undefined;
|
|
140
|
+
}
|
|
143
141
|
/**
|
|
144
142
|
* Handle the catalog request operation.
|
|
145
143
|
* @param httpRequestContext The request context for the operation.
|
|
@@ -150,16 +148,17 @@ export function generateRestRoutesFederatedCatalogue(baseRouteName, componentNam
|
|
|
150
148
|
async function catalogRequest(httpRequestContext, componentName, request) {
|
|
151
149
|
Guards.object(ROUTES_SOURCE, "request", request);
|
|
152
150
|
Guards.object(ROUTES_SOURCE, "request.body", request.body);
|
|
151
|
+
Guards.stringValue(ROUTES_SOURCE, "@type", request.body["@type"]);
|
|
153
152
|
const component = ComponentFactory.get(componentName);
|
|
154
|
-
const
|
|
155
|
-
const catalog = await component.query(filter);
|
|
156
|
-
// Add participantId from nodeIdentity (the node providing the catalog)
|
|
157
|
-
const nodeIdentity = httpRequestContext.nodeIdentity;
|
|
158
|
-
if (nodeIdentity) {
|
|
159
|
-
catalog.participantId = nodeIdentity;
|
|
160
|
-
}
|
|
153
|
+
const result = await component.query(request.body.filter, request.query?.cursor, Coerce.integer(request.query?.limit));
|
|
161
154
|
return {
|
|
162
|
-
|
|
155
|
+
statusCode: mapCatalogError(result.catalog),
|
|
156
|
+
body: result.catalog,
|
|
157
|
+
headers: Is.stringValue(result.cursor) && Is.stringValue(httpRequestContext.serverRequest?.url)
|
|
158
|
+
? {
|
|
159
|
+
[HeaderTypes.Link]: HeaderHelper.createLinkHeader(httpRequestContext.serverRequest.url, { cursor: result.cursor }, "next")
|
|
160
|
+
}
|
|
161
|
+
: undefined
|
|
163
162
|
};
|
|
164
163
|
}
|
|
165
164
|
/**
|
|
@@ -174,9 +173,10 @@ async function getDataset(httpRequestContext, componentName, request) {
|
|
|
174
173
|
Guards.object(ROUTES_SOURCE, "request.pathParams", request.pathParams);
|
|
175
174
|
Guards.stringValue(ROUTES_SOURCE, "request.pathParams.datasetId", request.pathParams.datasetId);
|
|
176
175
|
const component = ComponentFactory.get(componentName);
|
|
177
|
-
const
|
|
176
|
+
const result = await component.get(request.pathParams.datasetId);
|
|
178
177
|
return {
|
|
179
|
-
|
|
178
|
+
statusCode: mapCatalogError(result),
|
|
179
|
+
body: result
|
|
180
180
|
};
|
|
181
181
|
}
|
|
182
182
|
//# sourceMappingURL=federatedCatalogueRoutes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"federatedCatalogueRoutes.js","sourceRoot":"","sources":["../../src/federatedCatalogueRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IHttpRequestContext, IRestRoute, ITag } from \"@twin.org/api-models\";\nimport { ComponentFactory, Guards } from \"@twin.org/core\";\nimport type { IJsonLdContextDefinitionRoot } from \"@twin.org/data-json-ld\";\nimport type {\n\tICatalogRequestRequest,\n\tICatalogRequestResponse,\n\tIFederatedCatalogueComponent,\n\tIGetDatasetRequest,\n\tIGetDatasetResponse\n} from \"@twin.org/federated-catalogue-models\";\nimport { FederatedCatalogueContexts } from \"@twin.org/federated-catalogue-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport { CatalogTypes, DataspaceProtocolContexts } from \"@twin.org/standards-dataspace-protocol\";\nimport { DublinCoreContexts } from \"@twin.org/standards-dublin-core\";\nimport { DcatClasses, DcatContexts, type DcatContextType } from \"@twin.org/standards-w3c-dcat\";\n\n/**\n * The source used when communicating about these routes.\n */\nconst ROUTES_SOURCE = \"federatedCatalogueRoutes\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsFederatedCatalogue: ITag[] = [\n\t{\n\t\tname: \"Federated Catalogue\",\n\t\tdescription:\n\t\t\t\"Service providing Dataspace Protocol-compliant catalogue endpoints for dataset discovery and query.\"\n\t}\n];\n\n/**\n * The REST routes for federated catalogue.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesFederatedCatalogue(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst catalogRequestRoute: IRestRoute<ICatalogRequestRequest, ICatalogRequestResponse> = {\n\t\toperationId: \"catalogRequest\",\n\t\tsummary: \"Query the federated catalogue for datasets\",\n\t\ttag: tagsFederatedCatalogue[0].name,\n\t\tmethod: \"POST\",\n\t\tpath: `${baseRouteName}/request`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tcatalogRequest(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<ICatalogRequestRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"catalogRequestExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.ContextRoot],\n\t\t\t\t\t\t\t\"@type\": CatalogTypes.CatalogRequestMessage,\n\t\t\t\t\t\t\tfilter: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"dcterms:title\": \"Energy Consumption Data\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: \"catalogRequestNoFilterExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.ContextRoot],\n\t\t\t\t\t\t\t\"@type\": CatalogTypes.CatalogRequestMessage\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<ICatalogRequestResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"catalogRequestResponseExample\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\"@context\": [\n\t\t\t\t\t\t\t\t\tDataspaceProtocolContexts.ContextRoot,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdcat: DcatContexts.ContextRoot,\n\t\t\t\t\t\t\t\t\t\tdcterms: DublinCoreContexts.ContextTerms,\n\t\t\t\t\t\t\t\t\t\tcursor: `${FederatedCatalogueContexts.ContextRoot}cursor`\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t] as IJsonLdContextDefinitionRoot as DcatContextType,\n\t\t\t\t\t\t\t\t\"@id\":\n\t\t\t\t\t\t\t\t\t\"urn:x-catalog:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2\",\n\t\t\t\t\t\t\t\t\"@type\": DcatClasses.Catalog,\n\t\t\t\t\t\t\t\tparticipantId: \"did:example:node-identity-123\",\n\t\t\t\t\t\t\t\t\"dcat:dataset\": [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"@id\": \"urn:uuid:dataset-123\",\n\t\t\t\t\t\t\t\t\t\t\"@type\": DcatClasses.Dataset,\n\t\t\t\t\t\t\t\t\t\t\"dcterms:title\": \"Energy Consumption Data\",\n\t\t\t\t\t\t\t\t\t\t\"dcterms:description\": \"Historical energy consumption data\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t};\n\n\tconst getDatasetRoute: IRestRoute<IGetDatasetRequest, IGetDatasetResponse> = {\n\t\toperationId: \"getDataset\",\n\t\tsummary: \"Retrieve a specific dataset by ID\",\n\t\ttag: tagsFederatedCatalogue[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/datasets/:datasetId`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tgetDataset(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IGetDatasetRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"getDatasetRequestExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\tdatasetId: \"urn:uuid:dataset-123\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IGetDatasetResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"getDatasetResponseExample\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\"@context\": [\n\t\t\t\t\t\t\t\t\tDataspaceProtocolContexts.ContextRoot,\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\tdcat: DcatContexts.ContextRoot,\n\t\t\t\t\t\t\t\t\t\tdcterms: DublinCoreContexts.ContextTerms\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t] as IJsonLdContextDefinitionRoot as DcatContextType,\n\t\t\t\t\t\t\t\t\"@id\": \"urn:uuid:dataset-123\",\n\t\t\t\t\t\t\t\t\"@type\": DcatClasses.Dataset,\n\t\t\t\t\t\t\t\t\"dcterms:title\": \"Energy Consumption Data\",\n\t\t\t\t\t\t\t\t\"dcterms:description\": \"Historical energy consumption data\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t};\n\n\treturn [catalogRequestRoute, getDatasetRoute];\n}\n\n/**\n * Handle the catalog request operation.\n * @param httpRequestContext The request context for the operation.\n * @param componentName The name of the component to use.\n * @param request The request.\n * @returns The response.\n */\nasync function catalogRequest(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: ICatalogRequestRequest\n): Promise<ICatalogRequestResponse> {\n\tGuards.object<ICatalogRequestRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object(ROUTES_SOURCE, nameof(request.body), request.body);\n\n\tconst component: IFederatedCatalogueComponent = ComponentFactory.get(componentName);\n\n\tconst filter = request.body.filter;\n\n\tconst catalog = await component.query(filter);\n\n\t// Add participantId from nodeIdentity (the node providing the catalog)\n\tconst nodeIdentity = (httpRequestContext as { nodeIdentity?: string }).nodeIdentity;\n\tif (nodeIdentity) {\n\t\t(catalog as { participantId?: string }).participantId = nodeIdentity;\n\t}\n\n\treturn {\n\t\tbody: catalog\n\t};\n}\n\n/**\n * Handle the get dataset operation.\n * @param httpRequestContext The request context for the operation.\n * @param componentName The name of the component to use.\n * @param request The request.\n * @returns The response.\n */\nasync function getDataset(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IGetDatasetRequest\n): Promise<IGetDatasetResponse> {\n\tGuards.object<IGetDatasetRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object(ROUTES_SOURCE, nameof(request.pathParams), request.pathParams);\n\tGuards.stringValue(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams.datasetId),\n\t\trequest.pathParams.datasetId\n\t);\n\n\tconst component: IFederatedCatalogueComponent = ComponentFactory.get(componentName);\n\n\tconst dataset = await component.get(request.pathParams.datasetId);\n\n\treturn {\n\t\tbody: dataset\n\t};\n}\n"]}
|
|
1
|
+
{"version":3,"file":"federatedCatalogueRoutes.js","sourceRoot":"","sources":["../../src/federatedCatalogueRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["// Copyright 2025 IOTA Stiftung.\n// SPDX-License-Identifier: Apache-2.0.\nimport type { IHttpRequestContext, IRestRoute, ITag } from \"@twin.org/api-models\";\nimport { Coerce, ComponentFactory, Guards, Is } from \"@twin.org/core\";\nimport type {\n\tICatalogRequestRequest,\n\tICatalogRequestResponse,\n\tIFederatedCatalogueComponent,\n\tIGetDatasetRequest,\n\tIGetDatasetResponse\n} from \"@twin.org/federated-catalogue-models\";\nimport { nameof } from \"@twin.org/nameof\";\nimport {\n\tDataspaceProtocolCatalogTypes,\n\tDataspaceProtocolContexts,\n\ttype IDataspaceProtocolCatalog,\n\ttype IDataspaceProtocolCatalogError\n} from \"@twin.org/standards-dataspace-protocol\";\nimport { DcatClasses, type DcatContextType, type IDcatDataset } from \"@twin.org/standards-w3c-dcat\";\nimport { HeaderHelper, HeaderTypes, HttpStatusCode } from \"@twin.org/web\";\n\n/**\n * The source used when communicating about these routes.\n */\nconst ROUTES_SOURCE = \"federatedCatalogueRoutes\";\n\n/**\n * The tag to associate with the routes.\n */\nexport const tagsFederatedCatalogue: ITag[] = [\n\t{\n\t\tname: \"Federated Catalogue\",\n\t\tdescription:\n\t\t\t\"Service providing Dataspace Protocol-compliant catalogue endpoints for dataset discovery and query.\"\n\t}\n];\n\n/**\n * The REST routes for federated catalogue.\n * @param baseRouteName Prefix to prepend to the paths.\n * @param componentName The name of the component to use in the routes stored in the ComponentFactory.\n * @returns The generated routes.\n */\nexport function generateRestRoutesFederatedCatalogue(\n\tbaseRouteName: string,\n\tcomponentName: string\n): IRestRoute[] {\n\tconst catalogRequestRoute: IRestRoute<ICatalogRequestRequest, ICatalogRequestResponse> = {\n\t\toperationId: \"catalogRequest\",\n\t\tsummary: \"Query the federated catalogue for datasets\",\n\t\ttag: tagsFederatedCatalogue[0].name,\n\t\tmethod: \"POST\",\n\t\tpath: `${baseRouteName}/request`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tcatalogRequest(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<ICatalogRequestRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"catalogRequestExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.JsonLdContext],\n\t\t\t\t\t\t\t\"@type\": DataspaceProtocolCatalogTypes.CatalogRequestMessage,\n\t\t\t\t\t\t\tfilter: [\n\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\"dcterms:title\": \"Energy Consumption Data\"\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\tid: \"catalogRequestNoFilterExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.JsonLdContext],\n\t\t\t\t\t\t\t\"@type\": DataspaceProtocolCatalogTypes.CatalogRequestMessage\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<ICatalogRequestResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"catalogRequestResponseExample\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.JsonLdContext],\n\t\t\t\t\t\t\t\t\"@id\":\n\t\t\t\t\t\t\t\t\t\"urn:x-catalog:a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6a7b8c9d0e1f2\",\n\t\t\t\t\t\t\t\t\"@type\": \"Catalog\",\n\t\t\t\t\t\t\t\tparticipantId: \"did:example:node-identity-123\",\n\t\t\t\t\t\t\t\tdataset: [\n\t\t\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\t\t\"@context\": [DataspaceProtocolContexts.JsonLdContext],\n\t\t\t\t\t\t\t\t\t\t\"@id\": \"urn:uuid:dataset-123\",\n\t\t\t\t\t\t\t\t\t\t\"@type\": \"Dataset\",\n\t\t\t\t\t\t\t\t\t\ttitle: \"Energy Consumption Data\",\n\t\t\t\t\t\t\t\t\t\tdescription: \"Historical energy consumption data\"\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t]\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} as unknown as ICatalogRequestResponse\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t};\n\n\tconst getDatasetRoute: IRestRoute<IGetDatasetRequest, IGetDatasetResponse> = {\n\t\toperationId: \"getDataset\",\n\t\tsummary: \"Retrieve a specific dataset by ID\",\n\t\ttag: tagsFederatedCatalogue[0].name,\n\t\tmethod: \"GET\",\n\t\tpath: `${baseRouteName}/datasets/:datasetId`,\n\t\thandler: async (httpRequestContext, request) =>\n\t\t\tgetDataset(httpRequestContext, componentName, request),\n\t\trequestType: {\n\t\t\ttype: nameof<IGetDatasetRequest>(),\n\t\t\texamples: [\n\t\t\t\t{\n\t\t\t\t\tid: \"getDatasetRequestExample\",\n\t\t\t\t\trequest: {\n\t\t\t\t\t\tpathParams: {\n\t\t\t\t\t\t\tdatasetId: \"urn:uuid:dataset-123\"\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\tresponseType: [\n\t\t\t{\n\t\t\t\ttype: nameof<IGetDatasetResponse>(),\n\t\t\t\texamples: [\n\t\t\t\t\t{\n\t\t\t\t\t\tid: \"getDatasetResponseExample\",\n\t\t\t\t\t\tresponse: {\n\t\t\t\t\t\t\tbody: {\n\t\t\t\t\t\t\t\t\"@context\": DataspaceProtocolContexts.JsonLdContext as unknown as DcatContextType,\n\t\t\t\t\t\t\t\t\"@id\": \"urn:uuid:dataset-123\",\n\t\t\t\t\t\t\t\t\"@type\": DcatClasses.Dataset,\n\t\t\t\t\t\t\t\t\"dcterms:title\": \"Energy Consumption Data\",\n\t\t\t\t\t\t\t\t\"dcterms:description\": \"Historical energy consumption data\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t}\n\t\t]\n\t};\n\n\treturn [catalogRequestRoute, getDatasetRoute];\n}\n\n/**\n * Map the DS Protocol result to an HTTP status code.\n * @param result The result to map.\n * @returns The mapped status code or undefined if no mapping was found or not an error.\n */\nfunction mapCatalogError(\n\tresult: IDataspaceProtocolCatalog | IDcatDataset | IDataspaceProtocolCatalogError | undefined\n): HttpStatusCode | undefined {\n\tif (result?.[\"@type\"] === DataspaceProtocolCatalogTypes.CatalogError && Is.objectValue(result)) {\n\t\treturn (Coerce.integer(result.code) as HttpStatusCode) ?? HttpStatusCode.badRequest;\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Handle the catalog request operation.\n * @param httpRequestContext The request context for the operation.\n * @param componentName The name of the component to use.\n * @param request The request.\n * @returns The response.\n */\nasync function catalogRequest(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: ICatalogRequestRequest\n): Promise<ICatalogRequestResponse> {\n\tGuards.object<ICatalogRequestRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object(ROUTES_SOURCE, nameof(request.body), request.body);\n\tGuards.stringValue(ROUTES_SOURCE, \"@type\", request.body[\"@type\"]);\n\n\tconst component: IFederatedCatalogueComponent = ComponentFactory.get(componentName);\n\n\tconst result = await component.query(\n\t\trequest.body.filter as unknown[],\n\t\trequest.query?.cursor,\n\t\tCoerce.integer(request.query?.limit)\n\t);\n\n\treturn {\n\t\tstatusCode: mapCatalogError(result.catalog),\n\t\tbody: result.catalog,\n\t\theaders:\n\t\t\tIs.stringValue(result.cursor) && Is.stringValue(httpRequestContext.serverRequest?.url)\n\t\t\t\t? {\n\t\t\t\t\t\t[HeaderTypes.Link]: HeaderHelper.createLinkHeader(\n\t\t\t\t\t\t\thttpRequestContext.serverRequest.url,\n\t\t\t\t\t\t\t{ cursor: result.cursor },\n\t\t\t\t\t\t\t\"next\"\n\t\t\t\t\t\t)\n\t\t\t\t\t}\n\t\t\t\t: undefined\n\t};\n}\n\n/**\n * Handle the get dataset operation.\n * @param httpRequestContext The request context for the operation.\n * @param componentName The name of the component to use.\n * @param request The request.\n * @returns The response.\n */\nasync function getDataset(\n\thttpRequestContext: IHttpRequestContext,\n\tcomponentName: string,\n\trequest: IGetDatasetRequest\n): Promise<IGetDatasetResponse> {\n\tGuards.object<IGetDatasetRequest>(ROUTES_SOURCE, nameof(request), request);\n\tGuards.object(ROUTES_SOURCE, nameof(request.pathParams), request.pathParams);\n\tGuards.stringValue(\n\t\tROUTES_SOURCE,\n\t\tnameof(request.pathParams.datasetId),\n\t\trequest.pathParams.datasetId\n\t);\n\n\tconst component: IFederatedCatalogueComponent = ComponentFactory.get(componentName);\n\n\tconst result = await component.get(request.pathParams.datasetId);\n\n\treturn {\n\t\tstatusCode: mapCatalogError(result),\n\t\tbody: result\n\t};\n}\n"]}
|