diff --git a/__test_utils__/util.ts b/__test_utils__/util.ts index a2047ff2..4a562169 100644 --- a/__test_utils__/util.ts +++ b/__test_utils__/util.ts @@ -2,7 +2,7 @@ import type { Quad } from '@rdfjs/types'; import 'jest-rdf'; import { DataFactory, Parser, Store } from 'n3'; -import { data, dataStar, query, queryAll, result } from '../data/socrates'; +import { data, dataSplit, dataStar, query, queryAll, result } from '../data/socrates'; import { n3reasoner } from '../dist'; import { data as blogicData, result as blogicResult } from '../data/blogic'; import { data as regexData, result as regexResult } from '../data/regex'; @@ -138,16 +138,36 @@ export function universalTests() { expect(quads).toBeRdfIsomorphic(resultQuads); }); + it('should execute the n3reasoner [string single list input string output]', async () => { + const resultStr: string = await n3reasoner([data], query); + const quads = (new Parser({ format: 'text/n3' })).parse(resultStr); + expect(quads).toBeRdfIsomorphic(resultQuads); + }); + it('should execute the n3reasoner [string input explicit string output]', async () => { const resultStr: string = await n3reasoner(data, query, { outputType: 'string' }); const quads = (new Parser({ format: 'text/n3' })).parse(resultStr); expect(quads).toBeRdfIsomorphic(resultQuads); }); + it('should execute the n3reasoner [string single list input explicit string output]', async () => { + const resultStr: string = await n3reasoner(data, query, { outputType: 'string' }); + const quads = (new Parser({ format: 'text/n3' })).parse(resultStr); + expect(quads).toBeRdfIsomorphic(resultQuads); + }); + it('should execute the n3reasoner [string input explicit quad output]', () => expect>( n3reasoner(data, query, { outputType: 'quads' }), ).resolves.toBeRdfIsomorphic(resultQuads)); + it('should execute the n3reasoner [string single list input explicit quad output]', () => expect>( + n3reasoner([data], query, { outputType: 'quads' }), + ).resolves.toBeRdfIsomorphic(resultQuads)); + + it('should execute the n3reasoner [string single list input explicit quad output]', () => expect>( + n3reasoner(dataSplit, query, { outputType: 'quads' }), + ).resolves.toBeRdfIsomorphic(resultQuads)); + it('should execute the n3reasoner without query quads', () => expect( n3reasoner(dataQuads), ).resolves.toBeRdfIsomorphic([socratesMortal])); diff --git a/data/socrates.ts b/data/socrates.ts index eefc020f..8ca877cb 100644 --- a/data/socrates.ts +++ b/data/socrates.ts @@ -10,16 +10,28 @@ export const queryAll = ` {?S ?P ?O} => {?S ?P ?O}. `; -export const data = ` +export const socratesPrefixes = ` @prefix rdfs: . @prefix : . +` -:Socrates a :Human. -:Human rdfs:subClassOf :Mortal. +export const socratesHuman = ':Socrates a :Human.'; +export const humanMortal = ':Human rdfs:subClassOf :Mortal.'; +export const subClassOf = '{?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}.' -{?A rdfs:subClassOf ?B. ?S a ?A} => {?S a ?B}. +export const data = `${socratesPrefixes} +${socratesHuman} +${humanMortal} + +${subClassOf} `; +export const dataSplit: [string, ...string[]] = [ + socratesPrefixes + socratesHuman, + socratesPrefixes + humanMortal, + socratesPrefixes + subClassOf, +] + export const result = ` @prefix : . diff --git a/lib/transformers.ts b/lib/transformers.ts index d2647d25..c80f5e54 100644 --- a/lib/transformers.ts +++ b/lib/transformers.ts @@ -44,18 +44,23 @@ export function SwiplEye(options?: Partial | undefined) { */ export function runQuery( Module: SWIPLModule, - data: string, + data: [string, ...string[]], queryString?: string, { output }: Options = {}, ): SWIPLModule { - const args: string[] = ['--nope', '--quiet', 'data.nq']; + const args = ['--nope', '--quiet']; + + for (let i = 0; i < data.length; i += 1) { + args.push(`data_${i}.n3s`); + Module.FS.writeFile(`data_${i}.n3s`, data[i]); + } if (queryString) { if (output) { throw new Error('Cannot use explicit output with explicit query'); } - Module.FS.writeFile('query.nq', queryString); - args.push('--query', './query.nq'); + Module.FS.writeFile('query.n3s', queryString); + args.push('--query', './query.n3s'); } else { switch (output) { case undefined: @@ -76,8 +81,6 @@ export function runQuery( } } - Module.FS.writeFile('data.nq', data); - queryOnce(Module, 'main', args); return Module; } @@ -92,8 +95,19 @@ function parse(res: string) { } export type Data = Quad[] | string +export type InputData = Data | [string, ...string[]] export type Query = Data | undefined +function inputDataToStrings(data: InputData): [string, ...string[]] { + if (typeof data === 'string') { + return [data]; + } + if (typeof data[0] === 'string') { + return data as [string, ...string[]]; + } + return [write(data as Quad[])]; +} + /** * Executes a basic query using the EYE Reasoner and default build of SWIPL * @param data The data for the query as RDF/JS quads @@ -105,12 +119,12 @@ export type Query = Data | undefined * @returns The result of the query as RDF/JS quads */ /* eslint-disable max-len */ -export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query: Query, options: { outputType: 'string' } & Options): Promise -export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query: Query, options: { outputType: 'quads' } & Options): Promise +export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query: Query, options: { outputType: 'string' } & Options): Promise +export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query: Query, options: { outputType: 'quads' } & Options): Promise export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Quad[], query?: Query, options?: { outputType?: undefined } & Options): Promise -export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: string, query?: Query, options?: { outputType?: undefined } & Options): Promise -export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query?: Query, options?: Options): Promise; -export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, query?: Query, options?: Options): Promise { +export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: string | [string, ...string[]], query?: Query, options?: { outputType?: undefined } & Options): Promise +export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query?: Query, options?: Options): Promise; +export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: InputData, query?: Query, options?: Options): Promise { /* eslint-enable max-len */ const outputType = options?.outputType; @@ -122,7 +136,7 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer }); runQuery( Module, - typeof data === 'string' ? data : write(data), + inputDataToStrings(data), query && (typeof query === 'string' ? query : write(query)), options, ); @@ -131,7 +145,7 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer throw new Error(`Error while executing query: ${err.join('\n')}`); } - return (outputType === 'quads' || (typeof data !== 'string' && outputType !== 'string')) + return (outputType === 'quads' || (typeof data !== 'string' && typeof data[0] !== 'string' && outputType !== 'string')) ? parse(res) : res; } @@ -147,12 +161,12 @@ export async function executeBasicEyeQuery(swipl: typeof SWIPL, data: Data, quer * @returns The result of the query as RDF/JS quads */ /* eslint-disable max-len */ -export async function n3reasoner(data: Data, query: Query, options: { outputType: 'string' } & Options): Promise -export async function n3reasoner(data: Data, query: Query, options: { outputType: 'quads' } & Options): Promise +export async function n3reasoner(data: InputData, query: Query, options: { outputType: 'string' } & Options): Promise +export async function n3reasoner(data: InputData, query: Query, options: { outputType: 'quads' } & Options): Promise export async function n3reasoner(data: Quad[], query?: Query, options?: { outputType?: undefined } & Options): Promise -export async function n3reasoner(data: string, query?: Query, options?: { outputType?: undefined } & Options): Promise -export async function n3reasoner(data: Data, query?: Query, options?: Options): Promise; -export async function n3reasoner(data: Data, query?: Query, options?: Options): Promise { +export async function n3reasoner(data: string | [string, ...string[]], query?: Query, options?: { outputType?: undefined } & Options): Promise +export async function n3reasoner(data: InputData, query?: Query, options?: Options): Promise; +export async function n3reasoner(data: InputData, query?: Query, options?: Options): Promise { /* eslint-enable max-len */ return executeBasicEyeQuery(options?.SWIPL || SWIPL, data, query, options); }