diff --git a/Dockerfile b/Dockerfile index 3bd24cf..52200e2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,2 @@ -FROM local-js-template -#FROM semtech/mu-javascript-template:1.8.0 +FROM semtech/mu-javascript-template:1.8.0 LABEL maintainer="karel.kremer@redpencil.io" diff --git a/docker-compose.debug.yml b/docker-compose.debug.yml index 41a7b22..13e3dac 100644 --- a/docker-compose.debug.yml +++ b/docker-compose.debug.yml @@ -16,7 +16,7 @@ services: - ./:/app # ignore app/dist because this is where we map the built files to, otherwise we get an infinite loop of creating files (on mac) - /app/dist - - ./dist:/build/ + - ./dist:/usr/src/dist networks: - debug networks: diff --git a/services/custom-forms.ts b/services/custom-forms.ts index d8b3781..1979ed8 100644 --- a/services/custom-forms.ts +++ b/services/custom-forms.ts @@ -15,14 +15,14 @@ type FieldDescription = | { name: string; displayType: string; - libraryEntryId?: never; + libraryEntryUri?: never; order?: number; path?: string; } | { name: string; displayType?: never; - libraryEntryId: string; + libraryEntryUri: string; order?: number; path?: string; }; @@ -51,8 +51,8 @@ function verifyFieldDescription(description: FieldDescription) { const noDisplayType = !description.displayType || description.displayType.trim().length === 0; const noLibraryEntry = - !description.libraryEntryId || - description.libraryEntryId.trim().length === 0; + !description.libraryEntryUri || + description.libraryEntryUri.trim().length === 0; if (noDisplayType && noLibraryEntry) { throw new HttpError( 'Field description must have a display type or a library entry id', @@ -88,6 +88,10 @@ async function addFieldToFormExtension( formTtl: string, fieldDescription: FieldDescription, ) { + if (fieldDescription.libraryEntryUri) { + return addLibraryFieldToFormExtension(formUri, formTtl, fieldDescription); + } + const id = uuidv4(); const uri = `http://data.lblod.info/id/lmb/form-fields/${id}`; const name = fieldDescription.name; @@ -115,6 +119,67 @@ async function addFieldToFormExtension( return { id, uri }; } +async function addLibraryFieldToFormExtension( + formUri: string, + formTtl: string, + fieldDescription: FieldDescription, +) { + const id = uuidv4(); + const uri = `http://data.lblod.info/id/lmb/form-fields/${id}`; + const fieldGroupUri = await fetchGroupFromFormTtl(formTtl); + + const libraryEntryUri = await verifyLibraryEntryUri( + fieldDescription.libraryEntryUri, + ); + if (!libraryEntryUri) { + throw new HttpError('Library entry not found', 404); + } + + await update(` + PREFIX form: + PREFIX mu: + PREFIX ext: + PREFIX sh: + PREFIX prov: + + INSERT { + ${sparqlEscapeUri(uri)} a form:Field; + ext:extendsGroup ${sparqlEscapeUri(fieldGroupUri)} ; + sh:name ${sparqlEscapeString(fieldDescription.name)} ; + prov:wasDerivedFrom ${sparqlEscapeUri(libraryEntryUri)} ; + form:displayType ?displayType ; + sh:order ${sparqlEscapeInt(99999)} ; + sh:path ?path ; + mu:uuid ${sparqlEscapeString(id)} . + ${sparqlEscapeUri(formUri)} form:includes ${sparqlEscapeUri(uri)} . + } WHERE { + ${sparqlEscapeUri(libraryEntryUri)} a ext:FormLibraryEntry ; + sh:path ?path ; + form:displayType ?displayType . + } + `); + return { id, uri }; +} + +async function verifyLibraryEntryUri(libraryEntryUri: string) { + const result = await query(` + PREFIX ext: + PREFIX mu: + PREFIX sh: + PREFIX form: + SELECT ?libraryEntry + WHERE { + VALUES ?libraryEntry { + ${sparqlEscapeUri(libraryEntryUri)} + } + ?libraryEntry a ext:FormLibraryEntry ; + form:displayType ?type ; + mu:uuid ?uuid ; + sh:path ?path . + }`); + return result.results.bindings[0]?.libraryEntry?.value; +} + async function fetchGroupFromFormTtl(formTtl: string) { const store = await ttlToStore(formTtl); const engine = new QueryEngine();