diff --git a/apis/core/lib/domain/cube-projects/Project.ts b/apis/core/lib/domain/cube-projects/Project.ts index cf3f9975e..5986a071a 100644 --- a/apis/core/lib/domain/cube-projects/Project.ts +++ b/apis/core/lib/domain/cube-projects/Project.ts @@ -16,7 +16,6 @@ interface ApiProject { initializeJobCollection(store: ResourceStore): void incrementPublishedRevision(): void updateMaintainer(organization: Term | undefined): { before: Term; after: Term } - updateIsHiddenCube(hiddenCube: Term | undefined): void rename(name: string | undefined): void } @@ -92,14 +91,6 @@ export function ProjectMixin resource: GraphPointer @@ -127,11 +131,11 @@ export async function createProject({ if (!maintainer || maintainer.termType !== 'NamedNode') { throw new DomainError('Missing organization or not a named node') } - const hiddenCube = resource.out(cc.isHiddenCube).term - if (!hiddenCube || hiddenCube.termType !== 'Literal' || hiddenCube.datatype.value !== 'http://www.w3.org/2001/XMLSchema#boolean') { + const hiddenCube = resource.out(cc.isHiddenCube) + if (!isLiteral(hiddenCube, xsd.boolean)) { throw new DomainError('Missing flag isHiddenCube or not a boolean') } - const isHiddenCube = hiddenCube.value === 'true' + const isHiddenCube = xsdTrue.equals(hiddenCube.term) let project: Project.Project let dataset: Dataset.Dataset diff --git a/apis/core/lib/domain/cube-projects/import.ts b/apis/core/lib/domain/cube-projects/import.ts index 2cc6ee363..d6b6e9f68 100644 --- a/apis/core/lib/domain/cube-projects/import.ts +++ b/apis/core/lib/domain/cube-projects/import.ts @@ -5,8 +5,9 @@ import $rdf from 'rdf-ext' import { cc } from '@cube-creator/core/namespace' import { Files } from '@cube-creator/express/multipart' import { createMinimalProject, Project } from '@cube-creator/model/Project' -import { dcterms, rdfs, schema, rdf } from '@tpluscode/rdf-ns-builders/strict' +import { dcterms, rdfs, schema, rdf, xsd } from '@tpluscode/rdf-ns-builders/strict' import clownface, { GraphPointer } from 'clownface' +import { isLiteral } from 'is-graph-pointer' import { obj } from 'through2' import TermSet from '@rdfjs/term-set' import { Organization } from '@rdfine/schema' @@ -16,6 +17,8 @@ import * as id from '../identifiers' import { ResourceStore } from '../../ResourceStore' import { exists } from './queries' +const xsdTrue = $rdf.literal('true', xsd.boolean) + interface ImportProject { projectsCollection: GraphPointer resource: GraphPointer @@ -97,11 +100,11 @@ export async function importProject({ if (!maintainer) { throw new BadRequest('Missing organization') } - const hiddenCube = resource.out(cc.isHiddenCube).term - if (!hiddenCube || hiddenCube.termType !== 'Literal' || hiddenCube.datatype.value !== 'http://www.w3.org/2001/XMLSchema#boolean') { + const hiddenCube = resource.out(cc.isHiddenCube) + if (!isLiteral(hiddenCube, xsd.boolean)) { throw new DomainError('Missing flag isHiddenCube or not a boolean') } - const isHiddenCube = hiddenCube.value === 'true' + const isHiddenCube = xsdTrue.equals(hiddenCube.term) const projectNode = await store.createMember(projectsCollection.term, id.cubeProject(label)) diff --git a/apis/core/lib/domain/cube-projects/update.ts b/apis/core/lib/domain/cube-projects/update.ts index 2e062ab95..d7f245495 100644 --- a/apis/core/lib/domain/cube-projects/update.ts +++ b/apis/core/lib/domain/cube-projects/update.ts @@ -1,8 +1,9 @@ import type { NamedNode } from '@rdfjs/types' +import $rdf from 'rdf-ext' import { GraphPointer } from 'clownface' import { DomainError } from '@cube-creator/api-errors' import { cc } from '@cube-creator/core/namespace' -import { dcterms, rdfs, schema } from '@tpluscode/rdf-ns-builders' +import { dcterms, rdfs, schema, xsd } from '@tpluscode/rdf-ns-builders' import { CsvProject, ImportProject, Project } from '@cube-creator/model' import type { Organization } from '@rdfine/schema' import type { Dictionary } from '@rdfine/prov' @@ -11,6 +12,8 @@ import { ResourceStore } from '../../ResourceStore' import { cubeNamespaceAllowed } from '../organization/query' import { exists, previouslyPublished } from './queries' +const xsdTrue = $rdf.literal('true', xsd.boolean) + interface UpdateProjectCommand { resource: GraphPointer store: ResourceStore @@ -23,7 +26,7 @@ export async function updateProject({ const project = await store.getResource(resource.term) project.rename(resource.out(rdfs.label).value) - project.updateIsHiddenCube(resource.out(cc.isHiddenCube).term) + project.isHiddenCube = xsdTrue.equals(resource.out(cc.isHiddenCube).term) const maintainer = project.updateMaintainer(resource.out(schema.maintainer).term) let currentCube: NamedNode diff --git a/apis/core/lib/domain/job/create.ts b/apis/core/lib/domain/job/create.ts index 02640c311..2b1a86283 100644 --- a/apis/core/lib/domain/job/create.ts +++ b/apis/core/lib/domain/job/create.ts @@ -76,7 +76,7 @@ export async function createPublishJob({ const metadata = await store.getResource(project.dataset) - const targetGraph = project.isHiddenCube ? $rdf.namedNode(organization.publishGraph.value + '/hidden') : organization.publishGraph + const targetGraph = project.isHiddenCube ? organization.hiddenGraph : organization.publishGraph const jobPointer = await store.createMember(jobCollection.term, id.job(jobCollection)) const job = Job.createPublish(jobPointer, { diff --git a/apis/core/test/domain/job/create.test.ts b/apis/core/test/domain/job/create.test.ts index 47b483e0e..2a22104bf 100644 --- a/apis/core/test/domain/job/create.test.ts +++ b/apis/core/test/domain/job/create.test.ts @@ -27,6 +27,7 @@ describe('domain/job/create', () => { maintainer: organization, cubeIdentifier: 'test-cube', dataset: $rdf.namedNode('myDataset'), + isHiddenCube: false, }) const tableCollection = namedNode('myTables') const csvMapping = namedNode('myCsvMapping') @@ -131,4 +132,30 @@ describe('domain/job/create', () => { await expect(promise).rejectedWith(DomainError) }) }) + + describe('createPublishJob for hiddenCube', () => { + let queries: Pick + + beforeEach(() => { + queries = { + getCubeTable: sinon.stub().resolves($rdf.namedNode('observations')), + } + + if (!organization.pointer.has(cc.publishGraph).value) { + organization.pointer.addOut(cc.publishGraph, $rdf.namedNode('publishGraph')) + } + project.isHiddenCube = true + }) + + it('creates a job resource', async () => { + // when + const job = await createPublishJob({ resource: jobCollection.term, store, queries }) + + // then + expect(job.has(rdf.type, cc.PublishJob).values.length).to.eq(1) + expect(job.out(cc.project).value).to.eq('myProject') + + expect(job.out(cc.publishGraph).term).to.deep.eq($rdf.namedNode('publishGraph/hidden')) + }) + }) }) diff --git a/packages/model/Organization.ts b/packages/model/Organization.ts index 89ef0195e..f83fa319e 100644 --- a/packages/model/Organization.ts +++ b/packages/model/Organization.ts @@ -1,4 +1,5 @@ import type { DatasetCore, NamedNode, Term } from '@rdfjs/types' +import $rdf from 'rdf-ext' import { Organization, OrganizationMixin as SchemaOrganizationMixin } from '@rdfine/schema' import { Constructor, namespace, property, ResourceIdentifier } from '@tpluscode/rdfine' import { cc } from '@cube-creator/core/namespace' @@ -13,6 +14,7 @@ interface CreateIdentifier { interface OrganizationEx { publishGraph: NamedNode + readonly hiddenGraph: NamedNode namespace: NamedNode dataset?: NamedNode accessURL: NamedNode @@ -31,6 +33,10 @@ export function OrganizationMixin