Skip to content
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
6 changes: 5 additions & 1 deletion .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,11 @@
"import/newline-after-import": "error",
"import/no-named-default": "error",
"import/no-anonymous-default-export": "error",
"import/dynamic-import-chunkname": "error"
"import/dynamic-import-chunkname": "error",
"@typescript-eslint/no-empty-function": [
"error",
{ "allow": ["decoratedFunctions"] }
]
},
"overrides": [
{
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ testem.log
Thumbs.db

#local .env files
.env
.env*local

# kube secrets
Expand Down
3 changes: 3 additions & 0 deletions apps/api-gateway/project.json
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@
},
{
"command": "nx serve api-gateway"
},
{
"command": "nx serve api-languages"
}
],
"parallel": true
Expand Down
19 changes: 19 additions & 0 deletions apps/api-gateway/schema.graphql
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ scalar join__FieldSet

enum join__Graph {
JOURNEYS @join__graph(name: "journeys" url: "http://127.0.0.1:4001/graphql")
LANGUAGES @join__graph(name: "languages" url: "http://127.0.0.1:4003/graphql")
USERS @join__graph(name: "users" url: "http://127.0.0.1:4002/graphql")
}

Expand Down Expand Up @@ -349,6 +350,16 @@ input JourneyUpdateInput {
title: String
}

type Language
@join__owner(graph: LANGUAGES)
@join__type(graph: LANGUAGES, key: "id")
{
bcp47: String @join__field(graph: LANGUAGES)
id: ID! @join__field(graph: LANGUAGES)
iso3: String @join__field(graph: LANGUAGES)
name(languageId: ID, primary: Boolean): [Translation]! @join__field(graph: LANGUAGES)
}

type LinkAction implements Action {
gtmEventName: String
parentBlockId: ID!
Expand Down Expand Up @@ -444,6 +455,8 @@ type Query {
adminJourneys: [Journey!]! @join__field(graph: JOURNEYS)
journey(id: ID!, idType: IdType): Journey @join__field(graph: JOURNEYS)
journeys: [Journey!]! @join__field(graph: JOURNEYS)
language(id: ID!): Language @join__field(graph: LANGUAGES)
languages(limit: Int, page: Int): [Language!]! @join__field(graph: LANGUAGES)
me: User @join__field(graph: USERS)
}

Expand Down Expand Up @@ -596,6 +609,12 @@ enum ThemeName {
base
}

type Translation {
language: Language!
primary: Boolean!
value: String!
}

enum TypographyAlign {
center
left
Expand Down
4 changes: 4 additions & 0 deletions apps/api-gateway/supergraph.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,7 @@ subgraphs:
routing_url: http://127.0.0.1:4002/graphql
schema:
file: ../api-users/schema.graphql
languages:
routing_url: http://127.0.0.1:4003/graphql
schema:
file: ../api-languages/schema.graphql
2 changes: 2 additions & 0 deletions apps/api-languages/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
DATABASE_URL="arangodb://arangodb:8529"
ARCLIGHT_API_KEY=
21 changes: 21 additions & 0 deletions apps/api-languages/.eslintrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"extends": ["../../.eslintrc.json"],
"ignorePatterns": ["!**/*"],
"overrides": [
{
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
"rules": {}
},
{
"files": ["*.ts", "*.tsx"],
"parserOptions": {
"project": ["apps/api-languages/tsconfig.*?.json"]
},
"rules": {}
},
{
"files": ["*.js", "*.jsx"],
"rules": {}
}
]
}
8 changes: 8 additions & 0 deletions apps/api-languages/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
FROM node:14-alpine
WORKDIR /app
COPY ./dist/apps/api-languages .
EXPOSE 4003
# dependencies that nestjs needs
RUN npm install --production --silent
RUN npm install tslib apollo-server-express @nestjs/mapped-types
CMD node ./main.js
13 changes: 13 additions & 0 deletions apps/api-languages/db/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { Database } from 'arangojs'

export function ArangoDB(): Database {
let db: Database
if (process.env.DATABASE_DB != null)
db = new Database({
url: process.env.DATABASE_URL,
databaseName: process.env.DATABASE_DB
})
else db = new Database({ url: process.env.DATABASE_URL })
db.useBasicAuth(process.env.DATABASE_USER, process.env.DATABASE_PASS)
return db
}
132 changes: 132 additions & 0 deletions apps/api-languages/db/seed.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import { aql } from 'arangojs'
import { isEmpty } from 'lodash'
import fetch from 'node-fetch'
import { ArangoDB } from './db'

interface Language {
_key: string
name: Array<{ value: string; languageId: string; primary: boolean }>
bcp47?: string
iso3?: string
}

interface MediaLanguage {
languageId: number
bcp47?: string
iso3?: string
nameNative: string
metadataLanguageTag: string
name: string
}

const db = ArangoDB()

async function getLanguage(languageId: string): Promise<Language | undefined> {
const rst = await db.query(aql`
FOR item IN ${db.collection('languages')}
FILTER item._key == ${languageId}
LIMIT 1
RETURN item`)
return await rst.next()
}

async function getLanguageByBcp47(
bcp47: string
): Promise<Language | undefined> {
const rst = await db.query(aql`
FOR item IN ${db.collection('languages')}
FILTER item.bcp47 == ${bcp47}
LIMIT 1
RETURN item`)
return await rst.next()
}

async function getMediaLanguages(): Promise<MediaLanguage[]> {
const response: {
_embedded: { mediaLanguages: MediaLanguage[] }
} = await (
await fetch(
`https://api.arclight.org/v2/media-languages?limit=5000&apiKey=${
process.env.ARCLIGHT_API_KEY ?? ''
}`
)
).json()
return response._embedded.mediaLanguages
}

async function digestMediaLanguage(
mediaLanguage: MediaLanguage
): Promise<void> {
const { languageId, bcp47, iso3, nameNative } = mediaLanguage
const body: Omit<Language, '_key'> = {
bcp47: isEmpty(bcp47) ? undefined : bcp47,
iso3: isEmpty(iso3) ? undefined : iso3,
name: [
{
value: nameNative,
languageId: languageId.toString(),
primary: true
}
]
}
const language = await getLanguage(languageId.toString())

if (language != null) {
await db.collection('languages').update(languageId.toString(), body)
} else {
await db
.collection('languages')
.save({ _key: languageId.toString(), ...body })
}
}

async function digestMediaLanguageMetadata(
mediaLanguage: MediaLanguage
): Promise<void> {
const { languageId, metadataLanguageTag, name } = mediaLanguage
const language = await getLanguage(languageId.toString())
if (language == null) return

const metadataLanguage = await getLanguageByBcp47(metadataLanguageTag)
if (metadataLanguage == null) return

if (
language.name.find(
({ languageId }) => languageId === metadataLanguage._key
) != null
)
return

const body: Omit<Language, '_key'> = {
name: [
...language.name,
{
value: name,
languageId: metadataLanguage._key,
primary: false
}
]
}
await db.collection('languages').update(languageId.toString(), body)
}

async function main(): Promise<void> {
try {
await db.createCollection('languages', { keyOptions: { type: 'uuid' } })
} catch {}
const mediaLanguages = await getMediaLanguages()

for (const mediaLanguage of mediaLanguages) {
console.log('language:', mediaLanguage.languageId)
Comment thread
tataihono marked this conversation as resolved.
await digestMediaLanguage(mediaLanguage)
}

for (const mediaLanguage of mediaLanguages) {
await digestMediaLanguageMetadata(mediaLanguage)
Comment thread
tataihono marked this conversation as resolved.
}
}

main().catch((e) => {
console.error(e)
process.exit(1)
})
1 change: 1 addition & 0 deletions apps/api-languages/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './src/app/__generated__/graphql'
15 changes: 15 additions & 0 deletions apps/api-languages/jest.config.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
module.exports = {
displayName: 'api-languages',
preset: '../../jest.preset.js',
globals: {
'ts-jest': {
tsconfig: '<rootDir>/tsconfig.spec.json'
}
},
testEnvironment: 'node',
transform: {
'^.+\\.[tj]s$': 'ts-jest'
},
moduleFileExtensions: ['ts', 'js', 'html'],
coverageDirectory: '../../coverage/apps/api-languages'
}
90 changes: 90 additions & 0 deletions apps/api-languages/project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
{
"root": "apps/api-languages",
"sourceRoot": "apps/api-languages/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nrwl/node:build",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/api-languages",
"main": "apps/api-languages/src/main.ts",
"tsConfig": "apps/api-languages/tsconfig.app.json",
"assets": [
"apps/api-languages/src/assets",
{
"glob": "**/*.graphql",
"input": "apps/api-languages/src/app/",
"output": "./assets"
}
],
"generatePackageJson": true
},
"configurations": {
"production": {
"optimization": true,
"extractLicenses": true,
"inspect": false,
"fileReplacements": [
{
"replace": "apps/api-languages/src/environments/environment.ts",
"with": "apps/api-languages/src/environments/environment.prod.ts"
}
]
}
}
},
"seed": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"command": "npx ts-node apps/api-languages/db/seed.ts"
}
},
"serve-nowatch": {
"executor": "@nrwl/node:execute",
"options": {
"buildTarget": "api-languages:build"
}
},
"serve": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "nx serve-nowatch api-languages"
},
{
"command": "npx ts-node apps/api-languages/src/generate-typings.ts"
}
],
"parallel": true
}
},
"lint": {
"executor": "@nrwl/linter:eslint",
"outputs": ["{options.outputFile}"],
"options": {
"lintFilePatterns": ["apps/api-languages/**/*.ts"]
}
},
"test": {
"executor": "@nrwl/jest:jest",
"outputs": ["coverage/apps/api-languages"],
"options": {
"jestConfig": "apps/api-languages/jest.config.js",
"passWithNoTests": true
}
},
"generate-graphql": {
"executor": "@nrwl/workspace:run-commands",
"options": {
"commands": [
{
"command": "rover subgraph introspect http://localhost:4003/graphql > apps/api-languages/schema.graphql"
}
]
}
}
},
"tags": []
}
17 changes: 17 additions & 0 deletions apps/api-languages/schema.graphql
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
type Language @key(fields: "id") {
id: ID!
bcp47: String
iso3: String
name(languageId: ID, primary: Boolean): [Translation]!
}

type Translation {
value: String!
language: Language!
primary: Boolean!
}

extend type Query {
languages(page: Int, limit: Int): [Language!]!
language(id: ID!): Language
}
Empty file.
Loading