Skip to content
This repository has been archived by the owner on Jun 1, 2022. It is now read-only.

Commit

Permalink
Load entities from different repo/dir through github API and filesystem
Browse files Browse the repository at this point in the history
  • Loading branch information
SachaG committed Oct 19, 2021
1 parent 75b3d9d commit b0277f4
Show file tree
Hide file tree
Showing 13 changed files with 184 additions and 83 deletions.
2 changes: 1 addition & 1 deletion src/compute/experience.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import _ from 'lodash'
import { Db } from 'mongodb'
import config from '../config'
import { ratioToPercentage, appendCompletionToYearlyResults } from './common'
import { getEntity } from '../helpers'
import { getEntity } from '../entities'
import { Completion, SurveyConfig } from '../types'
import { Filters, generateFiltersQuery } from '../filters'
import { computeCompletionByYear } from './generic'
Expand Down
2 changes: 1 addition & 1 deletion src/compute/generic.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import config from '../config'
import { Completion, SurveyConfig } from '../types'
import { Filters, generateFiltersQuery } from '../filters'
import { ratioToPercentage } from './common'
import { getEntity } from '../helpers'
import { getEntity } from '../entities'
import { getParticipationByYearMap } from './demographics'
import { useCache } from '../caching'

Expand Down
2 changes: 1 addition & 1 deletion src/compute/matrices.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import _ from 'lodash'
import { Db } from 'mongodb'
import config from '../config'
import { ratioToPercentage } from './common'
import { getEntity } from '../helpers'
import { getEntity } from '../entities'
import { SurveyConfig } from '../types'
import { ToolExperienceFilterId, toolExperienceConfigById } from './tools'

Expand Down
140 changes: 140 additions & 0 deletions src/entities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
import { Entity } from './types'
import { Octokit } from '@octokit/core'
import fetch from 'node-fetch'
import yaml from 'js-yaml'
import { readdir, readFile } from 'fs/promises'
import last from 'lodash/last'
import { logToFile } from './debug'

let entities: Entity[] = []

const octokit = new Octokit({ auth: process.env.GITHUB_TOKEN })

// load locales if not yet loaded
export const loadOrGetEntities = async () => {
if (entities.length === 0) {
entities = await loadEntities()
}
return entities
}

export const loadFromGitHub = async () => {
const entities: Entity[] = []
console.log(`-> loading entities repo`)

const options = {
owner: 'StateOfJS',
repo: 'entities',
path: ''
}

const contents = await octokit.request('GET /repos/{owner}/{repo}/contents/{path}', options)
const files = contents.data as any[]

// loop over repo contents and fetch raw yaml files
for (const file of files) {
const extension: string = last(file?.name.split('.')) || ''
if (['yml', 'yaml'].includes(extension)) {
const response = await fetch(file.download_url)
const contents = await response.text()
try {
const yamlContents: any = yaml.load(contents)
const category = file.name.replace('./', '').replace('.yml', '')
yamlContents.forEach((entity: Entity) => {
const tags = entity.tags ? [...entity.tags, category] : [category]
entities.push({
...entity,
category,
tags
})
})
} catch (error) {
console.log(`// Error loading file ${file.name}`)
console.log(error)
}
}
}
return entities
}

// when developing locally, load from local files
export const loadLocally = async () => {
console.log(`-> loading entities locally`)

const entities: Entity[] = []

const devDir = __dirname.split('/').slice(1, -2).join('/')
const path = `/${devDir}/stateof-entities/`
const files = await readdir(path)
const yamlFiles = files.filter((f: String) => f.includes('.yml'))

// loop over dir contents and fetch raw yaml files
for (const fileName of yamlFiles) {
const filePath = path + '/' + fileName
const contents = await readFile(filePath, 'utf8')
const yamlContents: any = yaml.load(contents)
const category = fileName.replace('./', '').replace('.yml', '')
yamlContents.forEach((entity: Entity) => {
const tags = entity.tags ? [...entity.tags, category] : [category]
entities.push({
...entity,
category,
tags
})
})
}

return entities
}

// load locales contents through GitHub API or locally
export const loadEntities = async () => {
console.log('// loading entities')

const entities: Entity[] =
process.env.LOAD_LOCALES === 'local' ? await loadLocally() : await loadFromGitHub()
console.log('// done loading entities')

return entities
}

export const initEntities = async () => {
console.log('// initializing locales…')
const entities = await loadOrGetEntities()
logToFile('entities.json', entities, { mode: 'overwrite' })
}

export const getEntities = async ({ type, tag, tags }: { type?: string; tag?: string, tags?: string[] }) => {
let entities = await loadOrGetEntities()
if (type) {
entities = entities.filter(e => e.type === type)
}
if (tag) {
entities = entities.filter(e => e.tags && e.tags.includes(tag))
}
if (tags) {
entities = entities.filter(e => tags.every(t => e.tags && e.tags.includes(t)))
}
return entities
}

// Look up entities by id, name, or aliases (case-insensitive)
export const getEntity = async ({ id }: { id: string }) => {
const entities = await loadOrGetEntities()

if (!id || typeof id !== 'string') {
return
}

const lowerCaseId = id.toLowerCase()
const entity = entities.find(e => {
return (
(e.id && e.id.toLowerCase() === lowerCaseId) ||
(e.id && e.id.toLowerCase().replace(/\-/g, '_') === lowerCaseId) ||
(e.name && e.name.toLowerCase() === lowerCaseId) ||
(e.aliases && e.aliases.find((a: string) => a.toLowerCase() === lowerCaseId))
)
})

return entity || {}
}
35 changes: 2 additions & 33 deletions src/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,14 @@
import { EnumTypeDefinitionNode } from 'graphql'
import typeDefs from './type_defs/schema.graphql'
import allEntities from './data/entities/index'
// import allEntities from './data/entities/index'
import { RequestContext, ResolverDynamicConfig, SurveyConfig } from './types'
import {
computeTermAggregationAllYearsWithCache,
computeTermAggregationSingleYearWithCache
} from './compute'
import { Filters } from './filters'
import {loadOrGetEntities} from './entities'

export const getEntities = ({ type, tag, tags }: { type?: string; tag?: string, tags?: string[] }) => {
let entities = allEntities
if (type) {
entities = entities.filter(e => e.type === type)
}
if (tag) {
entities = entities.filter(e => e.tags && e.tags.includes(tag))
}
if (tags) {
entities = entities.filter(e => tags.every(t => e.tags && e.tags.includes(t)))
}
return entities
}

// Look up entities by id, name, or aliases (case-insensitive)
export const getEntity = ({ id }: { id: string }) => {
if (!id || typeof id !== 'string') {
return
}

const lowerCaseId = id.toLowerCase()
const entity = allEntities.find(e => {
return (
(e.id && e.id.toLowerCase() === lowerCaseId) ||
(e.id && e.id.toLowerCase().replace(/\-/g, '_') === lowerCaseId) ||
(e.name && e.name.toLowerCase() === lowerCaseId) ||
(e.aliases && e.aliases.find((a: string) => a.toLowerCase() === lowerCaseId))
)
})

return entity || {}
}

/**
* Return either e.g. other_tools.browsers.choices or other_tools.browsers.others_normalized
Expand Down
22 changes: 2 additions & 20 deletions src/i18n.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import { EnumTypeDefinitionNode } from 'graphql'
import { Entity, StringFile, Locale, TranslationStringObject } from './types'
import entities from './data/entities/index'
import typeDefs from './type_defs/schema.graphql'
import { Octokit } from '@octokit/core'
import fetch from 'node-fetch'
Expand All @@ -10,6 +9,7 @@ import marked from 'marked'
import { logToFile } from './debug'
import { readdir, readFile } from 'fs/promises'
import last from 'lodash/last'
import { loadOrGetEntities } from './entities'

let locales: Locale[] = []

Expand Down Expand Up @@ -68,6 +68,7 @@ export const loadFromGitHub = async (localesWithRepos: any) => {
}
return locales
}

// when developing locally, load from local files
export const loadLocally = async (localesWithRepos: any) => {
let i = 0
Expand Down Expand Up @@ -119,25 +120,6 @@ export const loadLocales = async () => {
return locales
}

// Look up entities by id, name, or aliases (case-insensitive)
export const getEntity = ({ id }: { id: string }) => {
if (!id || typeof id !== 'string') {
return
}

const lowerCaseId = id.toLowerCase()
const entity = entities.find(e => {
return (
(e.id && e.id.toLowerCase() === lowerCaseId) ||
(e.id && e.id.toLowerCase().replace(/\-/g, '_') === lowerCaseId) ||
(e.name && e.name.toLowerCase() === lowerCaseId) ||
(e.aliases && e.aliases.find((a: string) => a.toLowerCase() === lowerCaseId))
)
})

return entity || {}
}

/**
* Return either e.g. other_tools.browsers.choices or other_tools.browsers.others_normalized
*/
Expand Down
6 changes: 4 additions & 2 deletions src/resolvers/features.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Db } from 'mongodb'
import { useCache } from '../caching'
import { fetchMdnResource } from '../external_apis'
import features from '../data/entities/features.yml'
import { RequestContext, SurveyConfig } from '../types'
import { computeTermAggregationByYear } from '../compute'
import { Filters } from '../filters'
import { Entity } from '../types'
import { getEntities } from '../entities'

const computeFeatureExperience = async (
db: Db,
Expand All @@ -32,12 +32,14 @@ export default {
}
},
Feature: {
name: ({ id }: { id: string }) => {
name: async ({ id }: { id: string }) => {
const features = await getEntities({ tag: 'feature' })
const feature = features.find((f: Entity) => f.id === id)

return feature && feature.name
},
mdn: async ({ id }: { id: string }) => {
const features = await getEntities({ tag: 'feature' })
const feature = features.find((f: Entity) => f.id === id)
if (!feature || !feature.mdn) {
return
Expand Down
4 changes: 3 additions & 1 deletion src/resolvers/features_others.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
import { Db } from 'mongodb'
import features from '../data/entities/features.yml'
import { useCache } from '../caching'
import { computeTermAggregationByYear } from '../compute'
import { getOtherKey } from '../helpers'
import { RequestContext, SurveyConfig } from '../types'
import { Filters } from '../filters'
import { Entity } from '../types'
import { getEntities } from '../entities'

interface OtherFeaturesConfig {
survey: SurveyConfig
Expand All @@ -19,6 +19,8 @@ const computeOtherFeatures = async (
id: string,
filters?: Filters
) => {
const features = await getEntities({ tag: 'feature'})

const otherFeaturesByYear = await useCache(computeTermAggregationByYear, db, [
survey,
`features_others.${getOtherKey(id)}`,
Expand Down
2 changes: 1 addition & 1 deletion src/resolvers/query.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { SurveyType } from '../types'
import { getEntities, getEntity } from '../helpers'
import { getEntities, getEntity } from '../entities'
import { getLocales, getLocaleObject, getTranslation } from '../i18n'
import { SurveyConfig } from '../types'

Expand Down
44 changes: 23 additions & 21 deletions src/resolvers/surveys.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
import { getEntity, getGraphQLEnumValues, getDemographicsResolvers } from '../helpers'
import { getGraphQLEnumValues, getDemographicsResolvers } from '../helpers'
import { getEntity } from '../entities'
import { RequestContext, SurveyConfig } from '../types'
import { Filters } from '../filters'
import {computeToolExperienceGraph, computeToolsCardinalityByUser, ToolExperienceId} from '../compute'
import {
computeToolExperienceGraph,
computeToolsCardinalityByUser,
ToolExperienceId
} from '../compute'
import { useCache } from '../caching'

const toolIds = getGraphQLEnumValues('ToolID')
Expand Down Expand Up @@ -77,10 +82,7 @@ export default {
id,
filters
}),
happiness: (
survey: SurveyConfig,
{ id, filters }: { id: string; filters?: Filters }
) => ({
happiness: (survey: SurveyConfig, { id, filters }: { id: string; filters?: Filters }) => ({
survey,
id,
filters
Expand Down Expand Up @@ -141,20 +143,20 @@ export default {
{ db }: RequestContext
) => useCache(computeToolExperienceGraph, db, [survey, id, filters])
})),
tools_cardinality_by_user: (survey: SurveyConfig, {
year,
// tool IDs
ids,
experienceId,
}: {
year: number
ids: string[]
experienceId: ToolExperienceId
}, context: RequestContext) => useCache(
computeToolsCardinalityByUser,
context.db,
[survey, year, ids, experienceId]
),
tools_cardinality_by_user: (
survey: SurveyConfig,
{
year,
// tool IDs
ids,
experienceId
}: {
year: number
ids: string[]
experienceId: ToolExperienceId
},
context: RequestContext
) => useCache(computeToolsCardinalityByUser, context.db, [survey, year, ids, experienceId]),
tools_others: (
survey: SurveyConfig,
{ id, filters }: { id: string; filters?: Filters }
Expand All @@ -171,6 +173,6 @@ export default {
ids,
filters
}),
totals: (survey: SurveyConfig) => survey,
totals: (survey: SurveyConfig) => survey
}
}
Loading

0 comments on commit b0277f4

Please sign in to comment.