mirror of
https://github.com/roleypoly/roleypoly-v1.git
synced 2025-04-25 12:19:10 +00:00
temp commit
This commit is contained in:
parent
e86f7ff68e
commit
6fb39d6c4d
22 changed files with 282 additions and 39 deletions
|
@ -11,3 +11,4 @@
|
|||
esproposal.optional_chaining=enable
|
||||
munge_underscores=true
|
||||
emoji=true
|
||||
esproposal.export_star_as=enable
|
|
@ -1,6 +1,5 @@
|
|||
// @flow
|
||||
import Eris, { type Message, type TextChannel } from 'eris'
|
||||
import logger from './logger.js'
|
||||
import Eris, { type Message, type TextChannel, type Guild } from 'eris'
|
||||
import RPCClient from '@roleypoly/rpc-client'
|
||||
import randomEmoji from './random-emoji'
|
||||
import DMCommands from './commands/dm'
|
||||
|
@ -8,6 +7,8 @@ import TextCommands from './commands/text'
|
|||
import RootCommands from './commands/root'
|
||||
import type { Command } from './commands/_types'
|
||||
import retry from 'async-retry'
|
||||
|
||||
import logger from './logger'
|
||||
const log = logger(__filename)
|
||||
|
||||
export type BotConfig = $Shape<{
|
||||
|
@ -228,8 +229,18 @@ export default class Bot {
|
|||
}
|
||||
}
|
||||
|
||||
async syncGuild (type: string, guild: Guild) {
|
||||
await this.rpc.syncGuild(type, guild.id)
|
||||
}
|
||||
|
||||
async start () {
|
||||
this.client.on('messageCreate', this.handleMessage)
|
||||
|
||||
const guildSyncTriggers = ['guildCreate', 'guildDelete', 'guildRoleAdd', 'guildRoleDelete', 'guildRoleUpdate']
|
||||
for (const trigger of guildSyncTriggers) {
|
||||
this.client.on(trigger, this.syncGuild.bind(this, trigger))
|
||||
}
|
||||
|
||||
await this.client.connect()
|
||||
log.info('started bot')
|
||||
}
|
||||
|
|
|
@ -7,7 +7,6 @@
|
|||
"dev": "yarn build --watch"
|
||||
},
|
||||
"dependencies": {
|
||||
"@roleypoly/rpc-client": "2.0.0",
|
||||
"async-retry": "^1.2.3",
|
||||
"dotenv": "^7.0.0",
|
||||
"eris": "^0.9.0"
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
"dev": "yarn build --watch",
|
||||
"postinstall": "test -d lib || npm run build"
|
||||
},
|
||||
"types": "src/",
|
||||
"types": "src/index.js",
|
||||
"main": "lib/index.js",
|
||||
"files": ["lib"],
|
||||
"dependencies": {
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
// @flow
|
||||
import superagent from 'superagent'
|
||||
import RPCError from './error'
|
||||
import RPCError from './error.js'
|
||||
import retry from 'async-retry'
|
||||
|
||||
export { RPCError }
|
||||
|
||||
export type RPCResponse = {
|
||||
response?: mixed,
|
||||
hash?: string,
|
||||
|
|
11
packages/roleypoly-rpc-server/.babelrc
Normal file
11
packages/roleypoly-rpc-server/.babelrc
Normal file
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"presets": [ ["@babel/preset-env", { "targets": {"node": "current"} }], "@babel/preset-flow" ],
|
||||
"plugins": [
|
||||
"@babel/plugin-syntax-dynamic-import",
|
||||
"@babel/plugin-proposal-class-properties",
|
||||
"@babel/plugin-proposal-optional-chaining",
|
||||
"@babel/plugin-proposal-export-namespace-from",
|
||||
["@babel/plugin-transform-runtime",
|
||||
{ "helpers": false }]
|
||||
]
|
||||
}
|
24
packages/roleypoly-rpc-server/package.json
Normal file
24
packages/roleypoly-rpc-server/package.json
Normal file
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"private": true,
|
||||
"name": "@roleypoly/rpc-server",
|
||||
"version": "2.0.0",
|
||||
"scripts": {
|
||||
"build": "babel -d ./lib ./src",
|
||||
"dev": "yarn build --watch",
|
||||
"postinstall": "test -d lib || npm run build"
|
||||
},
|
||||
"types": "src/index.js",
|
||||
"main": "lib/index.js",
|
||||
"files": [
|
||||
"lib"
|
||||
],
|
||||
"dependencies": {
|
||||
"async-retry": "^1.2.3",
|
||||
"glob": "^7.1.3",
|
||||
"nats": "^1.2.10"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/cli": "^7.4.3",
|
||||
"@babel/plugin-proposal-export-namespace-from": "^7.2.0"
|
||||
}
|
||||
}
|
|
@ -1,22 +1,21 @@
|
|||
// @flow
|
||||
import logger from '../logger'
|
||||
import logger from './logger'
|
||||
import glob from 'glob'
|
||||
import path from 'path'
|
||||
import { type AppContext } from '../Roleypoly'
|
||||
|
||||
const log = logger(__filename)
|
||||
const PROD: boolean = process.env.NODE_ENV === 'production'
|
||||
|
||||
export default (ctx: AppContext, forceClear: ?boolean = false): {
|
||||
export default (globString: string, ctx: any, forceClear: ?boolean = false): {
|
||||
[rpc: string]: Function
|
||||
} => {
|
||||
let map = {}
|
||||
const apis = glob.sync(`${__dirname}/**/!(index).js`).map(v => v.replace(__dirname, '.'))
|
||||
const apis = glob.sync(globString)
|
||||
log.debug('found rpcs', apis)
|
||||
|
||||
for (let a of apis) {
|
||||
const filename = path.basename(a)
|
||||
const dirname = path.dirname(a)
|
||||
// const dirname = path.dirname(a)
|
||||
|
||||
const pathname = a
|
||||
delete require.cache[require.resolve(pathname)]
|
||||
|
@ -27,11 +26,6 @@ export default (ctx: AppContext, forceClear: ?boolean = false): {
|
|||
continue
|
||||
}
|
||||
|
||||
if (dirname === 'client') {
|
||||
log.debug(`skipping ${a}`)
|
||||
continue
|
||||
}
|
||||
|
||||
// testing only
|
||||
if (filename.endsWith('_test.js') && PROD) {
|
||||
log.debug(`skipping ${a}`)
|
|
@ -1,9 +1,10 @@
|
|||
// @flow
|
||||
import fnv from 'fnv-plus'
|
||||
import autoloader from './_autoloader'
|
||||
import RPCError from '@roleypoly/rpc-client/error'
|
||||
import type Roleypoly, { Router } from '../Roleypoly'
|
||||
import autoloader from './autoloader'
|
||||
import { RPCError } from '@roleypoly/rpc-client'
|
||||
import type Roleypoly, { Router } from '@roleypoly/server/Roleypoly'
|
||||
import type { Context } from 'koa'
|
||||
export * as secureAs from './security'
|
||||
// import logger from '../logger'
|
||||
// const log = logger(__filename)
|
||||
|
||||
|
@ -68,7 +69,7 @@ export default class RPCServer {
|
|||
}
|
||||
|
||||
// check if RPC exists
|
||||
const { fn, args } = (ctx.request.body: RPCIncoming)
|
||||
const { fn, args } = ((ctx.request.body: any): RPCIncoming)
|
||||
|
||||
if (!(fn in this.rpcMap)) {
|
||||
return this.rpcError(ctx, null, new RPCError(`RPC call ${fn}(...) not found.`, 404))
|
70
packages/roleypoly-rpc-server/src/logger.js
Normal file
70
packages/roleypoly-rpc-server/src/logger.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
// @flow
|
||||
import chalk from 'chalk'
|
||||
|
||||
export class Logger {
|
||||
debugOn: boolean
|
||||
name: string
|
||||
quietSql: boolean
|
||||
|
||||
constructor (name: string, debugOverride: boolean = false) {
|
||||
this.name = name
|
||||
this.debugOn = (process.env.DEBUG === 'true' || process.env.DEBUG === '*') || debugOverride
|
||||
this.quietSql = (process.env.DEBUG_SQL !== 'true')
|
||||
}
|
||||
|
||||
fatal (text: string, ...data: any) {
|
||||
this.error(text, data)
|
||||
|
||||
if (typeof data[data.length - 1] === 'number') {
|
||||
process.exit(data[data.length - 1])
|
||||
} else {
|
||||
process.exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
error (text: string, ...data: any) {
|
||||
console.error(chalk.red.bold(`ERR ${this.name}:`) + `\n ${text}`, data)
|
||||
}
|
||||
|
||||
warn (text: string, ...data: any) {
|
||||
console.warn(chalk.yellow.bold(`WARN ${this.name}:`) + `\n ${text}`, data)
|
||||
}
|
||||
|
||||
notice (text: string, ...data: any) {
|
||||
console.log(chalk.cyan.bold(`NOTICE ${this.name}:`) + `\n ${text}`, data)
|
||||
}
|
||||
|
||||
info (text: string, ...data: any) {
|
||||
console.info(chalk.blue.bold(`INFO ${this.name}:`) + `\n ${text}`, data)
|
||||
}
|
||||
|
||||
deprecated (text: string, ...data: any) {
|
||||
console.warn(chalk.yellowBright(`DEPRECATED ${this.name}:`) + `\n ${text}`, data)
|
||||
console.trace()
|
||||
}
|
||||
|
||||
request (text: string, ...data: any) {
|
||||
console.info(chalk.green.bold(`HTTP ${this.name}:`) + `\n ${text}`)
|
||||
}
|
||||
|
||||
debug (text: string, ...data: any) {
|
||||
if (this.debugOn) {
|
||||
console.log(chalk.gray.bold(`DEBUG ${this.name}:`) + `\n ${text}`, data)
|
||||
}
|
||||
}
|
||||
|
||||
rpc (call: string, ...data: any) {
|
||||
console.log(chalk.redBright.bold`RPC` + chalk.redBright(` ${call}():`), data)
|
||||
}
|
||||
|
||||
sql (logger: Logger, ...data: any) {
|
||||
if (logger.debugOn && !logger.quietSql) {
|
||||
console.log(chalk.bold('DEBUG SQL:\n '), data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export default (pathname: string) => {
|
||||
const name = pathname.replace(__dirname, '').replace('.js', '')
|
||||
return new Logger(name)
|
||||
}
|
|
@ -1,9 +1,9 @@
|
|||
// @flow
|
||||
import { type AppContext } from '../Roleypoly'
|
||||
import { type AppContext } from '@roleypoly/server/Roleypoly'
|
||||
import { type Context } from 'koa'
|
||||
import RPCError from '@roleypoly/rpc-client/error'
|
||||
import { RPCError } from '@roleypoly/rpc-client'
|
||||
|
||||
import logger from '../logger'
|
||||
import logger from '../../roleypoly-server/logger'
|
||||
const log = logger(__filename)
|
||||
|
||||
const PermissionError = new RPCError('User does not have permission to call this RPC.', 403)
|
|
@ -10,7 +10,7 @@ import DiscordService from './services/discord'
|
|||
import SessionService from './services/sessions'
|
||||
import AuthService from './services/auth'
|
||||
import PresentationService from './services/presentation'
|
||||
import RPCServer from './rpc'
|
||||
import RPCServer from '@roleypoly/rpc-server'
|
||||
import fetchModels, { type Models } from './models'
|
||||
import fetchApis from './api'
|
||||
import retry from 'async-retry'
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"dependencies": {
|
||||
"@discordjs/uws": "^11.149.1",
|
||||
"@roleypoly/types": "^2.0.0",
|
||||
"@roleypoly/rpc-server": "^2.0.0",
|
||||
"@roleypoly/ui": "^2.0.0",
|
||||
"async-retry": "^1.2.3",
|
||||
"bufferutil": "^4.0.1",
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
import { type AppContext } from '../Roleypoly'
|
||||
import { type Context } from 'koa'
|
||||
import { type Guild } from 'eris'
|
||||
import * as secureAs from './_security'
|
||||
import RPCError from '@roleypoly/rpc-client/error'
|
||||
import { secureAs } from '@roleypoly/rpc-server'
|
||||
import { RPCError } from '@roleypoly/rpc-client'
|
||||
|
||||
export default ($: AppContext) => ({
|
||||
|
||||
rootGetAllServers: secureAs.root($, (ctx: Context) => {
|
||||
return $.discord.client.guilds.map<{
|
||||
return $.discord.guilds.valueSeq().map<{
|
||||
url: string,
|
||||
name: string,
|
||||
members: number,
|
||||
roles: number
|
||||
}>((g: Guild) => ({ url: `${$.config.appUrl}/s/${g.id}`, name: g.name, members: g.memberCount, roles: g.roles.size }))
|
||||
}>((g: Guild) => ({ url: `${$.config.appUrl}/s/${g.id}`, name: g.name, members: g.members.size, roles: g.roles.size })).toJS()
|
||||
}),
|
||||
|
||||
getServerSlug (ctx: Context, id: string) {
|
||||
|
@ -40,5 +40,18 @@ export default ($: AppContext) => ({
|
|||
}
|
||||
|
||||
return $.P.presentableServer(srv, gm)
|
||||
}),
|
||||
|
||||
listOwnServers: secureAs.authed($, async (ctx: Context, id: string) => {
|
||||
const { userId } = (ctx.session: { userId: string })
|
||||
const srv = $.discord.getRelevantServers(userId)
|
||||
return $.P.presentableServers(srv, userId)
|
||||
}),
|
||||
|
||||
syncGuild: secureAs.bot($, async (ctx: Context, type: string, guildId: string) => {
|
||||
const g = await $.discord.guild(guildId, true)
|
||||
if (g != null && type === 'guildCreate') {
|
||||
$.server.ensure(g)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ import type { AppContext } from '../Roleypoly'
|
|||
import Eris, { type Member, Role, type Guild, type Permission as ErisPermission } from 'eris'
|
||||
import LRU from 'lru-cache'
|
||||
// $FlowFixMe
|
||||
import { OrderedSet } from 'immutable'
|
||||
import { OrderedSet, OrderedMap } from 'immutable'
|
||||
import superagent from 'superagent'
|
||||
import type { AuthTokens } from './auth'
|
||||
import type { IFetcher } from './discord/types'
|
||||
|
@ -54,6 +54,8 @@ export type MemberExt = Member & {
|
|||
}
|
||||
|
||||
export default class DiscordService extends Service {
|
||||
static _guildExpiration = +(process.env.GUILD_INVALIDATION_TIME || 36e5)
|
||||
|
||||
ctx: AppContext
|
||||
client: Eris
|
||||
|
||||
|
@ -67,6 +69,8 @@ export default class DiscordService extends Service {
|
|||
|
||||
fetcher: IFetcher
|
||||
|
||||
guilds: OrderedMap<Guild> = OrderedMap<Guild>()
|
||||
_lastGuildFetch: number
|
||||
constructor (ctx: AppContext) {
|
||||
super(ctx)
|
||||
this.ctx = ctx
|
||||
|
@ -88,14 +92,15 @@ export default class DiscordService extends Service {
|
|||
})
|
||||
|
||||
this.fetcher = new RestFetcher(this)
|
||||
this.fetchGuilds(true)
|
||||
}
|
||||
|
||||
isRoot (id: string): boolean {
|
||||
return this.cfg.rootUsers.has(id)
|
||||
}
|
||||
|
||||
getRelevantServers (user: string) {
|
||||
return this.client.guilds.filter(guild => guild.members.has(user))
|
||||
getRelevantServers (user: string): OrderedSet<Guild> {
|
||||
return this.guilds.filter(guild => guild.members.has(user))
|
||||
}
|
||||
|
||||
async gm (serverId: string, userId: string, { canFake = false }: { canFake: boolean } = {}): Promise<?MemberExt> {
|
||||
|
@ -280,6 +285,36 @@ export default class DiscordService extends Service {
|
|||
return `https://discordapp.com/oauth2/authorize?client_id=${this.cfg.clientId}&scope=bot&permissions=268435456`
|
||||
}
|
||||
|
||||
async fetchGuilds (force: boolean = false) {
|
||||
if (
|
||||
force ||
|
||||
this.guilds.isEmpty() ||
|
||||
this._lastGuildFetch + DiscordService._guildExpiration < Date.now()
|
||||
) {
|
||||
const g = await this.fetcher.getGuilds()
|
||||
this.guilds = OrderedMap(g.reduce((acc, g) => ({ ...acc, [g.id]: g }), {}))
|
||||
}
|
||||
}
|
||||
|
||||
async guild (id: string, invalidate: boolean = false): Promise<?Guild> {
|
||||
// fetch if needed
|
||||
await this.fetchGuilds()
|
||||
|
||||
// do we know about it?
|
||||
// (also don't get this if we're invalidating)
|
||||
if (invalidate === false && this.guilds.has(id)) {
|
||||
return this.guilds.get(id)
|
||||
}
|
||||
|
||||
// else let's fetch and cache.
|
||||
const g = await this.fetcher.getGuild(id)
|
||||
if (g != null) {
|
||||
this.guilds = this.guilds.set(g.id, g)
|
||||
}
|
||||
|
||||
return g
|
||||
}
|
||||
|
||||
async issueChallenge (author: string) {
|
||||
// Create a challenge
|
||||
const chall = await this.ctx.auth.createDMChallenge(author)
|
||||
|
|
|
@ -4,6 +4,8 @@ import type DiscordSvc from '../discord'
|
|||
import type ErisClient, { User, Member, Guild } from 'eris'
|
||||
import LRU from 'lru-cache'
|
||||
import logger from '../../logger'
|
||||
// $FlowFixMe
|
||||
import { OrderedSet } from 'immutable'
|
||||
const log = logger(__filename)
|
||||
|
||||
export default class BotFetcher implements IFetcher {
|
||||
|
@ -71,4 +73,31 @@ export default class BotFetcher implements IFetcher {
|
|||
return null
|
||||
}
|
||||
}
|
||||
|
||||
getGuilds = async (): Promise<Guild[]> => {
|
||||
const last: ?string = undefined
|
||||
const limit: number = 100
|
||||
let out = OrderedSet<Guild>()
|
||||
|
||||
try {
|
||||
while (true) {
|
||||
// $FlowFixMe -- last is optional, but typedef isn't.
|
||||
const gl = await this.client.getRESTGuilds(limit, last)
|
||||
|
||||
out = out.union(gl)
|
||||
if (gl.length !== limit) {
|
||||
break
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
log.error('getAllGuilds failed', e)
|
||||
throw e
|
||||
}
|
||||
|
||||
return out.toArray()
|
||||
}
|
||||
|
||||
invalidateGuild (id: string) {
|
||||
this.cache.del(`G:${id}`)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -11,4 +11,6 @@ export interface IFetcher {
|
|||
getGuild: (id: string) => Promise<?Guild>;
|
||||
|
||||
getMember: (server: string, user: string) => Promise<?Member>;
|
||||
|
||||
getGuilds: () => Promise<Guild[]>;
|
||||
}
|
||||
|
|
|
@ -5,6 +5,8 @@ import { type AppContext } from '../Roleypoly'
|
|||
import { type Models } from '../models'
|
||||
import { type ServerModel } from '../models/Server'
|
||||
import type DiscordService from './discord'
|
||||
// $FlowFixMe
|
||||
import type { Sequence } from 'immutable'
|
||||
import {
|
||||
type Guild,
|
||||
type Collection
|
||||
|
@ -38,7 +40,7 @@ class PresentationService extends Service {
|
|||
}
|
||||
}
|
||||
|
||||
presentableServers (collection: Collection<Guild>, userId: string) {
|
||||
presentableServers (collection: Collection<Guild> | Sequence<Guild>, userId: string): Promise<PresentableServer[]> {
|
||||
return areduce(Array.from(collection.values()), async (acc, server) => {
|
||||
const gm = server.members.get(userId)
|
||||
if (gm == null) {
|
||||
|
|
|
@ -5,10 +5,10 @@ import type PresentationService from './presentation'
|
|||
import {
|
||||
type Guild
|
||||
} from 'eris'
|
||||
import { type ServerModel, type Category } from '../models/Server'
|
||||
import { type ServerModel, type Category } from '@roleypoly/types'
|
||||
|
||||
export default class ServerService extends Service {
|
||||
Server: any // Model<ServerModel> but flowtype is bugged
|
||||
Server: * // Model<ServerModel> but flowtype is bugged
|
||||
P: PresentationService
|
||||
constructor (ctx: AppContext) {
|
||||
super(ctx)
|
||||
|
|
|
@ -1,16 +1,29 @@
|
|||
// @flow
|
||||
import { namespaceConfig } from 'fast-redux'
|
||||
import RPC from '../config/rpc'
|
||||
// import { Map } from 'immutable'
|
||||
import type { PresentableServer as Server } from '@roleypoly/types'
|
||||
|
||||
const DEFAULT_STATE = {}
|
||||
export type ServersState = {
|
||||
[id: string]: Server
|
||||
}
|
||||
|
||||
export type ServersState = typeof DEFAULT_STATE
|
||||
const DEFAULT_STATE: ServersState = {}
|
||||
|
||||
export const { action, getState: getServerState } = namespaceConfig('servers', DEFAULT_STATE)
|
||||
|
||||
export const updateServers = action('updateServers', (state: ServersState, serverData) => ({
|
||||
export const updateServers = action('updateServers', (state: ServersState, serverData: Server[]) => ({
|
||||
...state,
|
||||
servers: serverData
|
||||
...serverData.reduce((acc, s) => ({ ...acc, [s.id]: s }), {})
|
||||
}))
|
||||
|
||||
export const updateSingleServer = action('updateSingleServer', (state, data, server) => ({ ...state, [server]: data }))
|
||||
|
||||
export const fetchServerList = (rpc?: typeof RPC) => async (dispatch: *) => {
|
||||
if (rpc == null) {
|
||||
rpc = RPC
|
||||
}
|
||||
|
||||
const servers: Server[] = await rpc.listOwnServers()
|
||||
dispatch(updateServers(servers))
|
||||
}
|
||||
|
|
37
yarn.lock
37
yarn.lock
|
@ -368,6 +368,14 @@
|
|||
"@babel/helper-create-class-features-plugin" "^7.4.0"
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-proposal-export-namespace-from@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.2.0.tgz#308fd4d04ff257fc3e4be090550840eeabad5dd9"
|
||||
integrity sha512-DZUxbHYxQ5fUFIkMEnh75ogEdBLPfL+mQUqrO2hNY2LGm+tqFnxE924+mhAcCOh/8za8AaZsWHbq6bBoS3TAzA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
"@babel/plugin-syntax-export-namespace-from" "^7.2.0"
|
||||
|
||||
"@babel/plugin-proposal-json-strings@^7.0.0", "@babel/plugin-proposal-json-strings@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.2.0.tgz#568ecc446c6148ae6b267f02551130891e29f317"
|
||||
|
@ -453,6 +461,13 @@
|
|||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-syntax-export-namespace-from@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.2.0.tgz#8d257838c6b3b779db52c0224443459bd27fb039"
|
||||
integrity sha512-1zGA3UNch6A+A11nIzBVEaE3DDJbjfB+eLIcf0GGOh/BJr/8NxL3546MGhV/r0RhH4xADFIEso39TKCfEMlsGA==
|
||||
dependencies:
|
||||
"@babel/helper-plugin-utils" "^7.0.0"
|
||||
|
||||
"@babel/plugin-syntax-flow@^7.2.0":
|
||||
version "7.2.0"
|
||||
resolved "https://registry.yarnpkg.com/@babel/plugin-syntax-flow/-/plugin-syntax-flow-7.2.0.tgz#a765f061f803bc48f240c26f8747faf97c26bf7c"
|
||||
|
@ -8173,6 +8188,14 @@ nanomatch@^1.2.9:
|
|||
snapdragon "^0.8.1"
|
||||
to-regex "^3.0.1"
|
||||
|
||||
nats@^1.2.10:
|
||||
version "1.2.10"
|
||||
resolved "https://registry.yarnpkg.com/nats/-/nats-1.2.10.tgz#3f673e80d3a513f7802b0a5c1f227127a3d1d780"
|
||||
integrity sha512-0FQMINZbyRkFMRbrpc6+IkKMQ+Zi2Ibr4YPhoEBlbP0Gw3ta23e/GB+LvXNqnV3htOPJNJ54+ToMI43BCYATGQ==
|
||||
dependencies:
|
||||
nuid "^1.0.0"
|
||||
ts-nkeys "^1.0.8"
|
||||
|
||||
natural-compare@^1.4.0:
|
||||
version "1.4.0"
|
||||
resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7"
|
||||
|
@ -8553,6 +8576,11 @@ nth-check@~1.0.1:
|
|||
dependencies:
|
||||
boolbase "~1.0.0"
|
||||
|
||||
nuid@^1.0.0:
|
||||
version "1.1.0"
|
||||
resolved "https://registry.yarnpkg.com/nuid/-/nuid-1.1.0.tgz#e0c5746350a25562f58283197f34c50861f44675"
|
||||
integrity sha512-C/JdZ6PtCqKsCEs4ni76nhBsdmuQgLAT/CTLNprkcLViDAnkk7qx5sSA8PVC2vmSsdBlSsFuGb52v6pwn1oaeg==
|
||||
|
||||
num2fraction@^1.2.2:
|
||||
version "1.2.2"
|
||||
resolved "https://registry.yarnpkg.com/num2fraction/-/num2fraction-1.2.2.tgz#6f682b6a027a4e9ddfa4564cd2589d1d4e669ede"
|
||||
|
@ -11600,6 +11628,13 @@ trough@^1.0.0:
|
|||
resolved "https://registry.yarnpkg.com/trough/-/trough-1.0.3.tgz#e29bd1614c6458d44869fc28b255ab7857ef7c24"
|
||||
integrity sha512-fwkLWH+DimvA4YCy+/nvJd61nWQQ2liO/nF/RjkTpiOGi+zxZzVkhb1mvbHIIW4b/8nDsYI8uTmAlc0nNkRMOw==
|
||||
|
||||
ts-nkeys@^1.0.8:
|
||||
version "1.0.12"
|
||||
resolved "https://registry.yarnpkg.com/ts-nkeys/-/ts-nkeys-1.0.12.tgz#cda47f4842fe2c4f88b1303817050673e16acb89"
|
||||
integrity sha512-5TgA+wbfxTy/9pdSuAhvneuL65KKoI7phonzNQH2UhnorAQAWehUwHNLEuli596wu/Fxh0SAhMeKZVLNx4s7Ow==
|
||||
dependencies:
|
||||
tweetnacl "^1.0.1"
|
||||
|
||||
tslib@^1.9.0:
|
||||
version "1.9.3"
|
||||
resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.9.3.tgz#d7e4dd79245d85428c4d7e4822a79917954ca286"
|
||||
|
@ -11629,7 +11664,7 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
|
|||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
|
||||
integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=
|
||||
|
||||
tweetnacl@^1.0.0:
|
||||
tweetnacl@^1.0.0, tweetnacl@^1.0.1:
|
||||
version "1.0.1"
|
||||
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-1.0.1.tgz#2594d42da73cd036bd0d2a54683dd35a6b55ca17"
|
||||
integrity sha512-kcoMoKTPYnoeS50tzoqjPY3Uv9axeuuFAZY9M/9zFnhoVvRfxz9K29IMPD7jGmt2c8SW7i3gT9WqDl2+nV7p4A==
|
||||
|
|
Loading…
Add table
Reference in a new issue