Skip to content

Commit

Permalink
Interpret @range {json} as rdf:JSON params
Browse files Browse the repository at this point in the history
  • Loading branch information
rubensworks committed Jun 14, 2021
1 parent 9727dc8 commit 09f7a37
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 7 deletions.
55 changes: 54 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,7 @@ Using comment tags, arguments can be customized.
|---|---
| `@ignored` | This field will be ignored.
| `@default {<value>}` | The `default` attribute of the parameter will be set to `<value>`
| `@range {<type>}` | The `range` attribute of the parameter will be set to `<type>`. You can only use values that fit the type of field. Options: `boolean, int, integer, number, byte, long, float, decimal, double, string`. For example, if your field has the type `number`, you could explicitly mark it as a `float` by using `@range {float}`. See [the documentation](https://componentsjs.readthedocs.io/en/latest/configuration/components/parameters/).
| `@range {<type>}` | The `range` attribute of the parameter will be set to `<type>`. You can only use values that fit the type of field. Options: `json, boolean, int, integer, number, byte, long, float, decimal, double, string`. For example, if your field has the type `number`, you could explicitly mark it as a `float` by using `@range {float}`. See [the documentation](https://componentsjs.readthedocs.io/en/latest/configuration/components/parameters/).

#### Examples

Expand Down Expand Up @@ -265,6 +265,59 @@ Component file:
}
```

**Tagging constructor fields as raw JSON:**

TypeScript class:
```typescript
export class MyActor {
/**
* @param myValue - Values will be passed as parsed JSON @range {json}
* @param ignoredArg - @ignored
*/
constructor(myValue: any, ignoredArg: string) {

}
}
```

Component file:
```json
{
"components": [
{
"parameters": [
{
"@id": "my-actor#TestClass#myValue",
"range": "rdf:JSON",
"required": false,
"unique": false,
"comment": "Values will be passed as parsed JSON"
}
],
"constructorArguments": [
{
"@id": "my-actor#TestClass#myValue"
}
]
}
]
}
```

When instantiating TestClass as follows, its JSON value will be passed directly into the constructor:
```json
{
"@id": "ex:myInstance",
"@type": "TestClass",
"myValue": {
"someKey": {
"someOtherKey1": 1,
"someOtherKey2": "abc"
}
}
}
```

**Tagging interface fields:**

TypeScript class:
Expand Down
2 changes: 1 addition & 1 deletion lib/serialize/ComponentConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -488,7 +488,7 @@ export class ComponentConstructor {
// Fill in required fields
const definition: ParameterDefinition = {
'@id': fieldId,
range: `xsd:${range}`,
range: range === 'json' ? 'rdf:JSON' : `xsd:${range}`,
};

// Fill in optional fields
Expand Down
7 changes: 5 additions & 2 deletions lib/serialize/ContextConstructor.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,12 @@ export class ContextConstructor {

// Generate type-scoped context when enabled
if (this.typeScopedContexts) {
const typeScopedContext: Record<string, string> = {};
const typeScopedContext: Record<string, Record<string, string>> = {};
for (const parameter of component.parameters) {
typeScopedContext[parameter['@id'].slice(Math.max(0, component['@id'].length + 1))] = parameter['@id'];
typeScopedContext[parameter['@id'].slice(Math.max(0, component['@id'].length + 1))] = {
'@id': parameter['@id'],
...parameter.range === 'rdf:JSON' ? { '@type': '@json' } : {},
};
}
(<any> shortcuts[match[0]])['@context'] = typeScopedContext;
}
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@
"@types/semver": "^7.3.4",
"@typescript-eslint/typescript-estree": "^4.6.1",
"comment-parser": "^0.7.6",
"componentsjs": "^4.2.0",
"componentsjs": "^4.3.0",
"jsonld-context-parser": "^2.0.2",
"lru-cache": "^6.0.0",
"minimist": "^1.2.5",
Expand Down
18 changes: 18 additions & 0 deletions test/serialize/ComponentConstructor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,24 @@ describe('ComponentConstructor', () => {
unique: true,
});
});

it('should construct a JSON parameter definition', () => {
const rangeValue = 'json';
expect(ctor.constructParameterRaw(context, <ClassLoaded> classReference, {
type: 'field',
name: 'field',
range: { type: 'raw', value: 'string' },
required: true,
unique: true,
comment: 'Hi',
}, rangeValue, 'mp:a/b/file-param#MyClass_field')).toEqual({
'@id': 'mp:a/b/file-param#MyClass_field',
comment: 'Hi',
range: 'rdf:JSON',
required: true,
unique: true,
});
});
});

describe('constructParameterClass', () => {
Expand Down
76 changes: 74 additions & 2 deletions test/serialize/ContextConstructor.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,80 @@ describe('ContextConstructor', () => {
'@id': 'mp:file1#MyClass1',
'@prefix': true,
'@context': {
param1: 'mp:file1#MyClass1_param1',
param2: 'mp:file1#MyClass1_param2',
param1: {
'@id': 'mp:file1#MyClass1_param1',
},
param2: {
'@id': 'mp:file1#MyClass1_param2',
},
},
},
MyClass2: {
'@id': 'mp:b/file2#MyClass2',
'@prefix': true,
'@context': {},
},
});
});

it('should handle non-empty component definitions when typeScopedContexts is true for JSON ranges', () => {
ctor = new ContextConstructor({
packageMetadata,
typeScopedContexts: true,
});
expect(ctor.constructComponentShortcuts({
'/docs/package/components/file1': {
'@context': [
'https://linkedsoftwaredependencies.org/bundles/npm/my-package/context.jsonld',
],
'@id': 'npmd:my-package',
components: [
{
'@id': 'mp:file1#MyClass1',
'@type': 'Class',
constructorArguments: [],
parameters: [
{
'@id': 'mp:file1#MyClass1_param1',
range: 'rdf:JSON',
},
{
'@id': 'mp:file1#MyClass1_param2',
range: 'rdf:JSON',
},
],
requireElement: 'MyClass1',
},
],
},
'/docs/package/components/b/file2': {
'@context': [
'https://linkedsoftwaredependencies.org/bundles/npm/my-package/context.jsonld',
],
'@id': 'npmd:my-package',
components: [
{
'@id': 'mp:b/file2#MyClass2',
'@type': 'Class',
requireElement: 'MyClass2',
constructorArguments: [],
parameters: [],
},
],
},
})).toEqual({
MyClass1: {
'@id': 'mp:file1#MyClass1',
'@prefix': true,
'@context': {
param1: {
'@id': 'mp:file1#MyClass1_param1',
'@type': '@json',
},
param2: {
'@id': 'mp:file1#MyClass1_param2',
'@type': '@json',
},
},
},
MyClass2: {
Expand Down

0 comments on commit 09f7a37

Please sign in to comment.