feat!: add xlog fn and builtIn on snippets model
Signed-off-by: Innei <tukon479@gmail.com>
This commit is contained in:
@@ -26,7 +26,7 @@ module.exports = {
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['src/migration/**/*.ts'],
|
||||
files: ['src/migration/**/*.ts', 'src/modules/serverless/pack/**/*.ts'],
|
||||
rules: {
|
||||
'import/no-default-export': 'off',
|
||||
},
|
||||
|
||||
@@ -66,4 +66,7 @@ export const generateDefaultConfig: () => IConfig = () => ({
|
||||
featureList: {
|
||||
emailSubscribe: false,
|
||||
},
|
||||
thirdPartyServiceIntegration: {
|
||||
xLogSiteId: '',
|
||||
},
|
||||
})
|
||||
|
||||
@@ -336,3 +336,16 @@ export class FeatureListDto {
|
||||
@IsOptional()
|
||||
emailSubscribe: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* 第三方服务集成
|
||||
*/
|
||||
@JSONSchema({ title: '第三方服务集成' })
|
||||
export class ThirdPartyServiceIntegrationDto {
|
||||
@JSONSchemaPlainField('xLog SiteId', {
|
||||
description: '文章发布同步到 [xLog](https://xlog.app)',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
xLogSiteId?: string
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import {
|
||||
SeoDto,
|
||||
TerminalOptionsDto,
|
||||
TextOptionsDto,
|
||||
ThirdPartyServiceIntegrationDto,
|
||||
UrlDto,
|
||||
} from './configs.dto'
|
||||
|
||||
@@ -72,6 +73,10 @@ export abstract class IConfig {
|
||||
@Type(() => FeatureListDto)
|
||||
@ValidateNested()
|
||||
featureList: Required<FeatureListDto>
|
||||
|
||||
@Type(() => ThirdPartyServiceIntegrationDto)
|
||||
@ValidateNested()
|
||||
thirdPartyServiceIntegration: Required<ThirdPartyServiceIntegrationDto>
|
||||
}
|
||||
|
||||
export type IConfigKeys = keyof IConfig
|
||||
|
||||
@@ -15,4 +15,8 @@ export interface BuiltInFunctionObject {
|
||||
path: string
|
||||
method: string
|
||||
code: string
|
||||
reference: string
|
||||
}
|
||||
|
||||
export const defineBuiltInSnippetConfig = (config: BuiltInFunctionObject) =>
|
||||
config
|
||||
|
||||
4
src/modules/serverless/pack/index.ts
Normal file
4
src/modules/serverless/pack/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
import { builtInSnippets } from './built-in'
|
||||
import { xLogPackSnippets } from './xlog'
|
||||
|
||||
export const allBuiltInSnippetPack = [...xLogPackSnippets, ...builtInSnippets]
|
||||
20
src/modules/serverless/pack/xlog/get_page_id.ts
Normal file
20
src/modules/serverless/pack/xlog/get_page_id.ts
Normal file
@@ -0,0 +1,20 @@
|
||||
import { defineBuiltInSnippetConfig } from '../../function.types'
|
||||
|
||||
export default defineBuiltInSnippetConfig({
|
||||
name: 'getPageId',
|
||||
method: 'GET',
|
||||
code: `import axios from 'axios';
|
||||
|
||||
export default async function handler(ctx: Context) {
|
||||
const { req } = ctx
|
||||
const { query } = req
|
||||
const { slug, handle } = query
|
||||
return axios.get('https://xlog.app/api/slug2id', {
|
||||
params: {
|
||||
slug, handle
|
||||
}
|
||||
}).then(data => data.data).catch(err => ({ err }))
|
||||
}`,
|
||||
path: 'get_page_id',
|
||||
reference: 'xlog',
|
||||
})
|
||||
3
src/modules/serverless/pack/xlog/index.ts
Normal file
3
src/modules/serverless/pack/xlog/index.ts
Normal file
@@ -0,0 +1,3 @@
|
||||
import get_page_id from './get_page_id'
|
||||
|
||||
export const xLogPackSnippets = [get_page_id]
|
||||
@@ -118,11 +118,12 @@ export class ServerlessController {
|
||||
@Delete('/reset/:id')
|
||||
@Auth()
|
||||
async resetBuiltInFunction(@Param('id') id: string) {
|
||||
const isBuiltin = await this.serverlessService.isBuiltInFunction(id)
|
||||
if (!isBuiltin) {
|
||||
const builtIn = await this.serverlessService.isBuiltInFunction(id)
|
||||
if (!builtIn) {
|
||||
throw new BadRequestException('can not reset a non-builtin function')
|
||||
}
|
||||
await this.serverlessService.resetBuiltInFunction(isBuiltin)
|
||||
await this.serverlessService.resetBuiltInFunction(builtIn)
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -41,7 +41,7 @@ import {
|
||||
FunctionContextRequest,
|
||||
FunctionContextResponse,
|
||||
} from './function.types'
|
||||
import { builtInSnippets } from './pack/built-in'
|
||||
import { allBuiltInSnippetPack as builtInSnippets } from './pack'
|
||||
import { ServerlessStorageCollectionName } from './serverless.model'
|
||||
import { complieTypeScriptBabelOptions, hashStable } from './serverless.util'
|
||||
|
||||
@@ -671,41 +671,54 @@ export class ServerlessService implements OnModuleInit {
|
||||
|
||||
private async pourBuiltInFunctions() {
|
||||
const paths = [] as string[]
|
||||
const references = new Set<string>()
|
||||
const pathCodeMap = new Map<string, BuiltInFunctionObject>()
|
||||
for (const s of builtInSnippets) {
|
||||
paths.push(s.path)
|
||||
pathCodeMap.set(s.path, s)
|
||||
if (s.reference) {
|
||||
references.add(s.reference)
|
||||
}
|
||||
}
|
||||
|
||||
// 0. get built-in functions is exist in db
|
||||
const result = await this.model
|
||||
.find({
|
||||
name: {
|
||||
$in: paths,
|
||||
},
|
||||
reference: 'built-in',
|
||||
type: SnippetType.Function,
|
||||
})
|
||||
.lean()
|
||||
const result = await this.model.find({
|
||||
name: {
|
||||
$in: paths,
|
||||
},
|
||||
// FIXME reference not only `built-in` now
|
||||
reference: {
|
||||
$in: ['built-in'].concat(Array.from(references.values())),
|
||||
},
|
||||
type: SnippetType.Function,
|
||||
})
|
||||
|
||||
// 1. filter is exist
|
||||
const migrationTasks = [] as Promise<any>[]
|
||||
for (const doc of result) {
|
||||
const path = doc.name
|
||||
pathCodeMap.delete(path)
|
||||
|
||||
// migration, add builtIn set to `true`
|
||||
if (!doc.builtIn) {
|
||||
migrationTasks.push(doc.updateOne({ builtIn: true }))
|
||||
}
|
||||
}
|
||||
await Promise.all(migrationTasks)
|
||||
|
||||
// 2. pour
|
||||
|
||||
for (const [path, { code, method, name }] of pathCodeMap) {
|
||||
for (const [path, { code, method, name, reference }] of pathCodeMap) {
|
||||
this.logger.log(`pour built-in function: ${name}`)
|
||||
await this.model.create({
|
||||
type: SnippetType.Function,
|
||||
name: path,
|
||||
reference: 'built-in',
|
||||
reference: reference || 'built-in',
|
||||
raw: code,
|
||||
method: method || 'get',
|
||||
enable: true,
|
||||
private: false,
|
||||
builtIn: true,
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -717,14 +730,21 @@ export class ServerlessService implements OnModuleInit {
|
||||
})
|
||||
.lean()
|
||||
if (!document) return false
|
||||
const isBuiltin =
|
||||
document.type == SnippetType.Function && document.reference == 'built-in'
|
||||
return isBuiltin ? document.name : false
|
||||
const isBuiltin = document.type == SnippetType.Function && document.builtIn
|
||||
return isBuiltin
|
||||
? {
|
||||
name: document.name,
|
||||
reference: document.reference || 'built-in',
|
||||
}
|
||||
: false
|
||||
}
|
||||
|
||||
async resetBuiltInFunction(name: string) {
|
||||
const builtIn = builtInSnippets.find((s) => s.path == name)
|
||||
if (!builtIn) {
|
||||
async resetBuiltInFunction(model: { name: string; reference: string }) {
|
||||
const { name, reference } = model
|
||||
const builtInSnippet = builtInSnippets.find(
|
||||
(s) => s.path === name && s.reference === reference,
|
||||
)
|
||||
if (!builtInSnippet) {
|
||||
throw new InternalServerErrorException('built-in function not found')
|
||||
}
|
||||
|
||||
@@ -732,7 +752,7 @@ export class ServerlessService implements OnModuleInit {
|
||||
{
|
||||
name,
|
||||
},
|
||||
{ raw: builtIn.code },
|
||||
{ raw: builtInSnippet.code },
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,4 +115,9 @@ export class SnippetModel extends BaseModel {
|
||||
enable?: boolean
|
||||
|
||||
updated?: string
|
||||
|
||||
@prop({
|
||||
default: false,
|
||||
})
|
||||
builtIn?: boolean
|
||||
}
|
||||
|
||||
@@ -4,7 +4,12 @@ import { render } from 'ejs'
|
||||
import { createTransport } from 'nodemailer'
|
||||
import Mail from 'nodemailer/lib/mailer'
|
||||
|
||||
import { Injectable, Logger, OnModuleInit } from '@nestjs/common'
|
||||
import {
|
||||
Injectable,
|
||||
Logger,
|
||||
OnModuleDestroy,
|
||||
OnModuleInit,
|
||||
} from '@nestjs/common'
|
||||
import { OnEvent } from '@nestjs/event-emitter'
|
||||
|
||||
import { BizException } from '~/common/exceptions/biz.exception'
|
||||
@@ -29,7 +34,7 @@ export enum LinkApplyEmailType {
|
||||
}
|
||||
|
||||
@Injectable()
|
||||
export class EmailService implements OnModuleInit {
|
||||
export class EmailService implements OnModuleInit, OnModuleDestroy {
|
||||
private instance: ReturnType<typeof createTransport>
|
||||
private logger: Logger
|
||||
constructor(
|
||||
@@ -49,6 +54,10 @@ export class EmailService implements OnModuleInit {
|
||||
}
|
||||
}
|
||||
|
||||
onModuleDestroy() {
|
||||
this.teardown()
|
||||
}
|
||||
|
||||
async readTemplate(
|
||||
type: ReplyMailType | NewsletterMailType,
|
||||
): Promise<string> {
|
||||
@@ -116,10 +125,16 @@ export class EmailService implements OnModuleInit {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
teardown() {
|
||||
this.instance?.close?.()
|
||||
}
|
||||
|
||||
@OnEvent(EventBusEvents.EmailInit)
|
||||
init() {
|
||||
this.getConfigFromConfigService()
|
||||
.then((config) => {
|
||||
this.teardown()
|
||||
this.instance = createTransport({
|
||||
...config,
|
||||
secure: true,
|
||||
|
||||
Reference in New Issue
Block a user