From b9db92b20a2fdb62ff81699d668a1e7bde35e262 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Fri, 20 Dec 2024 12:16:24 +0100 Subject: [PATCH 01/15] feat(ui): dimensions search form --- .../shared-dimensions/bootstrap/entrypoint.ts | 2 +- apis/shared-dimensions/bootstrap/shapes.ts | 5 + apis/shared-dimensions/hydra/index.ttl | 15 +- .../lib/domain/shared-dimensions.ts | 10 +- .../lib/handlers/shared-dimensions.ts | 23 ++- apis/shared-dimensions/lib/namespace.ts | 1 + apis/shared-dimensions/lib/shapeToQuery.ts | 8 +- .../lib/shapes/dimensions-query-shape.ttl | 16 ++ apis/shared-dimensions/lib/shapes/index.ts | 1 + .../lib/shapes/shared-dimension.ts | 22 +++ apis/shared-dimensions/lib/store/index.ts | 5 +- apis/shared-dimensions/package.json | 2 +- fuseki/shared-dimensions.trig | 1 + patches/sparql-http-client+2.4.0.patch | 145 ++++++++++++++++++ ui/src/api/mixins/SharedDimension.ts | 4 - ui/src/forms/editors/index.ts | 2 +- ui/src/store/modules/projects.ts | 6 +- ui/src/store/modules/sharedDimensions.ts | 19 ++- ui/src/store/serializers.ts | 2 +- ui/src/views/SharedDimensions.vue | 58 ++++--- yarn.lock | 96 ++++++------ 21 files changed, 340 insertions(+), 103 deletions(-) create mode 100644 patches/sparql-http-client+2.4.0.patch diff --git a/apis/shared-dimensions/bootstrap/entrypoint.ts b/apis/shared-dimensions/bootstrap/entrypoint.ts index 17574ebfa..0dc6152e3 100644 --- a/apis/shared-dimensions/bootstrap/entrypoint.ts +++ b/apis/shared-dimensions/bootstrap/entrypoint.ts @@ -5,5 +5,5 @@ import type { BootstrappedResourceFactory } from './index' export const entrypoint = (ptr: BootstrappedResourceFactory, ns: NamespaceBuilder) => ptr('').addOut(rdf.type, [hydra.Resource, md.Entrypoint]) - .addOut(md.sharedDimensions, ns('_term-sets?pageSize=1000')) + .addOut(md.sharedDimensions, ns('_term-sets?pageSize=20')) .addOut(md.hierarchies, ns('_hierarchies')) diff --git a/apis/shared-dimensions/bootstrap/shapes.ts b/apis/shared-dimensions/bootstrap/shapes.ts index 3fa87f2dc..5ee823237 100644 --- a/apis/shared-dimensions/bootstrap/shapes.ts +++ b/apis/shared-dimensions/bootstrap/shapes.ts @@ -11,6 +11,10 @@ const SharedDimensionUpdate = clownface({ dataset: $rdf.dataset() }) .namedNode(shape('shape/shared-dimension-update')) .addOut(rdf.type, sh.NodeShape) +const SharedDimensionSearch = clownface({ dataset: $rdf.dataset() }) + .namedNode(shape('shape/shared-dimension-search')) + .addOut(rdf.type, sh.NodeShape) + const SharedDimensionTermCreate = clownface({ dataset: $rdf.dataset() }) .namedNode(shape('shape/shared-dimension-term-create')) .addOut(rdf.type, sh.NodeShape) @@ -30,6 +34,7 @@ const HierarchyCreate = clownface({ dataset: $rdf.dataset() }) export default [ SharedDimensionCreate, SharedDimensionUpdate, + SharedDimensionSearch, SharedDimensionTermCreate, SharedDimensionTermUpdate, Hierarchy, diff --git a/apis/shared-dimensions/hydra/index.ttl b/apis/shared-dimensions/hydra/index.ttl index d55331b2a..d7e2c69fd 100644 --- a/apis/shared-dimensions/hydra/index.ttl +++ b/apis/shared-dimensions/hydra/index.ttl @@ -1,3 +1,4 @@ +PREFIX owl: BASE @prefix rdfs: . @prefix schema: . @@ -41,8 +42,9 @@ md:SharedDimensions rdfs:subClassOf hydra:Collection ; hydra:supportedOperation [ - a hydra:Operation ; + a hydra:Operation, schema:DownloadAction ; hydra:method "GET" ; + hydra:expects ; code:implementedBy [ a code:EcmaScript ; @@ -51,7 +53,7 @@ md:SharedDimensions hydra-box:variables [ a hydra:IriTemplate ; - hydra:template "/_term-sets{?q,pageSize,page}" ; + hydra:template "/_term-sets{?q,pageSize,page,includeDeprecated}" ; hydra:mapping [ a hydra:IriTemplateMapping ; @@ -67,6 +69,11 @@ md:SharedDimensions a hydra:IriTemplateMapping ; hydra:property hydra:pageIndex ; hydra:variable "page" ; + ], + [ + a hydra:IriTemplateMapping ; + hydra:property owl:deprecated ; + hydra:variable "includeDeprecated" ; ] ; ] ; ], [ @@ -85,6 +92,7 @@ md:SharedDimensions a sh:NodeShape, sh:Shape . a sh:NodeShape, sh:Shape . + a sh:NodeShape, sh:Shape . md:Hierarchies a hydra:Class ; @@ -320,6 +328,3 @@ md:SharedDimensionTerm ] ; ] ; . - - a sh:Shape . - a sh:Shape . diff --git a/apis/shared-dimensions/lib/domain/shared-dimensions.ts b/apis/shared-dimensions/lib/domain/shared-dimensions.ts index 306afb34b..786f73566 100644 --- a/apis/shared-dimensions/lib/domain/shared-dimensions.ts +++ b/apis/shared-dimensions/lib/domain/shared-dimensions.ts @@ -1,5 +1,5 @@ import path from 'path' -import type { Quad, Stream, Term } from '@rdfjs/types' +import type { Quad, Stream, Term, Literal } from '@rdfjs/types' import { hydra, rdf, schema, sh } from '@tpluscode/rdf-ns-builders' import $rdf from 'rdf-ext' import { toRdf } from 'rdf-literal' @@ -17,9 +17,10 @@ interface GetSharedDimensions { freetextQuery?: string limit?: number offset?: number + includeDeprecated?: Literal } -export async function getSharedDimensions(client: StreamClient, { freetextQuery = '', limit = 10, offset = 0 }: GetSharedDimensions = {}): Promise { +export async function getSharedDimensions(client: StreamClient, { freetextQuery = '', limit = 10, offset = 0, includeDeprecated }: GetSharedDimensions = {}): Promise { const { constructQuery } = await shapeToQuery() const shape = await loadShape('dimensions-query-shape') @@ -30,11 +31,12 @@ export async function getSharedDimensions(client: StreamClient, { freetextQuery limit, offset, freetextQuery, + includeDeprecated, orderBy: schema.name, })) await rewriteTemplates(shape, variables) - const dataset = await $rdf.dataset().import(await constructQuery(shape).execute(client)) + const dataset = await $rdf.dataset().import(await client.query.construct(constructQuery(shape))) clownface({ dataset }) .has(rdf.type, schema.DefinedTermSet) .forEach(termSet => { @@ -86,7 +88,7 @@ export async function getSharedTerms({ s } const { constructQuery } = await shapeToQuery() - return constructQuery(shape).execute(client, { + return client.query.construct(constructQuery(shape), { operation: 'postDirect', }) as any } diff --git a/apis/shared-dimensions/lib/handlers/shared-dimensions.ts b/apis/shared-dimensions/lib/handlers/shared-dimensions.ts index 00047987f..1b09a4325 100644 --- a/apis/shared-dimensions/lib/handlers/shared-dimensions.ts +++ b/apis/shared-dimensions/lib/handlers/shared-dimensions.ts @@ -1,12 +1,12 @@ import type { Term } from '@rdfjs/types' -import { hydra, oa, schema } from '@tpluscode/rdf-ns-builders' +import { hydra, oa, owl, schema, xsd } from '@tpluscode/rdf-ns-builders' import { asyncMiddleware } from 'middleware-async' import { protectedResource } from '@hydrofoil/labyrinth/resource' import { Enrichment } from '@hydrofoil/labyrinth/lib/middleware/preprocessResource' import httpError from 'http-errors' import clownface, { GraphPointer } from 'clownface' import $rdf from 'rdf-ext' -import { md } from '@cube-creator/core/namespace' +import * as ns from '@cube-creator/core/namespace' import conditional from 'express-conditional-middleware' import { isMultipart } from '@cube-creator/express/multipart' import { shaclValidate } from '../middleware/shacl' @@ -29,19 +29,26 @@ export const get = asyncMiddleware(async (req, res, next) => { const offset = (page - 1) * pageSize const queryParams = { freetextQuery: query.has(hydra.freetextQuery).out(hydra.freetextQuery).value, - validThrough: query.has(md.onlyValidTerms, query.literal(true)).terms.length ? new Date() : undefined, + validThrough: query.has(ns.md.onlyValidTerms, query.literal(true)).terms.length ? new Date() : undefined, limit: pageSize, offset, + includeDeprecated: $rdf.literal(query.has(owl.deprecated).out(owl.deprecated).value || 'false', xsd.boolean), } const collection = getCollection({ view: $rdf.namedNode(req.absoluteUrl()), memberQuads: await getSharedDimensions(streamClient, queryParams), - collectionType: md.SharedDimensions, + collectionType: ns.md.SharedDimensions, memberType: schema.DefinedTermSet, collection: req.hydra.resource.term, }) + collection.addOut(ns.query.templateMappings, templateMappings => { + for (const { predicate, object } of query.dataset) { + templateMappings.addOut(predicate, object) + } + }) + return res.dataset(collection.dataset) }) @@ -83,7 +90,7 @@ export const getTerms = asyncMiddleware(async (req, res, next) => { const queryParams = { sharedDimensions: sharedDimensions.map(rewriteTerm), freetextQuery: query.has(hydra.freetextQuery).out(hydra.freetextQuery).value, - validThrough: query.has(md.onlyValidTerms, query.literal(true)).terms.length ? new Date() : undefined, + validThrough: query.has(ns.md.onlyValidTerms, query.literal(true)).terms.length ? new Date() : undefined, limit: pageSize, offset, } @@ -91,7 +98,7 @@ export const getTerms = asyncMiddleware(async (req, res, next) => { const collection = getCollection({ memberQuads: await getSharedTerms(queryParams, parsingClient), memberType: schema.DefinedTerm, - collectionType: md.SharedDimensionTerms, + collectionType: ns.md.SharedDimensionTerms, collection: termsCollectionId(sharedDimensions, queryParams.freetextQuery), }) @@ -119,9 +126,9 @@ const postDirect = protectedResource(shaclValidate, asyncMiddleware(async (req, export const post = conditional(isMultipart, postImportedDimension, postDirect) export const injectTermsLink: Enrichment = async (req, pointer) => { - pointer.deleteOut(md.terms).addOut(md.terms, termsCollectionId([pointer.term])) + pointer.deleteOut(ns.md.terms).addOut(ns.md.terms, termsCollectionId([pointer.term])) } export const injectExportLink: Enrichment = async (req, pointer) => { - pointer.deleteOut(md.export).addOut(md.export, pointer.namedNode(`${env.MANAGED_DIMENSIONS_BASE}dimension/_export?dimension=${pointer.value}`)) + pointer.deleteOut(ns.md.export).addOut(ns.md.export, pointer.namedNode(`${env.MANAGED_DIMENSIONS_BASE}dimension/_export?dimension=${pointer.value}`)) } diff --git a/apis/shared-dimensions/lib/namespace.ts b/apis/shared-dimensions/lib/namespace.ts index f17afaf01..8411e002d 100644 --- a/apis/shared-dimensions/lib/namespace.ts +++ b/apis/shared-dimensions/lib/namespace.ts @@ -3,6 +3,7 @@ import env from './env' type Shapes = 'shape/shared-dimension-create' | 'shape/shared-dimension-update' +| 'shape/shared-dimension-search' | 'shape/shared-dimension-term-create' | 'shape/shared-dimension-term-update' | 'shape/hierarchy-create' diff --git a/apis/shared-dimensions/lib/shapeToQuery.ts b/apis/shared-dimensions/lib/shapeToQuery.ts index 9a8bc7dc1..d63103eee 100644 --- a/apis/shared-dimensions/lib/shapeToQuery.ts +++ b/apis/shared-dimensions/lib/shapeToQuery.ts @@ -2,7 +2,7 @@ import onetime from 'onetime' import { md } from '@cube-creator/core/namespace' import { AnyPointer, GraphPointer } from 'clownface' import { isGraphPointer } from 'is-graph-pointer' -import { hydra } from '@tpluscode/rdf-ns-builders' +import { hydra, sh } from '@tpluscode/rdf-ns-builders' import { Parameters, PropertyShape } from '@hydrofoil/shape-to-query/model/constraint/ConstraintComponent' import evalTemplateLiteral from 'rdf-loader-code/evalTemplateLiteral.js' import namespace from '@rdfjs/namespace' @@ -58,11 +58,13 @@ export async function rewriteTemplates(shape: AnyPointer, variables: Map { shape.dataset.delete(quad) - shape.dataset.add($rdf.quad(quad.subject, quad.predicate, value, quad.graph)) + if (value) { + shape.dataset.add($rdf.quad(quad.subject, quad.predicate, value, quad.graph)) + } }) templateNode.deleteOut() diff --git a/apis/shared-dimensions/lib/shapes/dimensions-query-shape.ttl b/apis/shared-dimensions/lib/shapes/dimensions-query-shape.ttl index bdefe3bc9..23b07117d 100644 --- a/apis/shared-dimensions/lib/shapes/dimensions-query-shape.ttl +++ b/apis/shared-dimensions/lib/shapes/dimensions-query-shape.ttl @@ -41,6 +41,15 @@ prefix md: sh:path rdf:type ; sh:hasValue schema:DefinedTermSet, meta:SharedDimension ; ] ; + sh:expression + [ + sh:deactivated [ s2q:variable "includeDeprecated" ; sh:defaultValue false ] ; + sparql:or + ( + [ sparql:not ( [ sparql:bound ( _:validThrough ) ] ) ] + [ sparql:gt ( _:validThrough [ sparql:now () ] ) ] + ) ; + ] ; ] ; ] ; ] ; @@ -101,3 +110,10 @@ prefix md: ] ] ; ] . + +_:validThrough + s2q:optional + [ + sh:path schema:validThrough ; + ] ; +. diff --git a/apis/shared-dimensions/lib/shapes/index.ts b/apis/shared-dimensions/lib/shapes/index.ts index 32e8e6bfc..dc16266ce 100644 --- a/apis/shared-dimensions/lib/shapes/index.ts +++ b/apis/shared-dimensions/lib/shapes/index.ts @@ -45,6 +45,7 @@ function entry(id: NamedNode, init: (graph: AnyPointer) => Initializer([ entry(shape['shape/shared-dimension-create'], sharedDimension.create), entry(shape['shape/shared-dimension-update'], sharedDimension.update), + entry(shape['shape/shared-dimension-search'], sharedDimension.search), entry(shape['shape/shared-dimension-term-create'], dimensionTerm.create), entry(shape['shape/shared-dimension-term-update'], dimensionTerm.update), entry(shape['shape/hierarchy-create'], hierarchy()), diff --git a/apis/shared-dimensions/lib/shapes/shared-dimension.ts b/apis/shared-dimensions/lib/shapes/shared-dimension.ts index 4e99dc4db..75d22363c 100644 --- a/apis/shared-dimensions/lib/shapes/shared-dimension.ts +++ b/apis/shared-dimensions/lib/shapes/shared-dimension.ts @@ -9,6 +9,7 @@ import { editor, iso6391, md, meta, sh1 } from '@cube-creator/core/namespace' import { fromPointer as nodeShape } from '@rdfine/shacl/lib/NodeShape' import { fromPointer as propertyGroup } from '@rdfine/shacl/lib/PropertyGroup' import { fromPointer as resource } from '@rdfine/rdfs/lib/Resource' +import { owl } from '@tpluscode/rdf-ns-builders' const defaultGroup = $rdf.namedNode('#default-group') const datatypeUri = [xsd.anyURI, ['URI']] @@ -387,3 +388,24 @@ export const update = (): Initializer => ({ }, ], }) + +export const search = (): Initializer => ({ + property: [ + { + path: hydra.freetextQuery, + name: 'Name', + minCount: 1, + maxCount: 1, + order: 1, + }, + { + path: owl.deprecated, + name: 'Show deprecated', + minCount: 1, + maxCount: 1, + defaultValue: false, + datatype: xsd.boolean, + order: 2, + }, + ], +}) diff --git a/apis/shared-dimensions/lib/store/index.ts b/apis/shared-dimensions/lib/store/index.ts index c1b334846..9bd5e75ac 100644 --- a/apis/shared-dimensions/lib/store/index.ts +++ b/apis/shared-dimensions/lib/store/index.ts @@ -30,10 +30,11 @@ export default class implements SharedDimensionsStore { const { constructQuery } = await shapeToQuery() const query = constructQuery(shape, { focusNode: term, - }).FROM(this.graph) + }) - const quads = await query.execute(this.client, { + const quads = await this.client.query.construct(query, { operation: 'postDirect', + defaultGraphUri: [this.graph], }) return clownface({ dataset: $rdf.dataset(quads), diff --git a/apis/shared-dimensions/package.json b/apis/shared-dimensions/package.json index 4ddaf1a9b..ebee17398 100644 --- a/apis/shared-dimensions/package.json +++ b/apis/shared-dimensions/package.json @@ -7,7 +7,7 @@ "@cube-creator/core": "1.0.0", "@cube-creator/express": "0.0.0", "@hydrofoil/labyrinth": "^0.4.2", - "@hydrofoil/shape-to-query": "^0.12", + "@hydrofoil/shape-to-query": "^0.13.2", "@rdfine/hydra": "^0.8.2", "@rdfine/rdfs": "^0.6.4", "@rdfine/schema": "^0.6.3", diff --git a/fuseki/shared-dimensions.trig b/fuseki/shared-dimensions.trig index 8fe521e22..519fbcb1d 100644 --- a/fuseki/shared-dimensions.trig +++ b/fuseki/shared-dimensions.trig @@ -114,6 +114,7 @@ graph { a schema:DefinedTermSet, meta:SharedDimension ; schema:validFrom "2021-01-20T23:59:59Z"^^xsd:dateTime ; + schema:validThrough "2021-04-20T23:59:59Z"^^xsd:dateTime ; schema:name "Colors"@en, "Farben"@de, "I colori"@it, "Les couleurs"@fr ; . diff --git a/patches/sparql-http-client+2.4.0.patch b/patches/sparql-http-client+2.4.0.patch new file mode 100644 index 000000000..182e0e995 --- /dev/null +++ b/patches/sparql-http-client+2.4.0.patch @@ -0,0 +1,145 @@ +diff --git a/node_modules/sparql-http-client/Endpoint.js b/node_modules/sparql-http-client/Endpoint.js +index 766b417..a9ee851 100644 +--- a/node_modules/sparql-http-client/Endpoint.js ++++ b/node_modules/sparql-http-client/Endpoint.js +@@ -36,7 +36,7 @@ class Endpoint { + * @param {boolean} [options.update=false] if true, performs a SPARQL Update + * @return {Promise} + */ +- async get (query, { headers, update = false } = {}) { ++ async get (query, { headers, update = false, defaultGraphUri = [], namedGraphUri = [] } = {}) { + let url = null + + if (!update) { +@@ -47,6 +47,13 @@ class Endpoint { + url.searchParams.append('update', query) + } + ++ for (const uri of defaultGraphUri) { ++ url.searchParams.append('default-graph-uri', uri) ++ } ++ for (const uri of namedGraphUri) { ++ url.searchParams.append('named-graph-uri', uri) ++ } ++ + return this.fetch(url.toString().replace(/\+/g, '%20'), { + method: 'GET', + headers: this.mergeHeaders(headers) +@@ -61,7 +68,7 @@ class Endpoint { + * @param {boolean} [options.update=false] if true, performs a SPARQL Update + * @return {Promise} + */ +- async postDirect (query, { headers, update = false } = {}) { ++ async postDirect (query, { headers, update = false, defaultGraphUri = [], namedGraphUri = [] } = {}) { + let url = null + + if (!update) { +@@ -76,6 +83,13 @@ class Endpoint { + headers.set('content-type', 'application/sparql-query; charset=utf-8') + } + ++ for (const uri of defaultGraphUri) { ++ url.searchParams.append('default-graph-uri', uri) ++ } ++ for (const uri of namedGraphUri) { ++ url.searchParams.append('named-graph-uri', uri) ++ } ++ + return this.fetch(url, { + method: 'POST', + headers, +@@ -91,7 +105,7 @@ class Endpoint { + * @param {boolean} [options.update=false] if true, performs a SPARQL Update + * @return {Promise} + */ +- async postUrlencoded (query, { headers, update = false } = {}) { ++ async postUrlencoded (query, { headers, update = false, defaultGraphUri = [], namedGraphUri = [] } = {}) { + let url = null + let body = null + +@@ -103,6 +117,13 @@ class Endpoint { + body = 'update=' + encodeURIComponent(query) + } + ++ for (const uri of defaultGraphUri) { ++ url.searchParams.append('default-graph-uri', uri) ++ } ++ for (const uri of namedGraphUri) { ++ url.searchParams.append('named-graph-uri', uri) ++ } ++ + headers = this.mergeHeaders(headers) + + if (!headers.has('content-type')) { +diff --git a/node_modules/sparql-http-client/RawQuery.js b/node_modules/sparql-http-client/RawQuery.js +index 5aa6bfc..1538933 100644 +--- a/node_modules/sparql-http-client/RawQuery.js ++++ b/node_modules/sparql-http-client/RawQuery.js +@@ -21,14 +21,14 @@ class RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async ask (query, { headers, operation = 'get' } = {}) { ++ async ask (query, { headers, operation = 'get', ...options } = {}) { + headers = this.endpoint.mergeHeaders(headers) + + if (!headers.has('accept')) { + headers.set('accept', 'application/sparql-results+json') + } + +- return this.endpoint[operation](query, { headers }) ++ return this.endpoint[operation](query, { headers, ...options }) + } + + /** +@@ -41,14 +41,14 @@ class RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async construct (query, { headers, operation = 'get' } = {}) { ++ async construct (query, { headers, operation = 'get', ...options } = {}) { + headers = new this.endpoint.fetch.Headers(headers) + + if (!headers.has('accept')) { + headers.set('accept', 'application/n-triples') + } + +- return this.endpoint[operation](query, { headers }) ++ return this.endpoint[operation](query, { headers, ...options }) + } + + /** +@@ -61,14 +61,14 @@ class RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async select (query, { headers, operation = 'get' } = {}) { ++ async select (query, { headers, operation = 'get', ...options } = {}) { + headers = this.endpoint.mergeHeaders(headers) + + if (!headers.has('accept')) { + headers.set('accept', 'application/sparql-results+json') + } + +- return this.endpoint[operation](query, { headers }) ++ return this.endpoint[operation](query, { headers, ...options }) + } + + /** +@@ -81,14 +81,14 @@ class RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='postUrlencoded'] + * @return {Promise} + */ +- async update (query, { headers, operation = 'postUrlencoded' } = {}) { ++ async update (query, { headers, operation = 'postUrlencoded', ...options } = {}) { + headers = new this.endpoint.fetch.Headers(headers) + + if (!headers.has('accept')) { + headers.set('accept', '*/*') + } + +- return this.endpoint[operation](query, { headers, update: true }) ++ return this.endpoint[operation](query, { headers, update: true, ...options }) + } + } + diff --git a/ui/src/api/mixins/SharedDimension.ts b/ui/src/api/mixins/SharedDimension.ts index 7e443d0fd..d059988b5 100644 --- a/ui/src/api/mixins/SharedDimension.ts +++ b/ui/src/api/mixins/SharedDimension.ts @@ -22,10 +22,6 @@ export default function mixin (base: Base) { @property.literal({ path: schema.validThrough, type: Date }) validThrough?: Date - - get deprecated () { - return this.validThrough && this.validThrough <= new Date() - } } return Impl diff --git a/ui/src/forms/editors/index.ts b/ui/src/forms/editors/index.ts index 36840d0c6..593fda640 100644 --- a/ui/src/forms/editors/index.ts +++ b/ui/src/forms/editors/index.ts @@ -90,7 +90,7 @@ export const checkBox: Lazy = { await import('./CheckboxEditor.vue').then(createCustomElement('cc-checkbox')) return ({ value }, { update }) => { - const booleanValue = trueTerm.equals(value.object?.term) + const booleanValue = value.object?.value === 'true' return html`` } }, diff --git a/ui/src/store/modules/projects.ts b/ui/src/store/modules/projects.ts index 70bbd56c1..fce0eaee1 100644 --- a/ui/src/store/modules/projects.ts +++ b/ui/src/store/modules/projects.ts @@ -1,9 +1,9 @@ import { ActionTree, MutationTree, GetterTree } from 'vuex' -import { api, rootURL } from '@/api' +import { api } from '@/api' import { RootState } from '../types' import * as ns from '@cube-creator/core/namespace' import { Project, ProjectsCollection } from '@cube-creator/model' -import { serializeProjectDetails, serializeProjectsCollection } from '../serializers' +import { serializeProjectDetails, serializeCollection } from '../serializers' import { RdfResource } from 'alcaeus' export interface ProjectsState { @@ -53,7 +53,7 @@ const actions: ActionTree = { const mutations: MutationTree = { storeCollection (state, collection) { - state.collection = collection ? serializeProjectsCollection(collection) : null + state.collection = collection ? serializeCollection(collection) : null }, storeProjectDetails (state, { project, details }) { diff --git a/ui/src/store/modules/sharedDimensions.ts b/ui/src/store/modules/sharedDimensions.ts index 5025cb615..210b3e31e 100644 --- a/ui/src/store/modules/sharedDimensions.ts +++ b/ui/src/store/modules/sharedDimensions.ts @@ -3,6 +3,7 @@ import { api } from '@/api' import { RootState } from '../types' import { cc, md } from '@cube-creator/core/namespace' import { Collection, RdfResource } from 'alcaeus' +import { serializeCollection } from '@/store/serializers' export interface SharedDimensionsState { entrypoint: null | RdfResource @@ -33,13 +34,25 @@ const actions: ActionTree = { return entrypoint }, - async fetchCollection (context) { + async fetchCollection (context, query) { const entrypoint = context.state.entrypoint const collectionURI = entrypoint?.get(md.sharedDimensions)?.id + let params = new URLSearchParams() + if (query) { + params = new URLSearchParams(query) + } else if (location.search) { + params = new URLSearchParams(location.search) + } + if (!collectionURI) throw new Error('Missing shared dimensions collection in entrypoint') - const collection = await api.fetchResource(collectionURI.value) + const collectionUrl = new URL(collectionURI.value) + for (const [key, value] of params) { + collectionUrl.searchParams.set(key, value) + } + + const collection = await api.fetchResource(collectionUrl.toString()) context.commit('storeCollection', collection) }, } @@ -50,7 +63,7 @@ const mutations: MutationTree = { }, storeCollection (state, collection) { - state.collection = collection + state.collection = collection ? serializeCollection(collection) : null }, } diff --git a/ui/src/store/serializers.ts b/ui/src/store/serializers.ts index 6765e9be2..689426caa 100644 --- a/ui/src/store/serializers.ts +++ b/ui/src/store/serializers.ts @@ -24,7 +24,7 @@ import { clone } from '@/store/searchParams' export const displayLanguage = ['en', 'de', 'fr', ''] -export function serializeProjectsCollection (collection: ProjectsCollection): ProjectsCollection { +export function serializeCollection (collection: ProjectsCollection): ProjectsCollection { return Object.freeze({ ...serializeResource(collection), searchParams: clone(collection.pointer), diff --git a/ui/src/views/SharedDimensions.vue b/ui/src/views/SharedDimensions.vue index 1aa894083..527b7be81 100644 --- a/ui/src/views/SharedDimensions.vue +++ b/ui/src/views/SharedDimensions.vue @@ -22,13 +22,18 @@
- - show deprecated - +
diff --git a/yarn.lock b/yarn.lock index 5e1155390..9bf8f95dc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1566,10 +1566,10 @@ rdf-loaders-registry "^0.2.0" sparql-http-client "^2.2.2" -"@hydrofoil/shape-to-query@^0.13.2": - version "0.13.2" - resolved "https://registry.yarnpkg.com/@hydrofoil/shape-to-query/-/shape-to-query-0.13.2.tgz#475939fe9ec5a3c0bd316f6a32bfaf4caf32cf83" - integrity sha512-7w1wPexW0XDiF7WtRkQtqnZTcJvhYKW+2rNIbl9cqZqto3A/8aKT+Hm4OKM3WTOgmGDpyDwbtE/itu5LkjzoEA== +"@hydrofoil/shape-to-query@^0.13.4": + version "0.13.4" + resolved "https://registry.yarnpkg.com/@hydrofoil/shape-to-query/-/shape-to-query-0.13.4.tgz#61ac73a33a1c8a34f6652a284ec7e2fdf5101b12" + integrity sha512-Q9GDAacePZZQkwnOxOD43BlkWBNDKr+VR05l3B8Q99D9gKYZ5AeF8kNDdH3za9LzES9Hc3hs/g0R8sM0Rz8WiQ== dependencies: "@hydrofoil/sparql-processor" "^0.1.2" "@tpluscode/rdf-ns-builders" ">=3.0.2" From e73ff6a708232fa701e549cd5aa3e1029cdcbcb8 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 09:10:37 +0100 Subject: [PATCH 04/15] refactor: changed interface --- .../lib/domain/hierarchies.ts | 15 ++++++--- .../lib/handlers/hierarchies.ts | 2 +- .../lib/handlers/hierarchy.ts | 2 +- .../lib/domain/managed-dimensions.test.ts | 31 +++++++++++++------ 4 files changed, 34 insertions(+), 16 deletions(-) diff --git a/apis/shared-dimensions/lib/domain/hierarchies.ts b/apis/shared-dimensions/lib/domain/hierarchies.ts index 710cc568b..af73d2126 100644 --- a/apis/shared-dimensions/lib/domain/hierarchies.ts +++ b/apis/shared-dimensions/lib/domain/hierarchies.ts @@ -1,4 +1,4 @@ -import type { NamedNode } from '@rdfjs/types' +import type { NamedNode, Quad } from '@rdfjs/types' import { CONSTRUCT, SELECT } from '@tpluscode/sparql-builder' import { md, meta } from '@cube-creator/core/namespace' import clownface, { GraphPointer } from 'clownface' @@ -7,9 +7,11 @@ import httpError from 'http-errors' import $rdf from 'rdf-ext' import slugify from 'slugify' import { DomainError } from '@cube-creator/api-errors' +import { ParsingClient } from 'sparql-http-client/ParsingClient' import { SharedDimensionsStore } from '../store' import env from '../env' import { textSearch } from '../query' +import { CollectionData } from '../handlers/collection' import { newId, replace } from './resource' interface GetHierarchies { @@ -18,7 +20,7 @@ interface GetHierarchies { offset: number } -export function getHierarchies({ freetextQuery, limit, offset }: GetHierarchies) { +export async function getHierarchies({ freetextQuery, limit, offset }: GetHierarchies, client: ParsingClient): Promise>> { const hierarchy = $rdf.variable('hierarchy') const name = $rdf.variable('name') @@ -35,10 +37,11 @@ export function getHierarchies({ freetextQuery, limit, offset }: GetHierarchies) .ORDER().BY(name) } - return CONSTRUCT` + return { + members: await CONSTRUCT` ?proxyUrl ?p ?o . ` - .WHERE` + .WHERE` { ${select} } @@ -46,7 +49,9 @@ export function getHierarchies({ freetextQuery, limit, offset }: GetHierarchies) ${hierarchy} ?p ?o . BIND(IRI(CONCAT("${env.MANAGED_DIMENSIONS_API_BASE}", "dimension/_hierarchy/proxy?id=", ENCODE_FOR_URI(STR(${hierarchy})))) AS ?proxyUrl) - ` + `.execute(client.query), + totalItems: 0, + } } interface CreateHierarchy { diff --git a/apis/shared-dimensions/lib/handlers/hierarchies.ts b/apis/shared-dimensions/lib/handlers/hierarchies.ts index b689c8ad7..ec5ddb539 100644 --- a/apis/shared-dimensions/lib/handlers/hierarchies.ts +++ b/apis/shared-dimensions/lib/handlers/hierarchies.ts @@ -27,7 +27,7 @@ export const get = asyncMiddleware(async (req, res, next) => { offset, } const collection = await getCollection({ - memberQuads: await getHierarchies(queryParams).execute(parsingClient.query), + data: await getHierarchies(queryParams, parsingClient), collectionType: md.Hierarchies, memberType: md.Hierarchy, collection: req.hydra.resource.term, diff --git a/apis/shared-dimensions/lib/handlers/hierarchy.ts b/apis/shared-dimensions/lib/handlers/hierarchy.ts index 9605716d4..3e8d8d555 100644 --- a/apis/shared-dimensions/lib/handlers/hierarchy.ts +++ b/apis/shared-dimensions/lib/handlers/hierarchy.ts @@ -56,7 +56,7 @@ export const getExternal = asyncMiddleware(async (req, res) => { }) const hierarchy = clownface({ - dataset: $rdf.dataset(await query.execute(parsingClient)), + dataset: $rdf.dataset(await parsingClient.query.construct(query)), }).namedNode(url) ensureEndpoint(hierarchy) diff --git a/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts b/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts index d1c9c6b62..669aae75e 100644 --- a/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts +++ b/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts @@ -13,9 +13,12 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR describe('getSharedDimensions', () => { it('returns from all graphs', async () => { + // given + const collectionData = await getSharedDimensions(mdClients.streamClient) + // when const dataset = $rdf.dataset([ - ...await getSharedDimensions(mdClients.streamClient), + ...collectionData.members, ]) // then @@ -28,11 +31,14 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR }) it('returns filtered by name', async () => { + // given + const collectionData = await getSharedDimensions(mdClients.streamClient, { + freetextQuery: 'colors', + }) + // when const dataset = $rdf.dataset([ - ...await getSharedDimensions(mdClients.streamClient, { - freetextQuery: 'colors', - }), + ...collectionData.members, ]) // then @@ -51,10 +57,11 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR sharedDimensions: [$rdf.namedNode('http://example.com/dimension/colors')], freetextQuery: undefined, } + const collectionData = await getSharedTerms(search, mdClients.streamClient) // when const dataset = await $rdf.dataset() - .import(await getSharedTerms(search, mdClients.streamClient)) + .import(collectionData.members) // then expect(dataset.match(null, rdf.type, schema.DefinedTerm)) @@ -82,10 +89,11 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR sharedDimensions: [$rdf.namedNode('https://ld.admin.ch/cube/dimension/technologies')], freetextQuery: 'sparql', } + const collectionData = await getSharedTerms(search, mdClients.streamClient) // when const dataset = await $rdf.dataset() - .import(await getSharedTerms(search, mdClients.streamClient)) + .import(collectionData.members) // then expect(dataset.match(null, rdf.type, schema.DefinedTerm)) @@ -118,10 +126,11 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR freetextQuery: undefined, limit: 1, } + const collectionData = await getSharedTerms(search, mdClients.streamClient) // when const dataset = await $rdf.dataset() - .import(await getSharedTerms(search, mdClients.streamClient)) + .import(collectionData.members) // then expect(dataset.match(null, rdf.type, schema.DefinedTerm)) @@ -134,9 +143,11 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR sharedDimensions: [$rdf.namedNode('http://example.com/dimension/colors')], freetextQuery: 'r', } + const collectionData = await getSharedTerms(search, mdClients.streamClient) + // when const dataset = await $rdf.dataset() - .import(await getSharedTerms(search, mdClients.streamClient)) + .import(collectionData.members) // then const [term, ...more] = dataset.match(null, rdf.type, schema.DefinedTerm) @@ -151,9 +162,11 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR freetextQuery: undefined, validThrough: new Date(Date.parse('2021-04-15')), } + const collectionData = await getSharedTerms(search, mdClients.streamClient) + // when const dataset = await $rdf.dataset() - .import(await getSharedTerms(search, mdClients.streamClient)) + .import(collectionData.members) // then const terms = [...dataset.match(null, rdf.type, schema.DefinedTerm)].map(({ subject }) => subject) From 8b08425efc36b81a9c409a43da8d7f9d4ee8595c Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 09:30:33 +0100 Subject: [PATCH 05/15] fix: patch sparql client types --- apis/shared-dimensions/lib/store/index.ts | 2 +- patches/@types+sparql-http-client+2.2.8.patch | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) create mode 100644 patches/@types+sparql-http-client+2.2.8.patch diff --git a/apis/shared-dimensions/lib/store/index.ts b/apis/shared-dimensions/lib/store/index.ts index 9bd5e75ac..401d07f57 100644 --- a/apis/shared-dimensions/lib/store/index.ts +++ b/apis/shared-dimensions/lib/store/index.ts @@ -60,7 +60,7 @@ export default class implements SharedDimensionsStore { async delete(id: NamedNode): Promise { const shape = await this.getShape(id) - await (await this.deleteQuery(shape, id)).execute(this.client) + await this.client.query.update(await this.deleteQuery(shape, id)) } private async deleteQuery(shape: GraphPointer, focusNode: NamedNode) { diff --git a/patches/@types+sparql-http-client+2.2.8.patch b/patches/@types+sparql-http-client+2.2.8.patch new file mode 100644 index 000000000..f9a65a82c --- /dev/null +++ b/patches/@types+sparql-http-client+2.2.8.patch @@ -0,0 +1,12 @@ +diff --git a/node_modules/@types/sparql-http-client/StreamClient.d.ts b/node_modules/@types/sparql-http-client/StreamClient.d.ts +index e4e1e60..9d9e621 100755 +--- a/node_modules/@types/sparql-http-client/StreamClient.d.ts ++++ b/node_modules/@types/sparql-http-client/StreamClient.d.ts +@@ -13,6 +13,7 @@ declare namespace StreamClient { + interface QueryOptions { + headers?: HeadersInit | undefined; + operation?: 'get' | 'postUrlencoded' | 'postDirect' | undefined; ++ defaultGraphUri?: Array | undefined; + } + + interface QueryInit { From d6ccfe64ca6a7cb62e29ab9e73afc5ceae94cbb1 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 14:51:16 +0100 Subject: [PATCH 06/15] fix: update full text querying and totals --- .../lib/domain/shared-dimensions.ts | 8 +- .../lib/handlers/collection.ts | 9 +- apis/shared-dimensions/lib/shapeToQuery.ts | 87 ++++++++++++++----- apis/shared-dimensions/package.json | 2 +- yarn.lock | 79 ++++++++--------- 5 files changed, 113 insertions(+), 72 deletions(-) diff --git a/apis/shared-dimensions/lib/domain/shared-dimensions.ts b/apis/shared-dimensions/lib/domain/shared-dimensions.ts index 1a29248a1..69dba6b8a 100644 --- a/apis/shared-dimensions/lib/domain/shared-dimensions.ts +++ b/apis/shared-dimensions/lib/domain/shared-dimensions.ts @@ -98,9 +98,11 @@ export async function getSharedTerms({ s } const { constructQuery } = await shapeToQuery() - return client.query.construct(constructQuery(shape), { - operation: 'postDirect', - }) as any + return { + members: await client.query.construct(constructQuery(shape), { + operation: 'postDirect', + }) as any, + } } async function loadShape(shape: string, shapeType: NamedNode = sh.NodeShape) { diff --git a/apis/shared-dimensions/lib/handlers/collection.ts b/apis/shared-dimensions/lib/handlers/collection.ts index 6d1f4e619..a9028e0d2 100644 --- a/apis/shared-dimensions/lib/handlers/collection.ts +++ b/apis/shared-dimensions/lib/handlers/collection.ts @@ -5,7 +5,7 @@ import { hydra, rdf } from '@tpluscode/rdf-ns-builders' export interface CollectionData = Stream | Iterable> { members: M - totalItems: number + totalItems?: number } interface CollectionHandler { @@ -25,7 +25,12 @@ export function getCollection({ collection, view, data: { members: memberQuads, graph.node(collection) .addOut(rdf.type, [hydra.Collection, collectionType]) .addOut(hydra.member, members) - .addOut(hydra.totalItems, totalItems) + + if (totalItems) { + graph.node(collection).addOut(hydra.totalItems, totalItems) + } else { + graph.node(collection).addOut(hydra.totalItems, members.terms.length) + } if (view) { graph.node(view) diff --git a/apis/shared-dimensions/lib/shapeToQuery.ts b/apis/shared-dimensions/lib/shapeToQuery.ts index d63103eee..043be862d 100644 --- a/apis/shared-dimensions/lib/shapeToQuery.ts +++ b/apis/shared-dimensions/lib/shapeToQuery.ts @@ -1,14 +1,14 @@ import onetime from 'onetime' import { md } from '@cube-creator/core/namespace' -import { AnyPointer, GraphPointer } from 'clownface' +import clownface, { AnyPointer, GraphPointer } from 'clownface' import { isGraphPointer } from 'is-graph-pointer' import { hydra, sh } from '@tpluscode/rdf-ns-builders' import { Parameters, PropertyShape } from '@hydrofoil/shape-to-query/model/constraint/ConstraintComponent' import evalTemplateLiteral from 'rdf-loader-code/evalTemplateLiteral.js' import namespace from '@rdfjs/namespace' -import { sparql } from '@tpluscode/sparql-builder' import $rdf from 'rdf-ext' import type { Literal } from '@rdfjs/types' +import type { ServicePattern, GroupPattern } from 'sparqljs' import env from './env' /* @@ -21,7 +21,11 @@ const _importDynamic = new Function('modulePath', 'return import(modulePath)') export default async function shapeToQuery(): Promise> { await setup() - const { constructQuery, deleteQuery, s2q } = await _importDynamic('@hydrofoil/shape-to-query') + const { + constructQuery, + deleteQuery, + s2q, + } = await _importDynamic('@hydrofoil/shape-to-query') as typeof import('@hydrofoil/shape-to-query') return { constructQuery, @@ -76,9 +80,9 @@ const setup = onetime(async () => { }) async function defineConstraintComponents() { - const { default: ConstraintComponent } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/ConstraintComponent.js') - const { constraintComponents } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/index.js') - const { PatternConstraintComponent } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/pattern.js') + const { default: ConstraintComponent } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/ConstraintComponent.js') as typeof import('@hydrofoil/shape-to-query/model/constraint/ConstraintComponent.js') + const { constraintComponents } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/index.js') as typeof import('@hydrofoil/shape-to-query/model/constraint/index.js') + const { PatternConstraintComponent } = await _importDynamic('@hydrofoil/shape-to-query/model/constraint/pattern.js') as typeof import('@hydrofoil/shape-to-query/model/constraint/pattern.js') constraintComponents.set(md.FreeTextSearchConstraintComponent, class TextSearch extends ConstraintComponent { static match(pointer: GraphPointer) { @@ -101,7 +105,7 @@ async function defineConstraintComponents() { yield new TextSearch('fuseki', patternElement.pointer.value) break default: - yield new PatternConstraintComponent('^' + patternElement.pointer.value) + yield new PatternConstraintComponent(patternElement.pointer.term as Literal) } } } @@ -110,29 +114,66 @@ async function defineConstraintComponents() { super(md.FreeTextSearchConstraintComponent) } - buildPatterns({ focusNode, valueNode, propertyPath }: Parameters): any { + buildPropertyShapePatterns(args: Parameters) { if (this.vendor === 'stardog') { - const fts = namespace('tag:stardog:api:search:') - return sparql` - service ${fts.textMatch} { - [] ${fts.query} """${this.pattern + '*'}"""; - ${fts.result} ${valueNode} ; - } - ${focusNode} ${propertyPath} ${valueNode} . - ` + return [this.stardogServiceGroup(args)] } if (this.vendor === 'fuseki') { - return sparql` - ${focusNode} (${propertyPath} """${this.pattern + '*'}""") . - - # Second filtering to make sure the word starts with the given query - ${focusNode} ${propertyPath} ${valueNode} . - FILTER (REGEX(${valueNode}, "^${this.pattern}", "i")) - ` + return [this.fusekiPatterns(args)] } throw new Error('Unsupported vendor') } + + stardogServiceGroup({ focusNode, valueNode, propertyPath }: Parameters): ServicePattern { + if (!propertyPath || !('value' in propertyPath)) { + throw new Error('Property path must be a named node') + } + + const fts = namespace('tag:stardog:api:search:') + + const patterns = clownface({ dataset: $rdf.dataset() }) + .blankNode() + .addOut(fts.query, $rdf.literal(this.pattern + '*')) + .addOut(fts.result, valueNode) + .node(focusNode).addOut(propertyPath, valueNode) + + return { + type: 'service', + name: fts.textMatch, + silent: false, + patterns: [{ + type: 'bgp', + triples: [...patterns.dataset], + }], + } + } + + fusekiPatterns({ focusNode, valueNode, propertyPath }: Parameters): GroupPattern { + if (!propertyPath || !('value' in propertyPath)) { + throw new Error('Property path must be a named node') + } + + const patterns = clownface({ dataset: $rdf.dataset() }) + .node(focusNode) + .addList($rdf.namedNode('http://jena.apache.org/text#query'), [propertyPath, $rdf.literal(this.pattern + '*')]) + .addOut(propertyPath, valueNode) // Second filtering to make sure the word starts with the given query + + return { + type: 'group', + patterns: [{ + type: 'bgp', + triples: [...patterns.dataset], + }, { + type: 'filter', + expression: { + type: 'operation', + operator: 'regex', + args: [valueNode, $rdf.literal('^' + this.pattern), $rdf.literal('i')], + }, + }], + } + } }) } diff --git a/apis/shared-dimensions/package.json b/apis/shared-dimensions/package.json index 160f5172e..0db7eb461 100644 --- a/apis/shared-dimensions/package.json +++ b/apis/shared-dimensions/package.json @@ -7,7 +7,7 @@ "@cube-creator/core": "1.0.0", "@cube-creator/express": "0.0.0", "@hydrofoil/labyrinth": "^0.4.2", - "@hydrofoil/shape-to-query": "^0.13.4", + "@hydrofoil/shape-to-query": "^0.13.5", "@rdfine/hydra": "^0.8.2", "@rdfine/rdfs": "^0.6.4", "@rdfine/schema": "^0.6.3", diff --git a/yarn.lock b/yarn.lock index f3dc20a44..ae2848407 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1566,19 +1566,19 @@ rdf-loaders-registry "^0.2.0" sparql-http-client "^2.2.2" -"@hydrofoil/shape-to-query@^0.13.4": - version "0.13.4" - resolved "https://registry.yarnpkg.com/@hydrofoil/shape-to-query/-/shape-to-query-0.13.4.tgz#61ac73a33a1c8a34f6652a284ec7e2fdf5101b12" - integrity sha512-Q9GDAacePZZQkwnOxOD43BlkWBNDKr+VR05l3B8Q99D9gKYZ5AeF8kNDdH3za9LzES9Hc3hs/g0R8sM0Rz8WiQ== +"@hydrofoil/shape-to-query@^0.13.5": + version "0.13.5" + resolved "https://registry.yarnpkg.com/@hydrofoil/shape-to-query/-/shape-to-query-0.13.5.tgz#246ffcaaf51d1ee3f1f62162310c23a2ad28d7d9" + integrity sha512-bwjUzeOLEV48tldt+0pGH8y21MOTO9cw6A78boM9i+bpKR6UJqAZ6Rv8RmeGSY5GTIILfuelqP/kgOgvM0C6Xw== dependencies: - "@hydrofoil/sparql-processor" "^0.1.2" + "@hydrofoil/sparql-processor" "^0.1.3" "@tpluscode/rdf-ns-builders" ">=3.0.2" "@tpluscode/rdf-string" "^1.3.3" "@types/sparqljs" "^3.1.11" "@vocabulary/dash" "^1.0.4" "@vocabulary/dash-sparql" "^1.0.4" "@vocabulary/sh" "^1.1.5" - "@zazuko/env" "^2.2.0" + "@zazuko/env" "^2.4.2" "@zazuko/prefixes" ">=2" clownface-shacl-path "^2.2" is-graph-pointer "^2.0.0" @@ -1667,10 +1667,10 @@ concat-merge "^1.0.3" lit "^2.0.0" -"@hydrofoil/sparql-processor@^0.1.2": - version "0.1.2" - resolved "https://registry.yarnpkg.com/@hydrofoil/sparql-processor/-/sparql-processor-0.1.2.tgz#5241204d114c98322a67ffec86fb2398b216586c" - integrity sha512-GjzGkiIA9mjEN8SElcPSfbO43JCpf+tz+r7cErXsb8CtjbP5Lw+/V54jJtu4Y2T0tx5azzXlCwHJC244Svzt5A== +"@hydrofoil/sparql-processor@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@hydrofoil/sparql-processor/-/sparql-processor-0.1.3.tgz#076b1a5ef53fc9ee65143afbad390b7247531689" + integrity sha512-QVgIy+H3038t0r2EtPuknn1I9Cn2foVKk36uU3Wk+npceFu995kTkH1T77AN4KRxsSZBUyENN9XUxaCvUwiN+Q== dependencies: "@types/sparqljs" "^3.1.11" "@zazuko/prefixes" "^2.1.0" @@ -3009,6 +3009,11 @@ dependencies: xmlchars "^2.2.0" +"@sec-ant/readable-stream@^0.4.1": + version "0.4.1" + resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" + integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== + "@sentry/browser@6.17.9": version "6.17.9" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.17.9.tgz#62eac0cc3c7c788df6b4677fe9882d3974d84027" @@ -4956,10 +4961,10 @@ "@zazuko/env" "^2.1.1" "@zazuko/rdf-utils-fs" "^3.3.0" -"@zazuko/env@^2.1.1", "@zazuko/env@^2.2.0": - version "2.2.0" - resolved "https://registry.yarnpkg.com/@zazuko/env/-/env-2.2.0.tgz#090ca10466113428483bfffeedf981b0b411d8e5" - integrity sha512-73KwqrckawQTmoPAizlkHIRpsqFOaR31LA4XEZUnLM6CbGF/DhmbclfhMtg8GBAiZLIVdgXj6GZAW0lUmA4knQ== +"@zazuko/env@^2.1.1", "@zazuko/env@^2.4.2": + version "2.4.2" + resolved "https://registry.yarnpkg.com/@zazuko/env/-/env-2.4.2.tgz#a9c3df642e3567f681ad23c3635cafa6bb2fb85d" + integrity sha512-mq3YTIs9dmXh2nyS2Hm94bNRHuItlgrp+5QS1zG6ClSpmgztKhMYNRhssmZvd0kBcpYZSV4+EogI/QxrkCg6ww== dependencies: "@rdfjs/data-model" "^2.0.1" "@rdfjs/dataset" "^2.0.1" @@ -4972,7 +4977,7 @@ "@zazuko/env-core" "^1.1.2" "@zazuko/prefixes" "^2.1.0" clownface "^2.0.2" - get-stream "^8.0.1" + get-stream "^9.0.1" rdf-dataset-ext "^1.1.0" "@zazuko/node-fetch@^2.6.6": @@ -8925,6 +8930,14 @@ get-stream@^8.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== +get-stream@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27" + integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== + dependencies: + "@sec-ant/readable-stream" "^0.4.1" + is-stream "^4.0.1" + get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -9873,6 +9886,11 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== +is-stream@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" + integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== + is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" @@ -14287,7 +14305,7 @@ string-to-stream@^3.0.1: dependencies: readable-stream "^3.4.0" -"string-width-cjs@npm:string-width@^4.2.0": +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -14304,15 +14322,6 @@ string-width@^2.1.1: is-fullwidth-code-point "^2.0.0" strip-ansi "^4.0.0" -string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: - version "4.2.3" - resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" - integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== - dependencies: - emoji-regex "^8.0.0" - is-fullwidth-code-point "^3.0.0" - strip-ansi "^6.0.1" - string-width@^5.0.0, string-width@^5.0.1, string-width@^5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" @@ -14382,7 +14391,7 @@ string_decoder@~1.1.1: dependencies: safe-buffer "~5.1.0" -"strip-ansi-cjs@npm:strip-ansi@^6.0.1": +"strip-ansi-cjs@npm:strip-ansi@^6.0.1", strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== @@ -14396,13 +14405,6 @@ strip-ansi@^4.0.0: dependencies: ansi-regex "^3.0.0" -strip-ansi@^6.0.0, strip-ansi@^6.0.1: - version "6.0.1" - resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" - integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== - dependencies: - ansi-regex "^5.0.1" - strip-ansi@^7.0.1: version "7.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" @@ -15577,7 +15579,7 @@ workerpool@6.2.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.2.1.tgz#46fc150c17d826b86a008e5a4508656777e9c343" integrity sha512-ILEIE97kDZvF9Wb9f6h5aXK4swSlKGUcOEGiIYb2OOu/IrDU9iwj0fD//SsA6E5ibwJxpEvhullJY4Sl4GcpAw== -"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0", wrap-ansi@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== @@ -15603,15 +15605,6 @@ wrap-ansi@^6.2.0: string-width "^4.1.0" strip-ansi "^6.0.0" -wrap-ansi@^7.0.0: - version "7.0.0" - resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" - integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== - dependencies: - ansi-styles "^4.0.0" - string-width "^4.1.0" - strip-ansi "^6.0.0" - wrap-ansi@^8.1.0: version "8.1.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" From de5388899387dd42e60ca00666648191d1dd7e19 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 14:57:05 +0100 Subject: [PATCH 07/15] revert: accidentally commited --- setup-lando.sh | 994 ------------------------------------------------- 1 file changed, 994 deletions(-) delete mode 100755 setup-lando.sh diff --git a/setup-lando.sh b/setup-lando.sh deleted file mode 100755 index 85f783cb9..000000000 --- a/setup-lando.sh +++ /dev/null @@ -1,994 +0,0 @@ -SCRIPT_VERSION="v3.7.2" -#!/bin/bash -set -u -# Lando POSIX setup script. -# -# This script is the official and recommended way to setup Lando on your POSIX -# based computer. For information on requirements, advanced usage or installing -# in different environments (Windows, CI, GitHub Actions) you should check out: -# -# - https://docs.lando.dev/install -# -# Script source is available at https://github.com/lando/setup-lando - -# -# Usage: -# -# To setup the latest stable version of Lando with all defaults you can -# directly curlbash: -# -# $ /bin/bash -c "$(curl -fsSL https://get.lando.dev/setup-lando.sh)" -# -# If you want to customize your installation you will need to download the -# script and invoke directly so you can pass in options: -# -# 1. download -# -# $ curl -fsSL https://get.lando.dev/setup-lando.sh -o setup-lando.sh -# -# 2. make executable -# -# $ chmod +x ./setup-lando.sh -# -# 3. print advanced usage -# -# $ bash setup-lando.sh --help -# -# 4. run customized setup -# -# $ bash setup-lando.sh --no-setup --version v3.23.1 --debug --yes - -# -# This script was based on the HOMEBREW installer script and as such you may -# enjoy the below licensing requirement: -# -# Copyright (c) 2009-present, Homebrew contributors -# All rights reserved. -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are met: -# -# * Redistributions of source code must retain the above copyright notice, this -# list of conditions and the following disclaimer. -# -# * Redistributions in binary form must reproduce the above copyright notice, -# this list of conditions and the following disclaimer in the documentation -# and/or other materials provided with the distribution. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -# DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -# SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -# -# Any code that has been modified by the original falls under -# Copyright (c) 2009-2023, Lando. -# All rights reserved. -# See license in the repo: https://github.com/lando/setup-lando/blob/main/LICENSE -# -# We don't need return codes for "$(command)", only stdout is needed. -# Allow `[[ -n "$(command)" ]]`, `func "$(command)"`, pipes, etc. -# shellcheck disable=SC2312 - -# DEFAULT VERSION -LANDO_DEFAULT_MV="3" - -# CONFIG -LANDO_BINDIR="$HOME/.lando/bin" -LANDO_DATADIR="${XDG_DATA_HOME:-$HOME/.data}/lando" -LANDO_SYSDIR="/usr/local/bin" -LANDO_TMPDIR=${TMPDIR:-/tmp} - -MACOS_OLDEST_SUPPORTED="12.0" -REQUIRED_CURL_VERSION="7.41.0" -SEMVER_REGEX='^(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)\.(0|[1-9][0-9]*)(-((0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(\.(0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(\+([0-9a-zA-Z-]+(\.[0-9a-zA-Z-]+)*))?$' - -abort() { - printf "%s\n" "$@" >&2 - exit 1 -} - -# Fail fast with a concise message when not using bash -# Single brackets are needed here for POSIX compatibility -# shellcheck disable=SC2292 -if [ -z "${BASH_VERSION:-}" ]; then - abort "Bash is required to interpret this script." -fi - -# Check if script is run with force-interactive mode in CI -if [[ -n "${CI-}" && -n "${INTERACTIVE-}" ]]; then - abort "Cannot run force-interactive mode in CI." -fi - -# Check if both `INTERACTIVE` and `NONINTERACTIVE` are set -# Always use single-quoted strings with `exp` expressions -# shellcheck disable=SC2016 -if [[ -n "${INTERACTIVE-}" && -n "${NONINTERACTIVE-}" ]]; then - abort 'Both `$INTERACTIVE` and `$NONINTERACTIVE` are set. Please unset at least one variable and try again.' -fi - -# Check if script is run in POSIX mode -if [[ -n "${POSIXLY_CORRECT+1}" ]]; then - abort 'Bash must not run in POSIX mode. Please unset POSIXLY_CORRECT and try again.' -fi - -if [[ -t 1 ]]; then - tty_escape() { printf "\033[%sm" "$1"; } -else - tty_escape() { :; } -fi -tty_mkbold() { tty_escape "1;$1"; } -tty_mkdim() { tty_escape "2;$1"; } -tty_blue="$(tty_escape 34)" -tty_bold="$(tty_mkbold 39)" -tty_dim="$(tty_mkdim 39)" -tty_green="$(tty_escape 32)" -tty_magenta="$(tty_escape 35)" -tty_red="$(tty_mkbold 31)" -tty_reset="$(tty_escape 0)" -tty_underline="$(tty_escape "4;39")" -tty_yellow="$(tty_escape 33)" - -get_installer_arch() { - local arch - arch="$(/usr/bin/uname -m || /usr/bin/arch || uname -m || arch)" - if [[ "${arch}" == "arm64" ]] || [[ "${arch}" == "aarch64" ]]; then - INSTALLER_ARCH="arm64" - elif [[ "${arch}" == "x86_64" ]] || [[ "${arch}" == "x64" ]]; then - INSTALLER_ARCH="x64" - else - INSTALLER_ARCH="${arch}" - fi -} - -get_installer_os() { - local os - os="$(uname)" - if [[ "${os}" == "Linux" ]]; then - INSTALLER_OS="linux" - elif [[ "${os}" == "Darwin" ]]; then - INSTALLER_OS="macos" - else - INSTALLER_OS="${os}" - fi -} - -# get sysinfo -get_installer_arch -get_installer_os - -# set defaults but allow envvars to be used -# -# RUNNER_DEBUG is used here so we can get good debug output when toggled in GitHub Actions -# see https://github.blog/changelog/2022-05-24-github-actions-re-run-jobs-with-debug-logging/ - -# @TODO: no-sudo option -# @TODO: dest based on lmv -ARCH="${LANDO_INSTALLER_ARCH:-"$INSTALLER_ARCH"}" -DEBUG="${LANDO_INSTALLER_DEBUG:-${RUNNER_DEBUG:-}}" -DEST="${LANDO_INSTALLER_DEST:-$HOME/.lando/bin}" -FAT="${LANDO_INSTALLER_FAT:-0}" -OS="${LANDO_INSTALLER_OS:-"$INSTALLER_OS"}" -SETUP="${LANDO_INSTALLER_SETUP:-1}" -SYMLINKER="${LANDO_BINDIR}/lando" -SYSLINK="${LANDO_INSTALLER_SYSLINK:-auto}" -SYSLINKER="${LANDO_SYSDIR}/lando" -VERSION="${LANDO_VERSION:-${LANDO_INSTALLER_VERSION:-stable}}" - -# preserve originals OPTZ -ORIGOPTS="$*" - -usage() { - cat <&2 - exit 1 -} - -abort_multi() { - while read -r line; do - printf "${tty_red}ERROR${tty_reset}: %s\n" "$(chomp "$line")" >&2 - done <<< "$@" - exit 1 -} - -chomp() { - printf "%s" "${1/"$'\n'"/}" -} - -debug() { - if [[ -n "${DEBUG-}" ]]; then - printf "${tty_dim}debug${tty_reset} %s\n" "$(shell_join "$@")" >&2 - fi -} - -debug_multi() { - if [[ -n "${DEBUG-}" ]]; then - while read -r line; do - debug "$1 $line" - done <<< "$@" - fi -} - -log() { - printf "%s\n" "$(shell_join "$@")" -} - -shell_join() { - local arg - printf "%s" "${1:-}" - shift - for arg in "$@"; do - printf " " - printf "%s" "${arg// /\ }" - done -} - -warn() { - printf "${tty_yellow}warning${tty_reset}: %s\n" "$(chomp "$@")" >&2 -} - -warn_multi() { - while read -r line; do - warn "${line}" - done <<< "$@" -} - -# if we dont have a SCRIPT_VERSION then try to get it from git -if [[ -z "${SCRIPT_VERSION-}" ]]; then - SCRIPT_VERSION="$(git describe --tags --always --abbrev=1)" -fi - -# print version of script -debug "running setup-lando.sh script version: ${SCRIPT_VERSION}" - -# debug raw options -# these are options that have not yet been validated or mutated e.g. the ones the user has supplied or defualts\ -debug "raw args setup-lando.sh $ORIGOPTS" -debug raw CI="${CI:-}" -debug raw NONINTERACTIVE="${NONINTERACTIVE:-}" -debug raw ARCH="$ARCH" -debug raw DEBUG="$DEBUG" -debug raw DEST="$DEST" -debug raw FAT="$FAT" -debug raw OS="$OS" -debug raw SETUP="$SETUP" -debug raw SYSLINK="$SYSLINK" -debug raw USER="$USER" -debug raw VERSION="$VERSION" - -####################################################################### tool-verification - -# precautions -unset HAVE_SUDO_ACCESS - -# shellcheck disable=SC2230 -find_tool() { - if [[ $# -ne 1 ]]; then - return 1 - fi - - local executable - while read -r executable; do - if [[ "${executable}" != /* ]]; then - warn "Ignoring ${executable} (relative paths don't work)" - elif "test_$1" "${executable}"; then - echo "${executable}" - break - fi - done < <(which -a "$1") -} - -find_first_existing_parent() { - dir="$1" - - while [[ ! -d "$dir" ]]; do - dir=$(dirname "$dir") - done - - echo "$dir" -} - -have_sudo_access() { - local GROUPS_CMD - local -a SUDO=("/usr/bin/sudo") - - GROUPS_CMD="$(which groups)" - - if [[ ! -x "/usr/bin/sudo" ]]; then - return 1 - fi - - if [[ -x "$GROUPS_CMD" ]]; then - if "$GROUPS_CMD" | grep -q sudo; then - HAVE_SUDO_ACCESS="0" - fi - if "$GROUPS_CMD" | grep -q admin; then - HAVE_SUDO_ACCESS="0" - fi - if "$GROUPS_CMD" | grep -q adm; then - HAVE_SUDO_ACCESS="0" - fi - if "$GROUPS_CMD" | grep -q wheel; then - HAVE_SUDO_ACCESS="0" - fi - fi - - if [[ -n "${SUDO_ASKPASS-}" ]]; then - SUDO+=("-A") - fi - - if [[ -z "${HAVE_SUDO_ACCESS-}" ]]; then - "${SUDO[@]}" -l -U "${USER}" &>/dev/null - HAVE_SUDO_ACCESS="$?" - fi - - if [[ "${HAVE_SUDO_ACCESS}" == 1 ]]; then - debug "${USER} does not appear to have sudo access!" - else - debug "${USER} has sudo access" - fi - - return "${HAVE_SUDO_ACCESS}" -} - -major() { - echo "$1" | cut -d '.' -f1 -} - -major_minor() { - echo "${1%%.*}.$( - x="${1#*.}" - echo "${x%%.*}" - )" -} - -# shellcheck disable=SC2317 -test_curl() { - if [[ ! -x "$1" ]]; then - return 1 - fi - - local curl_version_output curl_name_and_version - curl_version_output="$("$1" --version 2>/dev/null)" - curl_name_and_version="${curl_version_output%% (*}" - version_compare "$(major_minor "${curl_name_and_version##* }")" "$(major_minor "${REQUIRED_CURL_VERSION}")" -} - -# returns true if maj.min a is greater than maj.min b -version_compare() ( - yy_a="$(echo "$1" | cut -d'.' -f1)" - yy_b="$(echo "$2" | cut -d'.' -f1)" - if [ "$yy_a" -lt "$yy_b" ]; then - return 1 - fi - if [ "$yy_a" -gt "$yy_b" ]; then - return 0 - fi - mm_a="$(echo "$1" | cut -d'.' -f2)" - mm_b="$(echo "$2" | cut -d'.' -f2)" - - # trim leading zeros to accommodate CalVer - mm_a="${mm_a#0}" - mm_b="${mm_b#0}" - - if [ "${mm_a:-0}" -lt "${mm_b:-0}" ]; then - return 1 - fi - - return 0 -) - -# abort if we dont have curl, or the right version of it -if [[ -z "$(find_tool curl)" ]]; then - abort_multi "$(cat </dev/null; then - debug "curl ${URL}" - # shellcheck disable=SC2086 - debug_multi "curl" "$($CURL --location --head --silent $URL)" - abort "$(cat </dev/null; then - trap '/usr/bin/sudo -k' EXIT -fi - -# Things can fail later if `pwd` doesn't exist. -# Also sudo prints a warning message for no good reason -cd "/usr" || exit 1 - -# if running non-interactively then lets try to summarize what we are going to do -if [[ -z "${NONINTERACTIVE-}" ]]; then - log "${tty_bold}this script is about to:${tty_reset}" - log - # sudo prompt - if needs_sudo; then log "- ${tty_green}prompt${tty_reset} for ${tty_bold}sudo${tty_reset} password"; fi - # download - log "- ${tty_magenta}download${tty_reset} lando ${tty_bold}${HRV}${tty_reset} to ${tty_bold}${DEST}${tty_reset}" - # syslinke - if [[ "$SYSLINK" == "1" ]]; then log "- ${tty_magenta}create${tty_reset} ${tty_bold}syslink${tty_reset} in ${tty_bold}${LANDO_SYSDIR}${tty_reset}"; fi - # setup - if [[ "$SETUP" == "1" ]]; then log "- ${tty_blue}run${tty_reset} ${tty_bold}lando setup${tty_reset}"; fi - # shellenv - log "- ${tty_blue}run${tty_reset} ${tty_bold}lando shellenv --add${tty_reset}" - - # block for user - wait_for_user -fi - -# flag for password here if needed -if needs_sudo; then - log "please enter ${tty_bold}sudo${tty_reset} password:" - execute_sudo true -fi - -# Create directories if we need to -if [[ ! -d "$DEST" ]]; then auto_mkdirp "$DEST"; fi -if [[ ! -d "$LANDO_TMPDIR" ]]; then auto_mkdirp "$LANDO_TMPDIR"; fi -if [[ ! -d "$LANDO_BINDIR" ]]; then auto_mkdirp "$LANDO_BINDIR"; fi - -# download lando -log "${tty_magenta}downloading${tty_reset} ${tty_bold}${URL}${tty_reset} to ${tty_bold}${LANDO}${tty_reset}" -auto_curl_n_x "$LANDO_TMPFILE" "$URL" - -# weak "it works" test -execute "${LANDO_TMPFILE}" version >/dev/null - -# if dest = symlinker then we need to actually mv 2 LANDO_DATADIR -# NOTE: we use mv here instead of cp because of https://developer.apple.com/forums/thread/130313 -if [[ "$LANDO" == "$SYMLINKER" ]]; then - auto_mkdirp "${LANDO_DATADIR}/${VERSION}" - auto_mv "$LANDO_TMPFILE" "$HIDDEN_LANDO" - auto_link "$HIDDEN_LANDO" "$SYMLINKER" -else - auto_mv "$LANDO_TMPFILE" "$LANDO" - auto_link "$LANDO" "$SYMLINKER" -fi - -# hook up the syslink here -if [[ "$SYSLINK" == "1" ]]; then - auto_link "$SYMLINKER" "$SYSLINKER" -fi - -# if lando 3 then we need to do some other cleanup things -# @TODO: is there an equivalent on lando 4? -if [[ $LMV == '3' ]]; then - # remove preexisting lando core so this one can also assert primacy - execute rm -rf "$HOME/.lando/plugins/@lando/core" - # clean - execute "${LANDO}" --clear >/dev/null; -fi - -# test via log -log "${tty_green}downloaded${tty_reset} lando ${tty_bold}$("${LANDO}" version --component @lando/cli)${tty_reset} to ${tty_bold}${LANDO}${tty_reset}" - -# run correct setup flavor if needed -if [[ "$SETUP" == "1" ]]; then - if [[ "${NONINTERACTIVE-}" == "1" ]]; then - execute "${LANDO}" setup --yes "${LANDO_DEBUG-}" - else - execute "${LANDO}" setup "${LANDO_DEBUG-}" - fi -fi - -# shell env -execute "${LANDO}" shellenv --add "${LANDO_DEBUG-}" > /dev/null - -# sucess message here -log "${tty_green}success!${tty_reset} ${tty_magenta}lando${tty_reset} is now installed!" - -# if we cannot invoke the correct lando then print shellenv message -if \ - ! which lando > /dev/null \ - || [[ "$(readlink -f "$(which lando)")" != "$LANDO" && "$(readlink -f "$(which lando)")" != "$HIDDEN_LANDO" ]]; then - log - log "${tty_magenta}Start a new terminal session${tty_reset} or run ${tty_magenta}eval \"\$(${LANDO} shellenv)\"${tty_reset} to use lando" -fi - -# FIN! -exit 0 From 8ef22e5a54ee4bd18024bd5219875762b13c4600 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 15:04:51 +0100 Subject: [PATCH 08/15] build: fix ui build --- ui/src/views/SharedDimensions.vue | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ui/src/views/SharedDimensions.vue b/ui/src/views/SharedDimensions.vue index 02fff6080..caffac839 100644 --- a/ui/src/views/SharedDimensions.vue +++ b/ui/src/views/SharedDimensions.vue @@ -102,7 +102,7 @@ export default defineComponent({ this.operation = this.collection.actions.get this.searchParams = this.collection.searchParams this.pageSize = this.searchParams.out(hydra.limit).value - this.page = parseInt(this.$router.currentRoute.value.query.page) || 1 + this.page = parseInt(this.$router.currentRoute.value.query.page as any) || 1 }, setup () { @@ -134,7 +134,7 @@ export default defineComponent({ await this.$store.dispatch('sharedDimensions/fetchCollection', to.query) this.searchParams = this.collection.searchParams this.pageSize = this.searchParams.out(hydra.limit).value - this.page = parseInt(to.query.page) || 1 + this.page = parseInt(to.query.page as any) || 1 }, methods: { From 7b5fdabd9c4d2b1f28bb1a9322e8b564d42b3f26 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 15:05:48 +0100 Subject: [PATCH 09/15] build(deps): force older version of zazuko env which requires newer typescript --- package.json | 3 ++- yarn.lock | 28 +++++----------------------- 2 files changed, 7 insertions(+), 24 deletions(-) diff --git a/package.json b/package.json index 1ca6727ca..1e847edd5 100644 --- a/package.json +++ b/package.json @@ -78,7 +78,8 @@ ] }, "resolutions": { - "@types/eslint": "^8" + "@types/eslint": "^8", + "@zazuko/env": "2.2.0" }, "lint-staged": { "*.{js,ts,vue}": [ diff --git a/yarn.lock b/yarn.lock index ae2848407..3e758bd0d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3009,11 +3009,6 @@ dependencies: xmlchars "^2.2.0" -"@sec-ant/readable-stream@^0.4.1": - version "0.4.1" - resolved "https://registry.yarnpkg.com/@sec-ant/readable-stream/-/readable-stream-0.4.1.tgz#60de891bb126abfdc5410fdc6166aca065f10a0c" - integrity sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg== - "@sentry/browser@6.17.9": version "6.17.9" resolved "https://registry.yarnpkg.com/@sentry/browser/-/browser-6.17.9.tgz#62eac0cc3c7c788df6b4677fe9882d3974d84027" @@ -4961,10 +4956,10 @@ "@zazuko/env" "^2.1.1" "@zazuko/rdf-utils-fs" "^3.3.0" -"@zazuko/env@^2.1.1", "@zazuko/env@^2.4.2": - version "2.4.2" - resolved "https://registry.yarnpkg.com/@zazuko/env/-/env-2.4.2.tgz#a9c3df642e3567f681ad23c3635cafa6bb2fb85d" - integrity sha512-mq3YTIs9dmXh2nyS2Hm94bNRHuItlgrp+5QS1zG6ClSpmgztKhMYNRhssmZvd0kBcpYZSV4+EogI/QxrkCg6ww== +"@zazuko/env@2.2.0", "@zazuko/env@^2.1.1", "@zazuko/env@^2.4.2": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@zazuko/env/-/env-2.2.0.tgz#090ca10466113428483bfffeedf981b0b411d8e5" + integrity sha512-73KwqrckawQTmoPAizlkHIRpsqFOaR31LA4XEZUnLM6CbGF/DhmbclfhMtg8GBAiZLIVdgXj6GZAW0lUmA4knQ== dependencies: "@rdfjs/data-model" "^2.0.1" "@rdfjs/dataset" "^2.0.1" @@ -4977,7 +4972,7 @@ "@zazuko/env-core" "^1.1.2" "@zazuko/prefixes" "^2.1.0" clownface "^2.0.2" - get-stream "^9.0.1" + get-stream "^8.0.1" rdf-dataset-ext "^1.1.0" "@zazuko/node-fetch@^2.6.6": @@ -8930,14 +8925,6 @@ get-stream@^8.0.1: resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== -get-stream@^9.0.1: - version "9.0.1" - resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-9.0.1.tgz#95157d21df8eb90d1647102b63039b1df60ebd27" - integrity sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA== - dependencies: - "@sec-ant/readable-stream" "^0.4.1" - is-stream "^4.0.1" - get-symbol-description@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" @@ -9886,11 +9873,6 @@ is-stream@^3.0.0: resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== -is-stream@^4.0.1: - version "4.0.1" - resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-4.0.1.tgz#375cf891e16d2e4baec250b85926cffc14720d9b" - integrity sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A== - is-string@^1.0.5, is-string@^1.0.7: version "1.0.7" resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" From d5a746cbcf519a5fcaa4cd6b04ef567dc6932b27 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 15:11:04 +0100 Subject: [PATCH 10/15] test: adjust to changed sample data --- .../lib/domain/managed-dimensions.test.ts | 24 +++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts b/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts index 669aae75e..7272eccbf 100644 --- a/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts +++ b/apis/shared-dimensions/test/lib/domain/managed-dimensions.test.ts @@ -3,7 +3,7 @@ import { expect } from 'chai' import $rdf from 'rdf-ext' import { mdClients } from '@cube-creator/testing/lib' import { insertTestDimensions } from '@cube-creator/testing/lib/seedData' -import { rdf, rdfs, schema } from '@tpluscode/rdf-ns-builders' +import { rdf, rdfs, schema, xsd } from '@tpluscode/rdf-ns-builders' import { getSharedDimensions, getSharedTerms } from '../../../lib/domain/shared-dimensions' describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPARQL', () => { @@ -24,16 +24,36 @@ describe('@cube-creator/shared-dimensions-api/lib/domain/shared-dimensions @SPAR // then const termSets = [...dataset.match(null, rdf.type, schema.DefinedTermSet)].map(({ subject }) => subject) expect(termSets).to.deep.contain.members([ - $rdf.namedNode('http://example.com/dimension/colors'), + $rdf.namedNode('https://ld.admin.ch/cube/dimension/technologies'), $rdf.namedNode('http://example.com/dimension/countries'), $rdf.namedNode('http://example.com/dimension/chemicals'), ]) }) it('returns filtered by name', async () => { + // given + const collectionData = await getSharedDimensions(mdClients.streamClient, { + freetextQuery: 'techno', + }) + + // when + const dataset = $rdf.dataset([ + ...collectionData.members, + ]) + + // then + const termSets = [...dataset.match(null, rdf.type, schema.DefinedTermSet)].map(({ subject }) => subject) + expect(termSets).to.have.length(1) + expect(termSets).to.deep.contain.members([ + $rdf.namedNode('https://ld.admin.ch/cube/dimension/technologies'), + ]) + }) + + it('returns filtered to include deprecated', async () => { // given const collectionData = await getSharedDimensions(mdClients.streamClient, { freetextQuery: 'colors', + includeDeprecated: $rdf.literal('true', xsd.boolean), }) // when From 7d89bf9a1c8b2b76672c47c501b37297e1966e54 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 15:20:05 +0100 Subject: [PATCH 11/15] test(cypress): fix selectors, accommodate to second form on page --- ui/tests/e2e/specs/shared-dimensions.spec.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ui/tests/e2e/specs/shared-dimensions.spec.ts b/ui/tests/e2e/specs/shared-dimensions.spec.ts index dc3d49ed9..15df69cab 100644 --- a/ui/tests/e2e/specs/shared-dimensions.spec.ts +++ b/ui/tests/e2e/specs/shared-dimensions.spec.ts @@ -16,15 +16,15 @@ describe('Shared dimensions', () => { cy.contains('.button', 'Create shared dimension').click() - cy.contains('form-property', 'Identifier') + cy.get('.quickview').contains('form-property', 'Identifier') .find('input') .type(toIdentifier(dimensionName)) - cy.contains('form-property', 'Name') + cy.get('.quickview').contains('form-property', 'Name') .find('input') .type(dimensionName) - cy.contains('form-property', 'Name') + cy.get('.quickview').contains('form-property', 'Name') .find('select') .select('en') From 6a0c38edfb08eba7b341710086a3656d8a4f127d Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 15:28:22 +0100 Subject: [PATCH 12/15] revert: mistake --- apis/shared-dimensions/hydra/index.ttl | 3 +++ 1 file changed, 3 insertions(+) diff --git a/apis/shared-dimensions/hydra/index.ttl b/apis/shared-dimensions/hydra/index.ttl index 4961b6b21..c28cc7e33 100644 --- a/apis/shared-dimensions/hydra/index.ttl +++ b/apis/shared-dimensions/hydra/index.ttl @@ -355,3 +355,6 @@ md:SharedDimensionTerm ] ; ] ; . + + a sh:Shape . + a sh:Shape . From 5af9642767d1759f7f962be72c1715af46a52aa9 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 16:48:43 +0100 Subject: [PATCH 13/15] fix: loading from dedicated graph --- .../shared-dimensions/test/lib/loader.test.ts | 5 ++- patches/sparql-http-client+2.4.0.patch | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/apis/shared-dimensions/test/lib/loader.test.ts b/apis/shared-dimensions/test/lib/loader.test.ts index 864909fbe..5220acedc 100644 --- a/apis/shared-dimensions/test/lib/loader.test.ts +++ b/apis/shared-dimensions/test/lib/loader.test.ts @@ -5,6 +5,7 @@ import { INSERT } from '@tpluscode/sparql-builder' import { mdClients } from '@cube-creator/testing/lib' import namespace from '@rdfjs/namespace' import { hydra, schema, sh } from '@tpluscode/rdf-ns-builders' +import { md } from '@cube-creator/core/namespace' import Loader from '../../lib/loader' const ex = namespace('http://example.com/') @@ -12,7 +13,7 @@ const graph = ex('shared-dimensions') const testResources = INSERT.DATA` graph ${graph} { ${ex.foo} - a ${hydra.Resource} ; + a ${md.SharedDimension} ; ${schema.name} "Yes" ; ${ex.hidden} "foo" ; . @@ -53,7 +54,7 @@ describe('shared-dimensions/lib/loader @SPARQL', () => { // then expect(resource.types).to.have.property('size', 1) expect([...resource.types]).to.deep.contain.members([ - hydra.Resource, + md.SharedDimension, ]) }) diff --git a/patches/sparql-http-client+2.4.0.patch b/patches/sparql-http-client+2.4.0.patch index 182e0e995..420ed82b3 100644 --- a/patches/sparql-http-client+2.4.0.patch +++ b/patches/sparql-http-client+2.4.0.patch @@ -143,3 +143,46 @@ index 5aa6bfc..1538933 100644 } } +diff --git a/node_modules/sparql-http-client/StreamQuery.js b/node_modules/sparql-http-client/StreamQuery.js +index 163b325..bbbe20d 100644 +--- a/node_modules/sparql-http-client/StreamQuery.js ++++ b/node_modules/sparql-http-client/StreamQuery.js +@@ -27,8 +27,8 @@ class StreamQuery extends RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async ask (query, { headers, operation } = {}) { +- const res = await super.ask(query, { headers, operation }) ++ async ask (query, { headers, operation, ...options } = {}) { ++ const res = await super.ask(query, { headers, operation, ...options }) + + await checkResponse(res) + +@@ -44,14 +44,14 @@ class StreamQuery extends RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async construct (query, { headers, operation } = {}) { ++ async construct (query, { headers, operation, ...options } = {}) { + headers = new this.endpoint.fetch.Headers(headers) + + if (!headers.has('accept')) { + headers.set('accept', 'application/n-triples, text/turtle') + } + +- const res = await super.construct(query, { headers, operation }) ++ const res = await super.construct(query, { headers, operation, ...options }) + + await checkResponse(res) + +@@ -67,8 +67,8 @@ class StreamQuery extends RawQuery { + * @param {'get'|'postUrlencoded'|'postDirect'} [init.operation='get'] + * @return {Promise} + */ +- async select (query, { headers, operation } = {}) { +- const res = await super.select(query, { headers, operation }) ++ async select (query, { headers, operation, ...options } = {}) { ++ const res = await super.select(query, { headers, operation, ...options }) + + await checkResponse(res) + From 1fe9ee2475ebc21df88c338bc0dc506f98a52d72 Mon Sep 17 00:00:00 2001 From: Tomasz Pluskiewicz Date: Tue, 31 Dec 2024 17:12:56 +0100 Subject: [PATCH 14/15] Create late-cows-impress.md --- .changeset/late-cows-impress.md | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 .changeset/late-cows-impress.md diff --git a/.changeset/late-cows-impress.md b/.changeset/late-cows-impress.md new file mode 100644 index 000000000..d328c8702 --- /dev/null +++ b/.changeset/late-cows-impress.md @@ -0,0 +1,6 @@ +--- +"@cube-creator/ui": minor +"@cube-creator/shared-dimensions-api": minor +--- + +Searching and paging Shared Dimensions From 871c2db64c518b554b529a9ed85a2e16d6479177 Mon Sep 17 00:00:00 2001 From: tpluscode Date: Fri, 3 Jan 2025 09:58:22 +0100 Subject: [PATCH 15/15] fix: operation title --- apis/shared-dimensions/hydra/index.ttl | 1 + 1 file changed, 1 insertion(+) diff --git a/apis/shared-dimensions/hydra/index.ttl b/apis/shared-dimensions/hydra/index.ttl index c28cc7e33..2c5fa46b4 100644 --- a/apis/shared-dimensions/hydra/index.ttl +++ b/apis/shared-dimensions/hydra/index.ttl @@ -44,6 +44,7 @@ md:SharedDimensions [ a hydra:Operation, schema:DownloadAction ; hydra:method "GET" ; + hydra:title "Search" ; hydra:expects ; code:implementedBy [