Skip to content

Commit

Permalink
Improved usability of the .read method
Browse files Browse the repository at this point in the history
  • Loading branch information
juunini committed Oct 11, 2023
1 parent c9de76b commit 05f6896
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 13 deletions.
15 changes: 15 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,9 +97,24 @@ const imageURL = jsonld
.stringOrThrow()
// https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png

const imageURL = jsonld
.read('image')
.read('url')
.stringOrThrow()
// https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png

const id = jsonld.read('@id').get()
// https://mastodon.social/users/juunini

const id = jsonld.read('id').get()
// https://mastodon.social/users/juunini

const type = jsonld.read('@type').get()
// Person

const type = jsonld.read('type').get()
// Person

const manuallyApprovesFollowers = jsonld
.setNamespace({ as: 'https://www.w3.org/ns/activitystreams' })
.read('as', 'manuallyApprovesFollowers')
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@cloudmatelabs/jsonld-helper",
"version": "1.0.0",
"version": "1.1.0",
"description": "JSON-LD Helper",
"homepage": "https://github.com/cloudmatelabs/jsonld-helper-ts",
"repository": "cloudmatelabs/jsonld-helper-ts",
Expand Down
26 changes: 25 additions & 1 deletion src/reader.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ describe('read', () => {
describe('when given key is number, but value is not array', () => {
it('should changes type Nothing', async () => {
const jsonld = await JsonLDReader.parse(givenJSONLD)
expect(() => jsonld.read(0).getOrThrow()).toThrow('Not an array')
expect(() => jsonld.read(0).read(0).getOrThrow()).toThrow('Not an array')
})
})

Expand All @@ -42,6 +42,23 @@ describe('read', () => {
).toBe('https://mastodon.social/users/juunini/outbox')
})
})

describe('when not given namespace, find key', () => {
it('should return value', async () => {
const jsonld = await JsonLDReader.parse(givenJSONLD)
expect(jsonld.read('outbox').get()).toBe('https://mastodon.social/users/juunini/outbox')
})
})

describe('when given key is preDefined key', () => {
it('should return value', async () => {
const jsonld = await JsonLDReader.parse(givenJSONLD)
expect(jsonld.read('@id').get()).toBe('https://mastodon.social/users/juunini')
expect(jsonld.read('id').get()).toBe('https://mastodon.social/users/juunini')
expect(jsonld.read('@type').get()).toBe('Person')
expect(jsonld.read('type').get()).toBe('Person')
})
})
})

describe('stringOrThrow', () => {
Expand All @@ -57,6 +74,13 @@ describe('stringOrThrow', () => {
.read('as', 'url')
.stringOrThrow()
).toBe('https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png')

expect(
jsonld
.read('image')
.read('url')
.stringOrThrow()
).toBe('https://files.mastodon.social/accounts/headers/109/408/471/076/954/889/original/f4158a0d06a05763.png')
})
})

Expand Down
63 changes: 52 additions & 11 deletions src/reader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,14 +36,14 @@ export class JsonLDReader {
}

/**
* parse JSON-LD value. this method uses jsonld library's expand method. but, if expanded value is single value of array, returns JsonLDReader has first object of array.
* parse JSON-LD value. this method uses jsonld library's expand method.
*
* @param value JSON-LD object or array of JSON-LD objects
* @param options jsonld library's Options.Expand. see https://github.com/digitalbazaar/jsonld.js#custom-document-loader
*/
static async parse (value: object | object[], options?: Options.Expand): Promise<JsonLDReader> {
const data = await expand(value as JsonLdDocument, options)
return JsonLDReader.of(data.length === 1 ? data[0] : data)
return JsonLDReader.of(data)
}

/**
Expand All @@ -56,13 +56,13 @@ export class JsonLDReader {
}

/**
* @param key key or index of array
* @param key key or index of array. if given key is `outbox` and has `https://www.w3.org/ns/activitystreams#outbox`, returns value of `https://www.w3.org/ns/activitystreams#outbox`.
* @returns JsonLDReader instance. if key is not found, returns `Nothing` instance.
*/
public read (key: string | number): JsonLDReader
/**
* @param namespace if use `setNamespace` method to set namespace, you can use namespace as first argument. if not, insert full url as first argument. e.g. `https://www.w3.org/ns/activitystreams`
* @param key insert key. e.g. `url`
* @param key insert key. e.g. `url`. if has value is array and length is 1, it reads first element of array automatically.
* @returns JsonLDReader instance. if key is not found, returns `Nothing` instance.
*/
public read (namespace: string, key: string): JsonLDReader
Expand Down Expand Up @@ -224,18 +224,59 @@ export class JsonLDReader {
}

private readObject (key: string): JsonLDReader {
if (typeof this.value !== 'object') {
if (!this.valueIsObject()) {
return new Nothing(new Error('Not an object'))
}

const value = (this.value as any)?.length === 1
? (this.value as any[])[0]
: this.value
const scope = this.scope() as Record<string, any>
const value = scope[key]

const scope = (value as Record<string, any>)[key]
return scope === undefined
if (value !== undefined) {
if (key === '@type') {
return JsonLDReader.of(this.extractType(value), this.namespace)
}
return JsonLDReader.of(value, this.namespace)
}

const extractedKey = Object.keys(scope).find((k) => k.split('#')[1] === key)

return extractedKey === undefined
? new Nothing(new Error(`Not found key: ${key}`))
: JsonLDReader.of(scope, this.namespace)
: JsonLDReader.of(scope[extractedKey], this.namespace)
}

private extractType (value: string): string {
if (Array.isArray(value)) {
return this.extractType(value[0])
}

const hashSplit = value.split('#')
if (hashSplit.length === 2) {
return hashSplit[1]
}

const slashSplit = value.split('/')
return slashSplit[slashSplit.length - 1]
}

private valueIsObject (): boolean {
if (Array.isArray(this.value) && this.length === 1) {
return true
}

if (Array.isArray(this.value)) {
return false
}

return typeof this.value === 'object'
}

private scope (): unknown {
if (Array.isArray(this.value) && this.length === 1) {
return this.value[0]
}

return this.value
}

private getValue (): unknown {
Expand Down

0 comments on commit 05f6896

Please sign in to comment.