@things-factory/font-base 8.0.0-beta.8 → 8.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +5 -5
- package/server/controllers/google-fonts.ts +28 -0
- package/server/index.ts +4 -0
- package/server/migrations/1556862253039-SeedFont.ts +39 -0
- package/server/migrations/index.ts +9 -0
- package/server/routes.ts +8 -0
- package/server/service/font/font-mutation.ts +126 -0
- package/server/service/font/font-query.ts +62 -0
- package/server/service/font/font-type.ts +56 -0
- package/server/service/font/font.ts +84 -0
- package/server/service/font/index.ts +6 -0
- package/server/service/index.ts +20 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@things-factory/font-base",
|
|
3
|
-
"version": "8.0.0
|
|
3
|
+
"version": "8.0.0",
|
|
4
4
|
"main": "dist-server/index.js",
|
|
5
5
|
"browser": "client/index.js",
|
|
6
6
|
"things-factory": true,
|
|
@@ -24,9 +24,9 @@
|
|
|
24
24
|
"migration:create": "node ../../node_modules/typeorm/cli.js migration:create ./server/migrations/migration"
|
|
25
25
|
},
|
|
26
26
|
"dependencies": {
|
|
27
|
-
"@things-factory/attachment-base": "^8.0.0
|
|
28
|
-
"@things-factory/auth-base": "^8.0.0
|
|
29
|
-
"@things-factory/shell": "^8.0.0
|
|
27
|
+
"@things-factory/attachment-base": "^8.0.0",
|
|
28
|
+
"@things-factory/auth-base": "^8.0.0",
|
|
29
|
+
"@things-factory/shell": "^8.0.0"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "07ef27d272dd9a067a9648ac7013748510556a18"
|
|
32
32
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { config } from '@things-factory/env'
|
|
2
|
+
import fetch from 'node-fetch'
|
|
3
|
+
|
|
4
|
+
const address = 'https://www.googleapis.com/webfonts/v1/webfonts?key='
|
|
5
|
+
|
|
6
|
+
export async function getAllGoogleFonts() {
|
|
7
|
+
var key = config.get('googleFontAPIKey')
|
|
8
|
+
if (!key) {
|
|
9
|
+
console.warn(
|
|
10
|
+
"[things-factory/font-base] Could not read API key. Please check 'googleFontAPIKey' property in your configuration."
|
|
11
|
+
)
|
|
12
|
+
return []
|
|
13
|
+
}
|
|
14
|
+
var response = await fetch(`${address}${key}`)
|
|
15
|
+
if (response.ok) {
|
|
16
|
+
return (await response.json()).items.map(font => font.family)
|
|
17
|
+
} else {
|
|
18
|
+
let errorMsg = ''
|
|
19
|
+
errorMsg += `[things-factory/font-base] ${response.status} - ${response.statusText}.`
|
|
20
|
+
switch (response.status) {
|
|
21
|
+
case 400:
|
|
22
|
+
errorMsg += '\nYour API key may be incorrect or expired.'
|
|
23
|
+
break
|
|
24
|
+
}
|
|
25
|
+
console.warn(errorMsg)
|
|
26
|
+
return []
|
|
27
|
+
}
|
|
28
|
+
}
|
package/server/index.ts
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { MigrationInterface, QueryRunner } from 'typeorm'
|
|
2
|
+
|
|
3
|
+
import { Domain, getRepository } from '@things-factory/shell'
|
|
4
|
+
|
|
5
|
+
import { Font } from '../service/font/font'
|
|
6
|
+
|
|
7
|
+
const SEED_FONTS = ['Roboto', 'Pangolin', 'Railway', 'Slabo', 'Skranji']
|
|
8
|
+
|
|
9
|
+
export class seedFonts1556862253039 implements MigrationInterface {
|
|
10
|
+
public async up(queryRunner: QueryRunner): Promise<any> {
|
|
11
|
+
const repository = getRepository(Font)
|
|
12
|
+
const domainRepository = getRepository(Domain)
|
|
13
|
+
const domain = await domainRepository.findOneBy({
|
|
14
|
+
name: 'SYSTEM'
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
return await Promise.all(
|
|
18
|
+
SEED_FONTS.map(async font => {
|
|
19
|
+
await repository.save({
|
|
20
|
+
name: font,
|
|
21
|
+
domain,
|
|
22
|
+
provider: 'google',
|
|
23
|
+
uri: '',
|
|
24
|
+
path: '',
|
|
25
|
+
active: true
|
|
26
|
+
})
|
|
27
|
+
})
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
public async down(queryRunner: QueryRunner): Promise<any> {
|
|
32
|
+
const repository = getRepository(Font)
|
|
33
|
+
|
|
34
|
+
SEED_FONTS.reverse().forEach(async font => {
|
|
35
|
+
let record = await repository.findOneBy({ name: font })
|
|
36
|
+
await repository.remove(record)
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
const glob = require('glob')
|
|
2
|
+
const path = require('path')
|
|
3
|
+
|
|
4
|
+
export var migrations = []
|
|
5
|
+
|
|
6
|
+
glob.sync(path.resolve(__dirname, '.', '**', '*.js')).forEach(function(file) {
|
|
7
|
+
if (file.indexOf('index.js') !== -1) return
|
|
8
|
+
migrations = migrations.concat(Object.values(require(path.resolve(file))) || [])
|
|
9
|
+
})
|
package/server/routes.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { getAllGoogleFonts } from './controllers/google-fonts'
|
|
2
|
+
|
|
3
|
+
process.on('bootstrap-module-global-public-route' as any, (app, routes) => {
|
|
4
|
+
routes.get('/all-google-fonts', async (context, next) => {
|
|
5
|
+
context.type = 'application/json'
|
|
6
|
+
context.body = await getAllGoogleFonts()
|
|
7
|
+
})
|
|
8
|
+
})
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { Arg, Ctx, Mutation, Resolver, Root } from 'type-graphql'
|
|
2
|
+
|
|
3
|
+
import { createAttachments, deleteAttachmentsByRef } from '@things-factory/attachment-base'
|
|
4
|
+
import { getRepository, pubsub } from '@things-factory/shell'
|
|
5
|
+
|
|
6
|
+
import { Font } from './font'
|
|
7
|
+
import { FontPatch, NewFont } from './font-type'
|
|
8
|
+
|
|
9
|
+
function notifyChanges(event, domain, font) {
|
|
10
|
+
const { name, provider, uri, path, active } = font
|
|
11
|
+
const { subdomain } = domain
|
|
12
|
+
pubsub.publish('notify-font-changed', {
|
|
13
|
+
event,
|
|
14
|
+
font: {
|
|
15
|
+
domain: {
|
|
16
|
+
subdomain
|
|
17
|
+
},
|
|
18
|
+
name,
|
|
19
|
+
provider,
|
|
20
|
+
uri,
|
|
21
|
+
path,
|
|
22
|
+
active
|
|
23
|
+
}
|
|
24
|
+
})
|
|
25
|
+
}
|
|
26
|
+
@Resolver(Font)
|
|
27
|
+
export class FontMutation {
|
|
28
|
+
@Mutation(returns => Font, { description: 'To create new Font' })
|
|
29
|
+
async createFont(@Root() _, @Arg('font') font: NewFont, @Ctx() context: ResolverContext): Promise<Font> {
|
|
30
|
+
const { domain, user } = context.state
|
|
31
|
+
|
|
32
|
+
const repository = getRepository(Font)
|
|
33
|
+
|
|
34
|
+
const created = await repository.save({
|
|
35
|
+
domain,
|
|
36
|
+
creator: user,
|
|
37
|
+
updater: user,
|
|
38
|
+
...font
|
|
39
|
+
})
|
|
40
|
+
|
|
41
|
+
if (font.files) {
|
|
42
|
+
await createAttachments(
|
|
43
|
+
_,
|
|
44
|
+
{
|
|
45
|
+
attachments: font.files.map(file => {
|
|
46
|
+
return {
|
|
47
|
+
file,
|
|
48
|
+
refType: Font.name,
|
|
49
|
+
refBy: created.id
|
|
50
|
+
}
|
|
51
|
+
})
|
|
52
|
+
},
|
|
53
|
+
context
|
|
54
|
+
)
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
notifyChanges('created', domain, created)
|
|
58
|
+
|
|
59
|
+
return created
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
@Mutation(returns => Font, { description: 'To modify Font information' })
|
|
63
|
+
async updateFont(
|
|
64
|
+
@Root() _,
|
|
65
|
+
@Arg('id') id: string,
|
|
66
|
+
@Arg('patch') patch: FontPatch,
|
|
67
|
+
@Ctx() context: ResolverContext
|
|
68
|
+
): Promise<Font> {
|
|
69
|
+
const { domain, user } = context.state
|
|
70
|
+
|
|
71
|
+
const repository = getRepository(Font)
|
|
72
|
+
const font = await repository.findOne({
|
|
73
|
+
where: {
|
|
74
|
+
domain: { id: domain.id },
|
|
75
|
+
id
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
|
|
79
|
+
const updated = await repository.save({
|
|
80
|
+
...font,
|
|
81
|
+
...patch,
|
|
82
|
+
updater: user
|
|
83
|
+
})
|
|
84
|
+
|
|
85
|
+
if (patch.files) {
|
|
86
|
+
await deleteAttachmentsByRef(null, { refBys: [id] }, context)
|
|
87
|
+
await createAttachments(
|
|
88
|
+
_,
|
|
89
|
+
{
|
|
90
|
+
attachments: patch.files.map(file => {
|
|
91
|
+
return {
|
|
92
|
+
file,
|
|
93
|
+
refType: Font.name,
|
|
94
|
+
refBy: updated.id
|
|
95
|
+
}
|
|
96
|
+
})
|
|
97
|
+
},
|
|
98
|
+
context
|
|
99
|
+
)
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
notifyChanges('updated', domain, updated)
|
|
103
|
+
|
|
104
|
+
return updated
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
@Mutation(returns => Boolean, { description: 'To delete Font' })
|
|
108
|
+
async deleteFont(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<boolean> {
|
|
109
|
+
const { domain } = context.state
|
|
110
|
+
|
|
111
|
+
const repository = getRepository(Font)
|
|
112
|
+
const font = await repository.findOne({
|
|
113
|
+
where: { domain: { id: domain.id }, id }
|
|
114
|
+
})
|
|
115
|
+
|
|
116
|
+
if (font) {
|
|
117
|
+
await repository.remove(font)
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
await deleteAttachmentsByRef(null, { refBys: [id] }, context)
|
|
121
|
+
|
|
122
|
+
notifyChanges('removed', domain, font)
|
|
123
|
+
|
|
124
|
+
return true
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { In } from 'typeorm'
|
|
2
|
+
import { Arg, Args, Ctx, FieldResolver, Query, Resolver, Root } from 'type-graphql'
|
|
3
|
+
|
|
4
|
+
import { Attachment } from '@things-factory/attachment-base'
|
|
5
|
+
import { User } from '@things-factory/auth-base'
|
|
6
|
+
import { Domain, getQueryBuilderFromListParams, getRepository, ListParam } from '@things-factory/shell'
|
|
7
|
+
|
|
8
|
+
import { Font } from './font'
|
|
9
|
+
import { FontList } from './font-type'
|
|
10
|
+
|
|
11
|
+
@Resolver(Font)
|
|
12
|
+
export class FontQuery {
|
|
13
|
+
@Query(returns => Font, { description: 'To fetch a Font' })
|
|
14
|
+
async font(@Arg('id') id: string, @Ctx() context: ResolverContext): Promise<Font> {
|
|
15
|
+
const { domain } = context.state
|
|
16
|
+
|
|
17
|
+
return await getRepository(Font).findOne({
|
|
18
|
+
where: { domain: { id: In([domain.id, domain.parentId].filter(Boolean)) }, id }
|
|
19
|
+
})
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
@Query(returns => FontList, { description: 'To fetch multiple Fonts' })
|
|
23
|
+
async fonts(@Args(type => ListParam) params: ListParam, @Ctx() context: ResolverContext): Promise<FontList> {
|
|
24
|
+
const { domain } = context.state
|
|
25
|
+
|
|
26
|
+
const queryBuilder = getQueryBuilderFromListParams({
|
|
27
|
+
repository: getRepository(Font),
|
|
28
|
+
params,
|
|
29
|
+
domain,
|
|
30
|
+
searchables: ['name', 'description']
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
const [items, total] = await queryBuilder.getManyAndCount()
|
|
34
|
+
|
|
35
|
+
return { items, total }
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@FieldResolver(type => Domain)
|
|
39
|
+
async domain(@Root() font: Font) {
|
|
40
|
+
return await getRepository(Domain).findOneBy({ id: font.domainId })
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
@FieldResolver(type => Attachment)
|
|
44
|
+
async files(@Root() font: Font, @Ctx() context: ResolverContext) {
|
|
45
|
+
const { domain } = context.state
|
|
46
|
+
|
|
47
|
+
return await getRepository(Attachment).findBy({
|
|
48
|
+
domain: { id: domain.id },
|
|
49
|
+
refBy: font.id
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
@FieldResolver(type => User)
|
|
54
|
+
async updater(@Root() font: Font): Promise<User> {
|
|
55
|
+
return await getRepository(User).findOneBy({ id: font.updaterId })
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@FieldResolver(type => User)
|
|
59
|
+
async creator(@Root() font: Font): Promise<User> {
|
|
60
|
+
return await getRepository(User).findOneBy({ id: font.creatorId })
|
|
61
|
+
}
|
|
62
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import type { FileUpload } from 'graphql-upload/GraphQLUpload.js'
|
|
2
|
+
import GraphQLUpload from 'graphql-upload/GraphQLUpload.js'
|
|
3
|
+
import { Field, InputType, Int, ObjectType } from 'type-graphql'
|
|
4
|
+
|
|
5
|
+
import { Font } from './font'
|
|
6
|
+
|
|
7
|
+
@InputType()
|
|
8
|
+
export class NewFont {
|
|
9
|
+
@Field()
|
|
10
|
+
name: string
|
|
11
|
+
|
|
12
|
+
@Field({ nullable: true })
|
|
13
|
+
provider?: string
|
|
14
|
+
|
|
15
|
+
@Field({ nullable: true })
|
|
16
|
+
uri?: string
|
|
17
|
+
|
|
18
|
+
@Field({ nullable: true })
|
|
19
|
+
path?: string
|
|
20
|
+
|
|
21
|
+
@Field(type => [GraphQLUpload], { nullable: true })
|
|
22
|
+
files?: FileUpload[]
|
|
23
|
+
|
|
24
|
+
@Field({ nullable: true })
|
|
25
|
+
active?: boolean
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
@InputType()
|
|
29
|
+
export class FontPatch {
|
|
30
|
+
@Field({ nullable: true })
|
|
31
|
+
name: string
|
|
32
|
+
|
|
33
|
+
@Field({ nullable: true })
|
|
34
|
+
provider?: string
|
|
35
|
+
|
|
36
|
+
@Field({ nullable: true })
|
|
37
|
+
uri?: string
|
|
38
|
+
|
|
39
|
+
@Field({ nullable: true })
|
|
40
|
+
path?: string
|
|
41
|
+
|
|
42
|
+
@Field(type => [GraphQLUpload], { nullable: true })
|
|
43
|
+
files?: FileUpload[]
|
|
44
|
+
|
|
45
|
+
@Field({ nullable: true })
|
|
46
|
+
active?: boolean
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
@ObjectType()
|
|
50
|
+
export class FontList {
|
|
51
|
+
@Field(type => [Font])
|
|
52
|
+
items: Font[]
|
|
53
|
+
|
|
54
|
+
@Field(type => Int)
|
|
55
|
+
total: number
|
|
56
|
+
}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { Field, ID, ObjectType } from 'type-graphql'
|
|
2
|
+
import {
|
|
3
|
+
Column,
|
|
4
|
+
CreateDateColumn,
|
|
5
|
+
Entity,
|
|
6
|
+
Index,
|
|
7
|
+
ManyToOne,
|
|
8
|
+
PrimaryGeneratedColumn,
|
|
9
|
+
RelationId,
|
|
10
|
+
UpdateDateColumn
|
|
11
|
+
} from 'typeorm'
|
|
12
|
+
|
|
13
|
+
import { Attachment } from '@things-factory/attachment-base'
|
|
14
|
+
import { User } from '@things-factory/auth-base'
|
|
15
|
+
import { Domain } from '@things-factory/shell'
|
|
16
|
+
|
|
17
|
+
@Entity()
|
|
18
|
+
@Index('ix_font_0', (font: Font) => [font.domain, font.name], { unique: true })
|
|
19
|
+
@ObjectType({ description: 'Entity for Font' })
|
|
20
|
+
export class Font {
|
|
21
|
+
@PrimaryGeneratedColumn('uuid')
|
|
22
|
+
@Field(type => ID)
|
|
23
|
+
readonly id: string
|
|
24
|
+
|
|
25
|
+
@ManyToOne(type => Domain)
|
|
26
|
+
@Field(type => Domain)
|
|
27
|
+
domain?: Domain
|
|
28
|
+
|
|
29
|
+
@RelationId((font: Font) => font.domain)
|
|
30
|
+
domainId?: string
|
|
31
|
+
|
|
32
|
+
@Column()
|
|
33
|
+
@Field()
|
|
34
|
+
name: string
|
|
35
|
+
|
|
36
|
+
@Column()
|
|
37
|
+
@Field()
|
|
38
|
+
provider: string // custom, typekit, google,
|
|
39
|
+
|
|
40
|
+
@Column({
|
|
41
|
+
nullable: true
|
|
42
|
+
})
|
|
43
|
+
@Field({ nullable: true })
|
|
44
|
+
uri?: string // For typekit, custom,
|
|
45
|
+
|
|
46
|
+
@Column({
|
|
47
|
+
nullable: true
|
|
48
|
+
})
|
|
49
|
+
@Field({ nullable: true })
|
|
50
|
+
path?: string // Uploaded path for custom
|
|
51
|
+
|
|
52
|
+
@Column()
|
|
53
|
+
@Field()
|
|
54
|
+
active: boolean
|
|
55
|
+
|
|
56
|
+
@Field(type => [Attachment], { nullable: true })
|
|
57
|
+
files?: Attachment[]
|
|
58
|
+
|
|
59
|
+
@CreateDateColumn()
|
|
60
|
+
@Field({ nullable: true })
|
|
61
|
+
createdAt?: Date
|
|
62
|
+
|
|
63
|
+
@UpdateDateColumn()
|
|
64
|
+
@Field({ nullable: true })
|
|
65
|
+
updatedAt?: Date
|
|
66
|
+
|
|
67
|
+
@ManyToOne(type => User, {
|
|
68
|
+
nullable: true
|
|
69
|
+
})
|
|
70
|
+
@Field(type => User, { nullable: true })
|
|
71
|
+
creator?: User
|
|
72
|
+
|
|
73
|
+
@RelationId((font: Font) => font.creator)
|
|
74
|
+
creatorId?: string
|
|
75
|
+
|
|
76
|
+
@ManyToOne(type => User, {
|
|
77
|
+
nullable: true
|
|
78
|
+
})
|
|
79
|
+
@Field(type => User, { nullable: true })
|
|
80
|
+
updater?: User
|
|
81
|
+
|
|
82
|
+
@RelationId((font: Font) => font.updater)
|
|
83
|
+
updaterId?: string
|
|
84
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/* IMPORT ENTITIES AND RESOLVERS */
|
|
2
|
+
import { entities as FontEntities, resolvers as FontResolvers } from './font'
|
|
3
|
+
|
|
4
|
+
/* EXPORT ENTITY TYPES */
|
|
5
|
+
export * from './font/font'
|
|
6
|
+
|
|
7
|
+
/* EXPORT TYPES */
|
|
8
|
+
export * from './font/font-type'
|
|
9
|
+
|
|
10
|
+
export const entities = [
|
|
11
|
+
/* ENTITIES */
|
|
12
|
+
...FontEntities
|
|
13
|
+
]
|
|
14
|
+
|
|
15
|
+
export const schema = {
|
|
16
|
+
resolverClasses: [
|
|
17
|
+
/* RESOLVER CLASSES */
|
|
18
|
+
...FontResolvers
|
|
19
|
+
]
|
|
20
|
+
}
|