Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: simple key/value pairs #39

Merged
merged 3 commits into from
Feb 22, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/shaggy-pants-hammer.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"rdf-loader-code": minor
---

Add simpler syntax for creating key/value pair arguments (closes #37, closes #38)
6 changes: 6 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
root = true

[*]
indent_size = 2
indent_style = space
insert_final_newline = true
46 changes: 29 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,13 +200,13 @@ loading of an argument map. Such arguments are declared as name/value pairs.

```turtle
@prefix code: <https://code.described.at/>.
@prefix arg: <https://code.described.at/argument#>.

<urn:call:string#startsWith>
code:arguments [
code:name "first"; code:value "foo"
], [
code:name "second"; code:value "bar"
] .
code:arguments ([
arg:first "foo" ;
arg:second "bar" ;
]) .
```

Executing the code below against the above triples will return an object containing the values
Expand All @@ -220,20 +220,32 @@ Executing the code below against the above triples will return an object contain
]
```

To make this method consistent with the positional flavor, the object will actually be wrapped
in an array as presented above.
#### Mixed arguments

Both methods can be sed together to represent any kind of function signature.

For example, to call a function as below

```js
import rdf from '@zazuko/env'
import loadArguments from 'rdf-loader-code/arguments.js'
import registry from './registry.js'
import dataset from './dataset.js'
myFunction('foo', 42, { bar: { baz: 'baz' } })
```

const term = rdf.namedNode('urn:call:string#startsWith')
You would declare the argument list as follows:

const argumentsObject = loadArguments(
rdf.clownface({ term, dataset }),
{
loaderRegistry: registry
})
```turtle
@prefix code: <https://code.described.at/> .
@prefix arg: <https://code.described.at/argument#> .

<urn:call:myFunction>
code:arguments
(
"foo"
42
[
arg:bar
[
arg:baz "baz"
]
]
) .
```
19 changes: 19 additions & 0 deletions arguments.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,11 +38,30 @@ async function parseArguments(args: MultiPointer, options: ParseArgument): Promi
return [argObject]
}

const argumentPropPattern = new RegExp(`^${ns.code('argument#').value}(.+)$`)

async function parseArgument(arg: AnyPointer, { context, variables, basePath, loaderRegistry }: ParseArgument): Promise<unknown> {
if (!isGraphPointer(arg)) {
throw new Error('Cannot load argument. Expected a single node or RDF List.')
}

tpluscode marked this conversation as resolved.
Show resolved Hide resolved
const loadingNamedArgs = [...arg.dataset.match(arg.term)]
.map(async quad => {
const isArgumentProp = quad.predicate.value.match(argumentPropPattern)
if (isArgumentProp) {
const key = isArgumentProp[1]
const value = await parseArgument(clownface({ dataset: arg.dataset, term: quad.object }), { context, variables, basePath, loaderRegistry })
return <[string, unknown]>[key, value]
}
return []
})

const argMap = Object.fromEntries((await Promise.all(loadingNamedArgs)).filter(([key]) => !!key))

if (Object.keys(argMap).length > 0) {
return argMap
}

const code = await loaderRegistry.load(arg, { context, variables, basePath })

if (typeof code !== 'undefined') {
Expand Down
20 changes: 20 additions & 0 deletions test/arguments-shorthand.ttl
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
@prefix arg: <https://code.described.at/argument#> .
@prefix xsd: <http://www.w3.org/2001/XMLSchema#> .
@prefix code: <https://code.described.at/> .

<http://example.com/single> code:arguments
(
[
arg:foo "foo" ;
arg:bar true ;
arg:baz 10 ;
]
) .


<http://example.com/nested> code:arguments
(
[
arg:foo [ arg:bar [ arg:baz "buzz" ] ] ;
]
) .
30 changes: 30 additions & 0 deletions test/arguments.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -129,4 +129,34 @@ describe('arguments loader', () => {
}
})
})

describe('shorthand syntax', () => {
it('load key-value pairs from a single blank node', async () => {
const term = rdf.namedNode('http://example.com/single')
const dataset = await loadDataset('./arguments-shorthand.ttl')

const result = await loader({ term, dataset }, { loaderRegistry: dummyLoaderRegistry })

deepStrictEqual(result, [{
foo: 'foo',
bar: true,
baz: 10,
}])
})

it('load deep key-value pairs', async () => {
const term = rdf.namedNode('http://example.com/nested')
const dataset = await loadDataset('./arguments-shorthand.ttl')

const result = await loader({ term, dataset }, { loaderRegistry: dummyLoaderRegistry })

deepStrictEqual(result, [{
foo: {
bar: {
baz: 'buzz',
},
},
}])
})
})
})
Loading