Skip to content
This repository has been archived by the owner on Sep 3, 2023. It is now read-only.

Commit

Permalink
feat(nodes): Add SoftwareApp node
Browse files Browse the repository at this point in the history
  • Loading branch information
harlan-zw committed Aug 19, 2022
1 parent 806df16 commit cb87bce
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 2 deletions.
1 change: 1 addition & 0 deletions src/index.ts
Expand Up @@ -25,6 +25,7 @@ export * from './nodes/Product'
export * from './nodes/Question'
export * from './nodes/Rating'
export * from './nodes/Recipe'
export * from './nodes/SoftwareApp'
export * from './nodes/Review'
export * from './nodes/Video'
export * from './nodes/WebPage'
Expand Down
50 changes: 50 additions & 0 deletions src/nodes/SoftwareApp/index.test.ts
@@ -0,0 +1,50 @@
import { expect } from 'vitest'
import { injectSchemaOrg, useSchemaOrg, useSetup } from '../../../.test'
import { defineSoftwareApp } from '#provider'

describe('defineSoftwareApp', () => {
it('can be defined', () => {
useSetup(() => {
useSchemaOrg([
defineSoftwareApp({
name: 'Angry Birds',
operatingSystem: 'ANDROID',
applicationCategory: 'GameApplication',
aggregateRating: {
ratingValue: '4.6',
ratingCount: 8864,
},
offers: {
price: '1.00',
priceCurrency: 'USD',
},
}),
])

const { graphNodes } = injectSchemaOrg()

expect(graphNodes).toMatchInlineSnapshot(`
[
{
"@type": "SoftwareApplication",
"aggregateRating": {
"@type": "AggregateRating",
"ratingCount": 8864,
"ratingValue": "4.6",
},
"applicationCategory": "GameApplication",
"name": "Angry Birds",
"offers": {
"@type": "Offer",
"availability": "https://schema.org/InStock",
"price": "1.00",
"priceCurrency": "USD",
"priceValidUntil": "2023-12-30T00:00:00.000Z",
},
"operatingSystem": "ANDROID",
},
]
`)
})
})
})
79 changes: 79 additions & 0 deletions src/nodes/SoftwareApp/index.ts
@@ -0,0 +1,79 @@
import type { Arrayable, NodeRelation, NodeRelations, Thing } from '../../types'
import { defineSchemaOrgResolver, resolveRelation } from '../../core'
import type { Offer } from '../Offer'
import { offerResolver } from '../Offer'
import type { AggregateRating } from '../AggregateRating'
import { aggregateRatingResolver } from '../AggregateRating'
import type { Review } from '../Review'
import { reviewResolver } from '../Review'
import { resolveDefaultType } from '../../utils'

type ApplicationCategory =
'GameApplication' |
'SocialNetworkingApplication' |
'TravelApplication' |
'ShoppingApplication' |
'SportsApplication' |
'LifestyleApplication' |
'BusinessApplication' |
'DesignApplication' |
'DeveloperApplication' |
'DriverApplication' |
'EducationalApplication' |
'HealthApplication' |
'FinanceApplication' |
'SecurityApplication' |
'BrowserApplication' |
'CommunicationApplication' |
'DesktopEnhancementApplication' |
'EntertainmentApplication' |
'MultimediaApplication' |
'HomeApplication' |
'UtilitiesApplication' |
'ReferenceApplication'

export interface SoftwareAppLite extends Thing {
'@type'?: Arrayable<'SoftwareApplication' | 'MobileApplication' | 'VideoGame' | 'WebApplication'>
/**
* The name of the app.
*/
name?: string
/**
* An offer to sell the app.
* For developers, offers can indicate the marketplaces that carry the application.
* For marketplaces, use offers to indicate the price of the app for a specific app instance.
*/
offers: NodeRelations<Offer>
/**
* The average review score of the app.
*/
aggregateRating?: NodeRelation<AggregateRating>
/**
* A single review of the app.
*/
review?: NodeRelation<Review>
/**
* The type of app (for example, BusinessApplication or GameApplication). The value must be a supported app type.
*/
applicationCategory?: ApplicationCategory
/**
* The operating system(s) required to use the app (for example, Windows 7, OSX 10.6, Android 1.6)
*/
operatingSystem?: string
}

export interface SoftwareApp extends SoftwareAppLite {}

export const softwareAppResolver = defineSchemaOrgResolver<SoftwareApp>({
defaults: {
'@type': 'SoftwareApplication',
},
resolve(node, ctx) {
resolveDefaultType(node, 'SoftwareApplication')
node.offers = resolveRelation(node.offers, ctx, offerResolver)
node.aggregateRating = resolveRelation(node.aggregateRating, ctx, aggregateRatingResolver)
node.review = resolveRelation(node.review, ctx, reviewResolver)
return node
},
})

7 changes: 5 additions & 2 deletions src/runtime/base.ts
Expand Up @@ -22,7 +22,9 @@ import type {
Question,
ReadAction,
Recipe,
Review, SchemaOrgNodeDefinition,
Review,
SoftwareApp,
SchemaOrgNodeDefinition,
SearchAction,
VideoObject,
VirtualLocation,
Expand Down Expand Up @@ -56,7 +58,7 @@ import {
readActionResolver,
recipeResolver, resolveOpeningHours,
reviewResolver,
searchActionResolver,
searchActionResolver, softwareAppResolver,
videoResolver,
virtualLocationResolver,
webPageResolver,
Expand Down Expand Up @@ -88,6 +90,7 @@ export const definePerson = <T extends Person>(input?: T) => provideResolver(inp
export const defineProduct = <T extends Product>(input?: T) => provideResolver(input, productResolver as SchemaOrgNodeDefinition<T>)
export const defineQuestion = <T extends Question>(input?: T) => provideResolver(input, questionResolver as SchemaOrgNodeDefinition<T>)
export const defineRecipe = <T extends Recipe>(input?: T) => provideResolver(input, recipeResolver as SchemaOrgNodeDefinition<T>)
export const defineSoftwareApp = <T extends SoftwareApp>(input?: T) => provideResolver(input, softwareAppResolver as SchemaOrgNodeDefinition<T>)
export const defineReview = <T extends Review>(input?: T) => provideResolver(input, reviewResolver as SchemaOrgNodeDefinition<T>)
export const defineVideo = <T extends VideoObject>(input?: T) => provideResolver(input, videoResolver as SchemaOrgNodeDefinition<T>)
export const defineWebPage = <T extends WebPage>(input?: T) => provideResolver(input, webPageResolver as SchemaOrgNodeDefinition<T>)
Expand Down

0 comments on commit cb87bce

Please sign in to comment.