diff --git a/.changeset/eighty-geckos-burn.md b/.changeset/eighty-geckos-burn.md new file mode 100644 index 000000000..f83e1a467 --- /dev/null +++ b/.changeset/eighty-geckos-burn.md @@ -0,0 +1,6 @@ +--- +"@cube-creator/core-api": patch +"@cube-creator/cli": patch +--- + +Avoid duplicate datePublished on first revision diff --git a/apis/core/lib/domain/job/update.ts b/apis/core/lib/domain/job/update.ts index e257fcfef..db1fbc0d4 100644 --- a/apis/core/lib/domain/job/update.ts +++ b/apis/core/lib/domain/job/update.ts @@ -30,7 +30,7 @@ export async function update({ resource, store }: JobUpdateParams): Promise(project.dataset.id) - if (job.revision === 1) { + if (job.revision === 1 && !dataset.published) { dataset.setPublishedDate(job.modified) } } else if (isTransformJob(job)) { diff --git a/apis/core/test/domain/job/update.test.ts b/apis/core/test/domain/job/update.test.ts index 39c195bd0..a513b758e 100644 --- a/apis/core/test/domain/job/update.test.ts +++ b/apis/core/test/domain/job/update.test.ts @@ -202,6 +202,33 @@ describe('domain/job/update', () => { }) }) + it('does not change dataset published date on first revision', async () => { + // given + const resource = clownface({ dataset: $rdf.dataset() }) + .namedNode('job') + .addOut(schema.actionStatus, schema.CompletedActionStatus) + .addOut(dcterms.modified, $rdf.literal('2020-12-12T11:30:30', xsd.dateTime)) + job + .addOut(cc.revision, 1) + dataset.addOut(schema.datePublished, $rdf.literal('2020-10-12', xsd.date)) + + // when + await update({ + resource, + store, + }) + + // then + expect(dataset).to.matchShape({ + property: { + path: schema.datePublished, + hasValue: $rdf.literal('2020-10-12', xsd.date), + minCount: 1, + maxCount: 1, + }, + }) + }) + it('does not change dataset published date on revision>1', async () => { // given const resource = clownface({ dataset: $rdf.dataset() }) diff --git a/cli/lib/metadata.ts b/cli/lib/metadata.ts index 6554a0ef2..a1d7cfb14 100644 --- a/cli/lib/metadata.ts +++ b/cli/lib/metadata.ts @@ -1,7 +1,7 @@ import type { Literal, NamedNode, Quad } from '@rdfjs/types' import { obj } from 'through2' import $rdf from 'rdf-ext' -import { dcat, dcterms, rdf, schema, sh, _void, foaf } from '@tpluscode/rdf-ns-builders' +import { dcat, dcterms, rdf, schema, sh, _void, foaf, xsd } from '@tpluscode/rdf-ns-builders' import { cc, cube } from '@cube-creator/core/namespace' import { Dataset, Project, PublishJob } from '@cube-creator/model' import { HydraClient } from 'alcaeus/alcaeus' @@ -10,7 +10,7 @@ import { Published } from '@cube-creator/model/Cube' import { CONSTRUCT, sparql } from '@tpluscode/sparql-builder' import StreamClient from 'sparql-http-client/StreamClient' import { Readable } from 'readable-stream' -import { toRdf } from 'rdf-literal' +import { fromRdf, toRdf } from 'rdf-literal' import { tracer } from './otel/tracer' import { loadProject } from './project' @@ -54,6 +54,7 @@ interface QueryParams { project: Project revision: Literal cubeIdentifier: string + timestamp: Literal } function sourceCubeAndShape({ project, revision, cubeIdentifier }: QueryParams) { @@ -87,7 +88,8 @@ function sourceCubeAndShape({ project, revision, cubeIdentifier }: QueryParams) ` } -function cubeMetadata({ project, revision }: QueryParams) { +function cubeMetadata({ project, revision, timestamp }: QueryParams) { + const defaultDatePublished = toRdf(fromRdf(timestamp), { datatype: xsd.date }) return sparql` graph ${project.cubeGraph} { ?cube a ${cube.Cube} . @@ -96,6 +98,9 @@ function cubeMetadata({ project, revision }: QueryParams) { graph ${project.dataset.id} { ${project.dataset.id} ?cubeProp ?cubeMeta . + FILTER (?cubeProp != ${schema.datePublished}) + OPTIONAL { ${project.dataset.id} ${schema.datePublished} ?d } + BIND(COALESCE(?d, ${defaultDatePublished}) AS ?datePublished) MINUS { ${project.dataset.id} ${schema.hasPart}|${cc.dimensionMetadata} ?cubeMeta @@ -188,6 +193,7 @@ export async function loadCubeMetadata(this: Context, { jobUri, endpoint, user, project, cubeIdentifier, revision, + timestamp, } const stream = await CONSTRUCT` @@ -202,7 +208,7 @@ export async function loadCubeMetadata(this: Context, { jobUri, endpoint, user, ${dcat.accessURL} ${maintainer.accessURL} ; ${_void.sparqlEndpoint} ${maintainer.sparqlEndpoint} ; - ${revision.value === '1' ? sparql`${schema.datePublished} ${timestamp}` : ''} + ${schema.datePublished} ?datePublished ; . ?cube a ${schema.CreativeWork} ; ${schema.hasPart} ?cubeVersion . diff --git a/cli/test/lib/commands/publish.test.ts b/cli/test/lib/commands/publish.test.ts index 817f2eede..78981a0e2 100644 --- a/cli/test/lib/commands/publish.test.ts +++ b/cli/test/lib/commands/publish.test.ts @@ -306,6 +306,17 @@ describe('@cube-creator/cli/lib/commands/publish', function () { }) }) + it('adds published date to published cube', async function () { + expect(cubePointer.namedNode(targetCube())).to.matchShape({ + property: [{ + path: schema.datePublished, + datatype: xsd.date, + minCount: 1, + maxCount: 1, + }], + }) + }) + it('adds project identifier to dataset metadata', async function () { expect(cubePointer.namedNode(targetCube())).to.matchShape({ property: [{