Skip to content

Commit

Permalink
feat: esm
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Apr 22, 2024
1 parent a362765 commit d807430
Show file tree
Hide file tree
Showing 48 changed files with 11,629 additions and 7,134 deletions.
5 changes: 5 additions & 0 deletions .changeset/lucky-chairs-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@hydrofoil/labyrinth": patch
---

ESM
3 changes: 2 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@
"project": "./tsconfig.json"
},
"rules": {
"no-undef": "off"
"no-undef": "off",
"@typescript-eslint/no-explicit-any": "off"
},
"overrides": [{
"files": ["*.ts"],
Expand Down
10 changes: 5 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,22 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@master
uses: actions/checkout@v4
with:
# This makes Actions fetch all Git history so that Changesets can generate changelogs with the correct commits
fetch-depth: 0

- name: Setup Node.js
uses: actions/setup-node@v2.1.2
uses: actions/setup-node@v4
with:
node-version: 13
node-version: lts/*

- name: Install Dependencies
run: yarn
run: npm ci

- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@master
uses: changesets/action@v1
with:
# This expects you to have a script called release which does a build for your packages and calls changeset publish
publish: yarn release
Expand Down
26 changes: 13 additions & 13 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,33 @@ jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '14'
- run: yarn
node-version: lts/*
- run: npm ci
- run: yarn test
- name: Codecov
uses: codecov/codecov-action@v1.0.5
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}

build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '13'
- run: yarn
node-version: lts/*
- run: npm ci
- run: yarn build

lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/setup-node@v1
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: '13'
- run: yarn
node-version: lts/*
- run: npm ci
- run: yarn lint
13 changes: 0 additions & 13 deletions babel.config.json

This file was deleted.

10 changes: 5 additions & 5 deletions collection.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
import asyncMiddleware from 'middleware-async'
import clownface, { AnyPointer } from 'clownface'
import type { AnyPointer } from 'clownface'
import { hydra } from '@tpluscode/rdf-ns-builders'
import { protectedResource } from './resource'
import * as lib from './lib/collection'
import { protectedResource } from './resource.js'
import * as lib from './lib/collection.js'

export const get = protectedResource(asyncMiddleware(async (req, res) => {
const types = clownface(req.hydra.api).node([...req.hydra.resource.types])
const types = req.hydra.api.env.clownface(req.hydra.api).node([...req.hydra.resource.types])
let request: AnyPointer | undefined
if (req.dataset) {
request = clownface({ dataset: await req.dataset() })
request = req.hydra.api.env.clownface({ dataset: await req.dataset() })
}

const collection = await req.hydra.resource.clownface()
Expand Down
4 changes: 2 additions & 2 deletions errors.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ErrorRequestHandler, RequestHandler } from 'express'
import { IErrorMapper } from 'http-problem-details-mapper'
import { httpProblemMiddleware } from './lib/problemDetails'
import { NotFoundError } from './lib/error'
import { httpProblemMiddleware } from './lib/problemDetails.js'
import { NotFoundError } from './lib/error/index.js'

interface Options {
errorMappers?: IErrorMapper[]
Expand Down
37 changes: 17 additions & 20 deletions index.ts
Original file line number Diff line number Diff line change
@@ -1,21 +1,18 @@
import { HydraBox, middleware, ResourceLoader } from 'hydra-box'
import { HydraBoxMiddleware } from 'hydra-box/middleware'
import type { NamedNode } from '@rdfjs/types'
import { HydraBox, middleware, ResourceLoader } from '@kopflos-cms/core'
import { HydraBoxMiddleware } from '@kopflos-cms/core/middleware.js'
import cors from 'cors'
import { Router } from 'express'
import RdfResource from '@tpluscode/rdfine'
import * as Hydra from '@rdfine/hydra'
import StreamClient from 'sparql-http-client/StreamClient'
import { ApiInit, createApi } from './lib'
import { NotFoundError } from './lib/error'
import { logRequest, logRequestError } from './lib/logger'
import { NamedNode } from 'rdf-js'
import { removeHydraOperations, preprocessResource } from './lib/middleware'
import { SparqlQueryLoader } from './lib/loader'
import { ensureArray } from './lib/array'
import StreamClient, { StreamClient as IStreamClient, Options } from 'sparql-http-client/StreamClient.js'
import Environment from './lib/env.js'
import { ApiInit, createApi } from './lib/index.js'
import { NotFoundError } from './lib/error/index.js'
import { logRequest, logRequestError } from './lib/logger.js'
import { removeHydraOperations, preprocessResource } from './lib/middleware.js'
import { SparqlQueryLoader } from './lib/loader.js'
import { ensureArray } from './lib/array.js'

export { SparqlQueryLoader } from './lib/loader'

RdfResource.factory.addMixin(...Object.values(Hydra))
export { SparqlQueryLoader } from './lib/loader.js'

export interface User {
id?: NamedNode
Expand All @@ -24,9 +21,9 @@ export interface User {
declare module 'express-serve-static-core' {
export interface Request {
user?: User
hydra: HydraBox
hydra: HydraBox<Environment>
labyrinth: {
sparql: StreamClient
sparql: IStreamClient
collection: {
pageSize: number
}
Expand All @@ -36,7 +33,7 @@ declare module 'express-serve-static-core' {

type MiddlewareParams = ApiInit & {
loader?: ResourceLoader
sparql: ConstructorParameters<typeof StreamClient>[0] & {
sparql: Options & {
endpointUrl: string
}
middleware?: HydraBoxMiddleware
Expand All @@ -48,7 +45,7 @@ type MiddlewareParams = ApiInit & {
}

export async function hydraBox(middlewareInit: MiddlewareParams): Promise<Router> {
const { loader, codePath, sparql, options, ...params } = middlewareInit
const { env, loader, codePath, sparql, options, ...params } = middlewareInit

const app = Router()

Expand All @@ -70,7 +67,7 @@ export async function hydraBox(middlewareInit: MiddlewareParams): Promise<Router
app.use(middleware(
await createApi(middlewareInit),
{
loader: loader ?? new SparqlQueryLoader(sparql),
loader: loader ?? new SparqlQueryLoader(env, sparql),
middleware: {
operations: [
removeHydraOperations,
Expand Down
3 changes: 2 additions & 1 deletion lib/array.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
export function ensureArray<T>(arg: undefined | T | T[]) {
return !(arg) ? []
return !(arg)
? []
: Array.isArray(arg)
? arg
: [arg]
Expand Down
77 changes: 42 additions & 35 deletions lib/collection.ts
Original file line number Diff line number Diff line change
@@ -1,32 +1,33 @@
import clownface, { AnyPointer, GraphPointer, MultiPointer } from 'clownface'
import { IriTemplate, IriTemplateMixin } from '@rdfine/hydra'
import type { NamedNode } from '@rdfjs/types'
import type { AnyPointer, GraphPointer, MultiPointer } from 'clownface'
import { IriTemplate } from '@rdfine/hydra'
import { hydra, rdf } from '@tpluscode/rdf-ns-builders'
import $rdf from 'rdf-ext'
import { NamedNode } from 'rdf-js'
import StreamClient from 'sparql-http-client/StreamClient'
import { ResourceIdentifier } from '@tpluscode/rdfine'
import { HydraBox } from 'hydra-box'
import DatasetExt from 'rdf-ext/lib/Dataset'
import { getSparqlQuery } from './query/collection'
import { loadLinkedResources } from './query/eagerLinks'
import * as ns from './namespace'

const emptyDataset = clownface({ dataset: $rdf.dataset() })
import { StreamClient } from 'sparql-http-client/StreamClient.js'
import type { ResourceIdentifier } from '@tpluscode/rdfine'
import { HydraBox } from '@kopflos-cms/core'
import fromStream from 'rdf-dataset-ext/fromStream.js'
import addAll from 'rdf-dataset-ext/addAll.js'
import { isGraphPointer } from 'is-graph-pointer'

Check failure on line 10 in lib/collection.ts

View workflow job for this annotation

GitHub Actions / lint

'is-graph-pointer' should be listed in the project's dependencies. Run 'npm i -S is-graph-pointer' to add it
import { getSparqlQuery } from './query/collection.js'
import { loadLinkedResources } from './query/eagerLinks.js'
import * as ns from './namespace.js'
import E from './env.js'

interface AddCollectionViewsParams {
env: E
collection: GraphPointer
total: number
template: IriTemplate
query?: AnyPointer
pageSize: number
}

function templateParamsForPage(query: AnyPointer, page: number) {
const clone = clownface({ dataset: $rdf.dataset([...query.dataset]) })
function templateParamsForPage($rdf: E, query: AnyPointer, page: number) {
const clone = $rdf.clownface({ dataset: $rdf.dataset([...query.dataset]) })
.in().toArray()[0]

if (!clone) {
return clownface({ dataset: $rdf.dataset() }).blankNode().addOut(hydra.pageIndex, page)
return $rdf.clownface().blankNode().addOut(hydra.pageIndex, page)
}

if (page === 1) {
Expand All @@ -36,7 +37,7 @@ function templateParamsForPage(query: AnyPointer, page: number) {
return clone.deleteOut(hydra.pageIndex).addOut(hydra.pageIndex, page)
}

function addCollectionViews({ collection, total, template, query = emptyDataset, pageSize }: AddCollectionViewsParams): void {
function addCollectionViews({ env: $rdf, collection, total, template, query = $rdf.clownface(), pageSize }: AddCollectionViewsParams): void {
if (!template.mapping.some(m => m.property?.equals(hydra.pageIndex))) {
return
}
Expand All @@ -47,18 +48,18 @@ function addCollectionViews({ collection, total, template, query = emptyDataset,
const totalPages = Math.floor(total / pageSize) + 1

view.addOut(rdf.type, hydra.PartialCollectionView)
view.addOut(hydra.first, $rdf.namedNode(template.expand(templateParamsForPage(query, 1))))
view.addOut(hydra.last, $rdf.namedNode(template.expand(templateParamsForPage(query, totalPages))))
view.addOut(hydra.first, $rdf.namedNode(template.expand(templateParamsForPage($rdf, query, 1))))
view.addOut(hydra.last, $rdf.namedNode(template.expand(templateParamsForPage($rdf, query, totalPages))))
if (pageIndex > 1) {
view.addOut(hydra.previous, $rdf.namedNode(template.expand(templateParamsForPage(query, pageIndex - 1))))
view.addOut(hydra.previous, $rdf.namedNode(template.expand(templateParamsForPage($rdf, query, pageIndex - 1))))
}
if (pageIndex < totalPages) {
view.addOut(hydra.next, $rdf.namedNode(template.expand(templateParamsForPage(query, pageIndex + 1))))
view.addOut(hydra.next, $rdf.namedNode(template.expand(templateParamsForPage($rdf, query, pageIndex + 1))))
}
})
}

function addTemplateMappings(collection: GraphPointer, template: IriTemplate, request: AnyPointer = emptyDataset): void {
function addTemplateMappings(env: E, collection: GraphPointer, template: IriTemplate, request: AnyPointer = env.clownface()): void {
collection.addOut(ns.query.templateMappings, currMappings => {
template.mapping.forEach(mapping => {
if (mapping.property) {
Expand All @@ -69,10 +70,10 @@ function addTemplateMappings(collection: GraphPointer, template: IriTemplate, re
})
}

function getTemplate(hydra: HydraBox): IriTemplate | null {
function getTemplate(hydra: HydraBox<E>): IriTemplate | null {
const templateVariables = hydra.operation.out(ns.hydraBox.variables) as MultiPointer<ResourceIdentifier>
if (templateVariables.term) {
return new IriTemplateMixin.Class(templateVariables.toArray()[0])
return hydra.api.env.rdfine.hydra.IriTemplate(templateVariables.toArray()[0])
}

return null
Expand All @@ -82,19 +83,24 @@ interface CollectionParams {
collection: GraphPointer<NamedNode>
query?: AnyPointer
pageSize: number
hydraBox: HydraBox
hydraBox: HydraBox<E>
sparqlClient: StreamClient
}

export async function collection({ hydraBox, pageSize, sparqlClient, query, ...rest }: CollectionParams): Promise<GraphPointer<NamedNode, DatasetExt>> {
const api = clownface(hydraBox.api)
const collection = clownface({
dataset: $rdf.dataset([...rest.collection.dataset]),
export async function collection({ hydraBox, pageSize, sparqlClient, query, ...rest }: CollectionParams): Promise<GraphPointer<NamedNode>> {
const env = hydraBox.api.env
const api = env.clownface(hydraBox.api)
if (!isGraphPointer(api)) {
throw new Error('API term not set')
}
const collection = env.clownface({
dataset: env.dataset([...rest.collection.dataset]),
term: rest.collection.term,
})
const template = getTemplate(hydraBox)

const pageQuery = await getSparqlQuery({
env,
api,
collection,
query,
Expand All @@ -105,12 +111,12 @@ export async function collection({ hydraBox, pageSize, sparqlClient, query, ...r

let total = 0
if (pageQuery) {
const page = await pageQuery.members.execute(sparqlClient.query)
const totals = pageQuery.totals.execute(sparqlClient.query)
for await (const result of await totals) {
const page = pageQuery.members.execute(sparqlClient)
const totals = pageQuery.totals.execute(sparqlClient)
for await (const result of totals) {
total = Number.parseInt(result.count.value)
}
await collection.dataset.import(page)
await fromStream(collection.dataset, page)
}
collection.addOut(hydra.totalItems, total)

Expand All @@ -122,11 +128,12 @@ export async function collection({ hydraBox, pageSize, sparqlClient, query, ...r
const eagerLoadByCollection = api.node([hydraBox.operation.term, ...hydraBox.resource.types]).out(ns.query.include)
const eagerLoadByMembers = api.node(collection.out(hydra.member).out(rdf.type).terms).out(ns.query.include)
const includeLinked = [...eagerLoadByCollection.toArray(), ...eagerLoadByMembers.toArray()]
collection.dataset.addAll(await loadLinkedResources(collection.out(hydra.member), includeLinked, sparqlClient))
addAll(collection.dataset, await loadLinkedResources(env, collection.out(hydra.member), includeLinked, sparqlClient))

if (template) {
addTemplateMappings(collection, template, query)
addTemplateMappings(env, collection, template, query)
addCollectionViews({
env,
collection,
total,
template,
Expand Down
9 changes: 9 additions & 0 deletions lib/env.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import type { Environment } from '@rdfjs/environment/Environment.js'
import type { DataFactory } from '@rdfjs/types'
import Factory from '@kopflos-cms/core/lib/factory.js'
import type { DerivedEnvironment } from '@zazuko/env'
import type { RdfineFactory } from '@tpluscode/rdfine'
import type { TermMapFactory } from '@rdfjs/term-map/Factory.js'

type E = DerivedEnvironment<Environment<RdfineFactory | Required<DataFactory> | TermMapFactory>, Factory>
export default E
3 changes: 2 additions & 1 deletion lib/error/NotFound.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { ErrorMapper } from 'http-problem-details-mapper'
import { ProblemDocument } from 'http-problem-details'
import error from 'http-errors'

export class NotFoundError extends Error {
export class NotFoundError extends error.NotFound {
}

export class NotFoundErrorMapper extends ErrorMapper {
Expand Down
2 changes: 1 addition & 1 deletion lib/error/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export { NotFoundError } from './NotFound'
export { NotFoundError } from './NotFound.js'
Loading

0 comments on commit d807430

Please sign in to comment.