@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@things-factory/font-base",
3
- "version": "8.0.0-beta.8",
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-beta.8",
28
- "@things-factory/auth-base": "^8.0.0-beta.8",
29
- "@things-factory/shell": "^8.0.0-beta.5"
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": "bf5206511b2d84dfb95edc3dae7f54f6cbb9bcca"
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
+ }
@@ -0,0 +1,4 @@
1
+ export * from './service'
2
+ export * from './migrations'
3
+
4
+ import './routes'
@@ -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
+ })
@@ -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,6 @@
1
+ import { Font } from './font'
2
+ import { FontQuery } from './font-query'
3
+ import { FontMutation } from './font-mutation'
4
+
5
+ export const entities = [Font]
6
+ export const resolvers = [FontQuery, FontMutation]
@@ -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
+ }