feat: @speckle/shared & some comments fixes (#997)

This commit is contained in:
Kristaps Fabians Geikins
2022-10-10 16:32:23 +03:00
committed by GitHub
parent ba71184421
commit 0a58381174
39 changed files with 859 additions and 547 deletions
+9 -3
View File
@@ -319,8 +319,8 @@ jobs:
- yarn-packages-server-{{ checksum "yarn.lock" }}
- run:
name: Install Dependencies
command: yarn workspaces focus
working_directory: 'packages/server'
command: yarn
# working_directory: 'packages/server'
- save_cache:
name: Save Yarn Package Cache
@@ -329,7 +329,13 @@ jobs:
- .yarn/cache
- .yarn/unplugged
- run: 'dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379 -timeout 1m'
- run:
name: Build public packages
command: yarn build:public
- run:
name: Wait for dependencies to start
command: 'dockerize -wait tcp://localhost:5432 -wait tcp://localhost:6379 -timeout 1m'
- run:
command: touch .env.test
+3
View File
@@ -5,6 +5,9 @@ packages/frontend/dist
packages/frontend/profiler
packages/viewer/dist
packages/objectloader/dist
packages/*/dist
packages/*/dist-esm
packages/*/dist-cjs
*.env
*.env.test
*.crt
+3 -2
View File
@@ -21,10 +21,11 @@
"dev:docker:down": "docker-compose -f ./docker-compose-deps.yml down",
"dev": "yarn workspaces foreach -piv -j unlimited run dev",
"dev:no-server": "yarn workspaces foreach --exclude @speckle/server -piv -j unlimited run dev",
"dev:minimal": "yarn workspaces foreach -piv -j unlimited --include '{@speckle/server,@speckle/frontend}' run dev",
"dev:minimal": "yarn workspaces foreach -piv -j unlimited --include '{@speckle/server,@speckle/frontend,@speckle/shared}' run dev",
"gqlgen": "yarn workspaces foreach -piv -j unlimited --include '{@speckle/server,@speckle/frontend}' run gqlgen",
"dev:server": "yarn workspace @speckle/server dev",
"dev:frontend": "yarn workspace @speckle/frontend dev",
"dev:shared": "yarn workspace @speckle/shared dev",
"prepare": "husky install",
"postinstall": "husky install",
"cm": "cz"
@@ -43,7 +44,7 @@
"tslib": "^2.3.1",
"core-js": "3.22.4",
"graphql": "^15.3.0",
"typescript": "^4.5.4"
"typescript": "^4.8.4"
},
"config": {
"commitizen": {
+3 -2
View File
@@ -14,6 +14,7 @@ COPY package.json yarn.lock ./
COPY packages/frontend/package.json ./packages/frontend/
COPY packages/viewer/package.json ./packages/viewer/
COPY packages/objectloader/package.json ./packages/objectloader/
COPY packages/shared/package.json ./packages/shared/
RUN yarn workspaces focus -A
@@ -21,13 +22,13 @@ RUN yarn workspaces focus -A
COPY packages/objectloader ./packages/objectloader/
COPY packages/viewer ./packages/viewer/
COPY packages/frontend ./packages/frontend/
COPY packages/shared ./packages/shared/
# This way the foreach only builds the frontend and its deps
RUN yarn workspaces foreach -pt run build
RUN yarn workspaces foreach run build
# production stage
FROM openresty/openresty:1.21.4.1-bullseye as production-stage
ENV FILE_SIZE_LIMIT_MB=100
COPY --from=build-stage /speckle-server/packages/frontend/dist /usr/share/nginx/html
+3 -2
View File
@@ -14,6 +14,7 @@
},
"dependencies": {
"@apollo/client": "^3.7.0",
"@speckle/shared": "workspace:^",
"@speckle/viewer": "workspace:^",
"@tiptap/core": "^2.0.0-beta.176",
"@tiptap/extension-bold": "^2.0.0-beta.26",
@@ -75,8 +76,8 @@
"@types/lodash": "^4.14.180",
"@types/mixpanel-browser": "^2.38.0",
"@types/node": "^17.0.43",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"@vitejs/plugin-vue2": "^1.1.2",
"@vue/eslint-config-typescript": "^11.0.1",
"babel-plugin-lodash": "^3.3.4",
+4 -19
View File
@@ -1,24 +1,7 @@
import { Roles } from '@speckle/shared'
import type { ServerRoles, StreamRoles } from '@speckle/shared'
import { StreamRole } from '@/graphql/generated/graphql'
/**
* Speckle role constants
*/
export const Roles = Object.freeze(<const>{
Stream: {
Owner: 'stream:owner',
Contributor: 'stream:contributor',
Reviewer: 'stream:reviewer'
},
Server: {
Admin: 'server:admin',
User: 'server:user',
ArchivedUser: 'server:archived-user'
}
})
export type ServerRoles = typeof Roles['Server'][keyof typeof Roles['Server']]
export type StreamRoles = typeof Roles['Stream'][keyof typeof Roles['Stream']]
/**
* Keys for values stored in localStorage
*/
@@ -44,3 +27,5 @@ export function streamRoleToGraphQLEnum(role: StreamRoles): StreamRole {
return StreamRole.StreamContributor
}
}
export { Roles, ServerRoles, StreamRoles }
+8 -17
View File
@@ -1,24 +1,15 @@
export { isUndefinedOrVoid } from '@speckle/shared'
export type {
Nullable,
Optional,
MaybeNullOrUndefined,
MaybeAsync,
MaybeFalsy
} from '@speckle/shared'
import { ReactiveVar } from '@apollo/client/core'
import { isUndefined } from 'lodash'
import Vue, { VueConstructor } from 'vue'
import { LooseRequired } from 'vue/types/common'
export type Nullable<T> = T | null
export type Optional<T> = T | undefined
export type MaybeFalsy<T> = T | null | undefined | false | '' | 0
export type MaybeNullOrUndefined<T> = T | null | undefined
export type MaybeAsync<T> = T | Promise<T>
/**
* In TS undefined !== void, so use this type guard to check for both
*/
export const isUndefinedOrVoid = (val: unknown): val is void | undefined =>
isUndefined(val)
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type GetReactiveVarType<V extends ReactiveVar<any>> = V extends ReactiveVar<
infer T
@@ -1,6 +1,8 @@
import { trim, isNumber } from 'lodash'
import { RichTextEditor } from '@speckle/shared'
import { JSONContent } from '@tiptap/core'
import { Optional } from '@/helpers/typeHelpers'
const { isDocEmpty, documentToBasicString } = RichTextEditor
export { isDocEmpty, documentToBasicString }
export type SmartTextEditorSchemaOptions = {
/**
@@ -26,43 +28,3 @@ export function basicStringToDocument(text: string): JSONContent {
content: [{ type: 'paragraph', content: [textNode] }]
}
}
/**
* Check whether a doc is empty
*/
export function isDocEmpty(doc: JSONContent | null | undefined): boolean {
if (!doc) return true
return trim(documentToBasicString(doc, 1)).length < 1
}
/**
* Convert document to a basic string without all of the formatting, HTML tags, attributes etc.
* Useful for previews or text analysis.
* @param doc
* @param stopAtLength If set, will stop further parsing when the resulting string length
* reaches this length. Useful when you're only interested in the first few characters of the document.
*/
export function documentToBasicString(
doc: JSONContent | null | undefined,
stopAtLength: Optional<number> = undefined
): string {
if (!doc) return ''
const recursiveStringBuilder = (doc: JSONContent, currentString: string) => {
if (isNumber(stopAtLength) && currentString.length >= stopAtLength) {
return currentString
}
if (doc.text) {
currentString += doc.text
}
for (const contentDoc of doc.content || []) {
currentString = recursiveStringBuilder(contentDoc, currentString)
}
return currentString
}
return recursiveStringBuilder(doc, '')
}
+12 -6
View File
@@ -17,13 +17,18 @@ COPY .yarnrc.yml .
COPY .yarn ./.yarn
COPY package.json yarn.lock ./
COPY packages/server/package.json ./packages/server/
COPY packages/shared/package.json ./packages/shared/
RUN yarn workspaces focus -A
COPY packages/server ./packages/server/
COPY packages/shared ./packages/shared/
RUN yarn workspaces foreach run build
WORKDIR /speckle-server/packages/server
COPY packages/server/package.json .
RUN yarn workspaces focus
COPY packages/server .
RUN yarn build && yarn workspaces focus --production
RUN yarn workspaces focus --production
FROM node:16.15-bullseye-slim as production-stage
ARG NODE_ENV=production
@@ -39,6 +44,7 @@ COPY --from=build-stage /speckle-server/.yarnrc.yml .
COPY --from=build-stage /speckle-server/.yarn ./.yarn
COPY --from=build-stage /speckle-server/package.json /speckle-server/yarn.lock ./
COPY --from=build-stage /speckle-server/node_modules ./node_modules
COPY --from=build-stage /speckle-server/packages/shared /speckle-server/packages/shared
WORKDIR /speckle-server/packages/server
@@ -62,11 +62,15 @@ type Comment {
archived: Boolean!
screenshot: String
text: SmartTextEditorValue!
"""
Plain-text version of the comment text, ideal for previews
"""
rawText: String!
data: JSONObject
"""
Resources that this comment targets. Can be a mixture of either one stream, or multiple commits and objects.
"""
resources: [ResourceIdentifier]!
resources: [ResourceIdentifier!]!
createdAt: DateTime
"""
The time this comment was last updated. Corresponds also to the latest reply to this comment, if any.
@@ -25,6 +25,10 @@ const {
ensureCommentSchema
} = require('@/modules/comments/services/commentTextService')
const { withFilter } = require('graphql-subscriptions')
const { has } = require('lodash')
const {
documentToBasicString
} = require('@/modules/core/services/richTextEditorService')
const authorizeStreamAccess = async ({
streamId,
@@ -51,6 +55,7 @@ const authorizeStreamAccess = async ({
return stream
}
/** @type {import('@/modules/core/graph/generated/graphql').Resolvers} */
module.exports = {
Query: {
async comment(parent, args, context) {
@@ -92,6 +97,19 @@ module.exports = {
text(parent) {
const commentText = parent?.text || ''
return ensureCommentSchema(commentText)
},
rawText(parent) {
const { doc } = ensureCommentSchema(parent.text || '')
return documentToBasicString(doc)
},
/**
* Resolve resources, if they weren't already preloaded
*/
async resources(parent, _args, ctx) {
if (has(parent, 'resources')) return parent.resources
return await ctx.loaders.comments.getResources.load(parent.id)
}
},
Stream: {
@@ -1,6 +1,8 @@
import { CommentLinkRecord, CommentRecord } from '@/modules/comments/helpers/types'
import { Comments, knex } from '@/modules/core/dbSchema'
import { CommentLinks, Comments, knex } from '@/modules/core/dbSchema'
import { ResourceIdentifier } from '@/modules/core/graph/generated/graphql'
import { Optional } from '@/modules/shared/helpers/typeHelper'
import { keyBy } from 'lodash'
export type ExtendedComment = CommentRecord & {
/**
@@ -37,3 +39,23 @@ export async function getComment(params: { id: string; userId?: string }) {
query.where({ id }).first()
return (await query) as Optional<ExtendedComment>
}
/**
* Get resources array for the specified comments. Results object is keyed by comment ID.
*/
export async function getCommentsResources(commentIds: string[]) {
if (!commentIds.length) return {}
const q = CommentLinks.knex()
.select<{ commentId: string; resources: ResourceIdentifier[] }[]>([
CommentLinks.col.commentId,
knex.raw(
`JSON_AGG(json_build_object('resourceId', "resourceId", 'resourceType', "resourceType")) as resources`
)
])
.whereIn(CommentLinks.col.commentId, commentIds)
.groupBy(CommentLinks.col.commentId)
const results = await q
return keyBy(results, 'commentId')
}
@@ -1,18 +1,21 @@
const { RichTextParseError } = require('@/modules/shared/errors')
const {
import { RichTextParseError } from '@/modules/shared/errors'
import {
isTextEditorValueSchema,
isTextEditorDoc,
convertBasicStringToDocument,
isSerializedTextEditorValueSchema
} = require('@/modules/core/services/richTextEditorService')
const { isString, uniq } = require('lodash')
const { getBlobs } = require('@/modules/blobstorage/services')
const { InvalidAttachmentsError } = require('@/modules/comments/errors')
isSerializedTextEditorValueSchema,
SmartTextEditorValueSchema,
isDocEmpty
} from '@/modules/core/services/richTextEditorService'
import { isString, uniq } from 'lodash'
import { getBlobs } from '@/modules/blobstorage/services'
import { InvalidAttachmentsError } from '@/modules/comments/errors'
import { JSONContent } from '@tiptap/core'
const COMMENT_SCHEMA_VERSION = '1.0.0'
const COMMENT_SCHEMA_TYPE = 'stream_comment'
async function validateInputAttachments(streamId, blobIds) {
export async function validateInputAttachments(streamId: string, blobIds: string[]) {
blobIds = uniq(blobIds || [])
if (!blobIds.length) return
@@ -24,20 +27,21 @@ async function validateInputAttachments(streamId, blobIds) {
/**
* Build comment.text value from a ProseMirror doc
* @param {{
* doc: import("@tiptap/core").JSONContent | undefined,
* blobIds: string[]
* }} param1
* @returns {import('@/modules/core/services/richTextEditorService').SmartTextEditorValueSchema}
*/
function buildCommentTextFromInput({ doc = undefined, blobIds = [] }) {
if (!isTextEditorDoc(doc) && !blobIds.length) {
export function buildCommentTextFromInput({
doc = undefined,
blobIds = []
}: Partial<{
doc: JSONContent
blobIds: string[]
}>) {
if ((!isTextEditorDoc(doc) || isDocEmpty(doc)) && !blobIds.length) {
throw new RichTextParseError(
'Attempting to build comment text without document & attachments!'
)
}
return {
return <SmartTextEditorValueSchema>{
version: COMMENT_SCHEMA_VERSION,
type: COMMENT_SCHEMA_TYPE,
doc,
@@ -47,10 +51,10 @@ function buildCommentTextFromInput({ doc = undefined, blobIds = [] }) {
/**
* Ensure a comment value pulled from db (string or schema JSON) is formatted to be a text editor schema
* @param {string|import('@/modules/core/services/richTextEditorService').SmartTextEditorValueSchema} stringOrSchema
* @returns {import('@/modules/core/services/richTextEditorService').SmartTextEditorValueSchema}
*/
function ensureCommentSchema(stringOrSchema) {
export function ensureCommentSchema(
stringOrSchema: SmartTextEditorValueSchema | string
) {
if (isTextEditorValueSchema(stringOrSchema)) return stringOrSchema
if (isString(stringOrSchema)) {
const deserializedSchema = isSerializedTextEditorValueSchema(stringOrSchema)
@@ -63,9 +67,3 @@ function ensureCommentSchema(stringOrSchema) {
throw new RichTextParseError('Unexpected comment schema format')
}
module.exports = {
buildCommentTextFromInput,
ensureCommentSchema,
validateInputAttachments
}
@@ -93,7 +93,7 @@ module.exports = {
blobIds: input.blobIds
})
await Comments().insert(comment)
const [newComment] = await Comments().insert(comment, '*')
try {
await module.exports.streamResourceCheck({
streamId: input.streamId,
@@ -112,9 +112,6 @@ module.exports = {
}
await module.exports.viewComment({ userId, commentId: comment.id }) // so we don't self mark a comment as unread the moment it's created
// Get new comment from DB, that way we don't have to mock/fill in the missing
// values
const newComment = await module.exports.getComment({ id: comment.id, userId })
await CommentsEmitter.emit(CommentsEvents.Created, {
comment: newComment
})
@@ -140,7 +137,7 @@ module.exports = {
parentComment: parentCommentId
}
await Comments().insert(comment)
const [newComment] = await Comments().insert(comment, '*')
try {
const commentLink = { resourceId: parentCommentId, resourceType: 'comment' }
await module.exports.streamResourceCheck({
@@ -154,12 +151,6 @@ module.exports = {
}
await Comments().where({ id: parentCommentId }).update({ updatedAt: knex.fn.now() })
// Get new comment from DB, that way we don't have to mock/fill in the missing
// values
const newComment = await module.exports.getComment({
id: comment.id,
userId: authorId
})
await CommentsEmitter.emit(CommentsEvents.Created, {
comment: newComment
})
@@ -179,11 +170,10 @@ module.exports = {
doc: input.text,
blobIds: input.blobIds
})
await Comments().where({ id: input.id }).update({ text: newText })
const [updatedComment] = await Comments()
.where({ id: input.id })
.update({ text: newText }, '*')
// Get new comment from DB, that way we don't have to mock/fill in the missing
// values
const updatedComment = await module.exports.getComment({ id: input.id, userId })
await CommentsEmitter.emit(CommentsEvents.Updated, {
previousComment: editedComment,
newComment: updatedComment
@@ -1035,6 +1035,7 @@ describe('Comments @comments', () => {
})
describe('when reading comments', () => {
let parentCommentId
let emptyCommentId
before(async () => {
@@ -1046,7 +1047,7 @@ describe('Comments @comments', () => {
text: generateRandomCommentText(),
blobIds: [blob1.blobId]
})
const parentCommentId = createCommentResult.data.commentCreate
parentCommentId = createCommentResult.data.commentCreate
if (!parentCommentId) throw new Error('Comment creation failed!')
// Create a reply with a blob
@@ -1230,6 +1231,34 @@ describe('Comments @comments', () => {
).to.deep.equalInAnyOrder(expectedMetadata)
})
it('returns raw text correctly', async () => {
const {
data: { commentReply: commentId }
} = await createReply({
text: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{ type: 'mention', attrs: { label: 'Heyyoo', id: '123' } },
{ type: 'text', text: ' ' },
{ type: 'text', text: 'helloooo!' }
]
}
]
},
blobIds: [],
parentComment: parentCommentId
})
const results = await readComment({
id: commentId
})
expect(results).to.not.haveGraphQLErrors()
expect(results.data?.comment?.rawText).to.eq('@Heyyoo helloooo!')
})
it('returns a blob comment without text correctly', async () => {
const { data, errors } = await readComment({
id: emptyCommentId
@@ -1332,7 +1361,12 @@ describe('Comments @comments', () => {
blobIds: [],
display: 'invalid input text'
},
{ text: null, blobIds: [], display: 'no attachments & text' }
{ text: null, blobIds: [], display: 'no attachments & text' },
{
text: buildCommentInputFromString(' \n\n'),
blobIds: [],
display: 'no attachments & empty text'
}
]
invalidInputDataSet.forEach(({ text, blobIds, display }) => {
it(`input with ${display} throws an error`, async () => {
@@ -1358,6 +1392,27 @@ describe('Comments @comments', () => {
expect(errors || []).to.be.empty
})
it('a document with only a single mention an be successfully posted', async () => {
const results = await createOrReplyComment({
blobIds: [],
text: {
type: 'doc',
content: [
{
type: 'paragraph',
content: [
{ type: 'mention', attrs: { label: 'Some Guy', id: 'aabbcc' } }
]
}
]
}
})
const data = getResult(results.data)
expect(results).to.not.haveGraphQLErrors()
expect(data).to.be.ok
})
describe('and mentioning a user', () => {
const createOrReplyCommentWithMention = (targetUserId, input = {}) =>
createOrReplyComment({
@@ -197,11 +197,13 @@ export type Comment = {
createdAt?: Maybe<Scalars['DateTime']>;
data?: Maybe<Scalars['JSONObject']>;
id: Scalars['String'];
/** Plain-text version of the comment text, ideal for previews */
rawText: Scalars['String'];
reactions?: Maybe<Array<Maybe<Scalars['String']>>>;
/** Gets the replies to this comment. */
replies?: Maybe<CommentCollection>;
/** Resources that this comment targets. Can be a mixture of either one stream, or multiple commits and objects. */
resources: Array<Maybe<ResourceIdentifier>>;
resources: Array<ResourceIdentifier>;
screenshot?: Maybe<Scalars['String']>;
text: SmartTextEditorValue;
/** The time this comment was last updated. Corresponds also to the latest reply to this comment, if any. */
@@ -2079,9 +2081,10 @@ export type CommentResolvers<ContextType = GraphQLContext, ParentType extends Re
createdAt?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
data?: Resolver<Maybe<ResolversTypes['JSONObject']>, ParentType, ContextType>;
id?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
rawText?: Resolver<ResolversTypes['String'], ParentType, ContextType>;
reactions?: Resolver<Maybe<Array<Maybe<ResolversTypes['String']>>>, ParentType, ContextType>;
replies?: Resolver<Maybe<ResolversTypes['CommentCollection']>, ParentType, ContextType, RequireFields<CommentRepliesArgs, 'limit'>>;
resources?: Resolver<Array<Maybe<ResolversTypes['ResourceIdentifier']>>, ParentType, ContextType>;
resources?: Resolver<Array<ResolversTypes['ResourceIdentifier']>, ParentType, ContextType>;
screenshot?: Resolver<Maybe<ResolversTypes['String']>, ParentType, ContextType>;
text?: Resolver<ResolversTypes['SmartTextEditorValue'], ParentType, ContextType>;
updatedAt?: Resolver<Maybe<ResolversTypes['DateTime']>, ParentType, ContextType>;
@@ -1,57 +1,2 @@
import _ from 'lodash'
/**
* Speckle role constants
* - Stream - user roles in the context of a specific stream
* - Server - user roles in the context of the entire server
*/
export const Roles = Object.freeze(<const>{
Stream: {
Owner: 'stream:owner',
Contributor: 'stream:contributor',
Reviewer: 'stream:reviewer'
},
Server: {
Admin: 'server:admin',
User: 'server:user',
ArchivedUser: 'server:archived-user'
}
})
export type ServerRoles = typeof Roles['Server'][keyof typeof Roles['Server']]
export type StreamRoles = typeof Roles['Stream'][keyof typeof Roles['Stream']]
/**
* Speckle scope constants
* - Scopes define what kind of access has a user approved for a specific access token
*/
export const Scopes = Object.freeze(<const>{
Streams: {
Read: 'streams:read',
Write: 'streams:write'
},
Profile: {
Read: 'profile:read',
Email: 'profile:email',
Delete: 'profile:delete'
},
Users: {
Read: 'users:read',
Email: 'users:email',
Invite: 'users:invite'
},
Server: {
Stats: 'server:stats',
Setup: 'server:setup'
},
Tokens: {
Read: 'tokens:read',
Write: 'tokens:write'
}
})
/**
* All scopes
* @type {string[]}
*/
export const AllScopes = _.flatMap(Scopes, (v) => Object.values(v))
export { Roles, Scopes, AllScopes } from '@speckle/shared'
export type { ServerRoles, StreamRoles } from '@speckle/shared'
+8
View File
@@ -18,6 +18,8 @@ import {
import { Nullable } from '@/modules/shared/helpers/typeHelper'
import { ServerInviteRecord } from '@/modules/serverinvites/helpers/types'
import { getCommitStreams } from '@/modules/core/repositories/commits'
import { ResourceIdentifier } from '@/modules/core/graph/generated/graphql'
import { getCommentsResources } from '@/modules/comments/repositories/comments'
/**
* Build request-scoped dataloaders
@@ -93,6 +95,12 @@ export function buildRequestLoaders(ctx: AuthContext) {
}
)
},
comments: {
getResources: new DataLoader<string, ResourceIdentifier[]>(async (commentIds) => {
const results = await getCommentsResources(commentIds.slice())
return commentIds.map((id) => results[id]?.resources || [])
})
},
users: {
/**
* Get user from DB
@@ -1,125 +0,0 @@
const { trim, isString, isObjectLike } = require('lodash')
/**
* @typedef {{
* version: string,
* type: string,
* doc?: import("@tiptap/core").JSONContent | undefined,
* blobIds?: string[] | undefined
* }} SmartTextEditorValueSchema
*/
/**
* Used to match URLs that can appear anywhere in a string, not perfect, but crafting a perfect
* URL regex is quite complex and we only need this for legacy comments
*/
const MID_STRING_URL_RGX = /https?:\/\/\S+/gi
function isTextEditorDoc(value) {
return !isString(value) && isObjectLike(value) && value.type === 'doc'
}
function isTextEditorValueSchema(value) {
return (
isObjectLike(value) && value.type && value.version && (value.doc || value.blobIds)
)
}
/**
* Check if value is a schema serialized to string and return the schema object if so or false if not
* @param {string} schemaJson
* @returns {SmartTextEditorValueSchema|false}
*/
function isSerializedTextEditorValueSchema(schemaJson) {
let deserializedSchema = undefined
try {
const deserializedJson = JSON.parse(schemaJson)
if (deserializedJson && isTextEditorValueSchema(deserializedJson)) {
deserializedSchema = deserializedJson
}
} catch (e) {
// Suppressing serialization errors
}
return deserializedSchema || false
}
/**
* Build a rich text document out of a basic string
* @param {string} text
* @returns {import("@tiptap/core").JSONContent}
*/
function convertBasicStringToDocument(text) {
// Extract URLs and convert to text with link marks
const urlMatches = [...text.matchAll(MID_STRING_URL_RGX)].map((m) => m[0])
const splitTexts = text.split(MID_STRING_URL_RGX)
const textNodes = []
for (const textPart of splitTexts) {
// Build text node, if text part not empty
if (trim(textPart)) {
textNodes.push({
type: 'text',
text: textPart
})
}
// Get url node to append, if any remaining
const url = urlMatches.shift()
if (url) {
textNodes.push({
type: 'text',
text: url,
marks: [
{
attrs: {
href: url,
target: '_blank'
},
type: 'link'
}
]
})
}
}
return {
type: 'doc',
content: [
{
type: 'paragraph',
content: textNodes
}
]
}
}
/**
* Generator for walking through content nodes
* @param {import("@tiptap/core").JSONContent} document
* @returns {Generator<import("@tiptap/core").JSONContent>}
*/
function* iterateContentNodes(document) {
if (!document) return
/**
* @param {import("@tiptap/core").JSONContent} doc
*/
function* recursiveWalker(doc) {
yield doc
for (const contentDoc of doc.content || []) {
yield* recursiveWalker(contentDoc)
}
}
yield* recursiveWalker(document)
}
module.exports = {
isTextEditorValueSchema,
isTextEditorDoc,
isSerializedTextEditorValueSchema,
convertBasicStringToDocument,
iterateContentNodes
}
@@ -0,0 +1,63 @@
import { JSONContent } from '@tiptap/core'
import { isString, isObjectLike, get, has } from 'lodash'
import { RichTextEditor } from '@speckle/shared'
const { isDocEmpty, documentToBasicString, convertBasicStringToDocument } =
RichTextEditor
export { isDocEmpty, documentToBasicString, convertBasicStringToDocument }
export type SmartTextEditorValueSchema = {
version: string
type: string
doc?: JSONContent
blobIds?: string[]
}
export function isTextEditorDoc(value: unknown): value is JSONContent {
return !isString(value) && isObjectLike(value) && get(value, 'type') === 'doc'
}
export function isTextEditorValueSchema(
value: unknown
): value is SmartTextEditorValueSchema {
return (
isObjectLike(value) &&
has(value, 'type') &&
has(value, 'version') &&
(has(value, 'doc') || has(value, 'blobIds'))
)
}
/**
* Check if value is a schema serialized to string and return the schema object if so or false if not
*/
export function isSerializedTextEditorValueSchema(schemaJson: string) {
let deserializedSchema = undefined
try {
const deserializedJson = JSON.parse(schemaJson)
if (deserializedJson && isTextEditorValueSchema(deserializedJson)) {
deserializedSchema = deserializedJson
}
} catch (e) {
// Suppressing serialization errors
}
return deserializedSchema || false
}
/**
* Generator for walking through content nodes
*/
export function* iterateContentNodes(document: JSONContent): Generator<JSONContent> {
if (!document) return
function* recursiveWalker(doc: JSONContent): Generator<JSONContent> {
yield doc
for (const contentDoc of doc.content || []) {
yield* recursiveWalker(contentDoc)
}
}
yield* recursiveWalker(document)
}
@@ -1,13 +1,14 @@
import {
Nullable,
Optional,
MaybeNullOrUndefined,
MaybeAsync,
MaybeFalsy
} from '@speckle/shared'
import { RequestDataLoaders } from '@/modules/core/loaders'
import { AuthContext } from '@/modules/shared/authz'
import { Express } from 'express'
export type Nullable<T> = T | null
export type Optional<T> = T | undefined
export type MaybeNullOrUndefined<T> = T | null | undefined
export type MaybeAsync<T> = T | Promise<T>
export type MaybeFalsy<T> = T | null | undefined | false | '' | 0
export type SpeckleModule<T extends Record<string, unknown> = Record<string, unknown>> =
{
/**
@@ -39,3 +40,5 @@ export type GraphQLContext = AuthContext & {
*/
loaders: RequestDataLoaders
}
export { Nullable, Optional, MaybeNullOrUndefined, MaybeAsync, MaybeFalsy }
+3 -2
View File
@@ -37,6 +37,7 @@
"@graphql-tools/schema": "^9.0.4",
"@sentry/node": "^6.17.9",
"@sentry/tracing": "^6.17.9",
"@speckle/shared": "workspace:^",
"apollo-server-express": "^3.10.2",
"bcrypt": "^5.0.0",
"bull": "^4.8.5",
@@ -116,8 +117,8 @@
"@types/verror": "^1.10.6",
"@types/yargs": "^17.0.10",
"@types/zxcvbn": "^4.4.1",
"@typescript-eslint/eslint-plugin": "^5.32.0",
"@typescript-eslint/parser": "^5.32.0",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"axios": "^0.25.0",
"chai": "^4.2.0",
"chai-http": "^4.3.0",
+1
View File
@@ -14,6 +14,7 @@ import { ApolloServer, gql } from 'apollo-server-express'
const commentWithRepliesFragment = gql`
fragment CommentWithReplies on Comment {
id
rawText
text {
doc
attachments {
@@ -191,11 +191,13 @@ export type Comment = {
createdAt?: Maybe<Scalars['DateTime']>;
data?: Maybe<Scalars['JSONObject']>;
id: Scalars['String'];
/** Plain-text version of the comment text, ideal for previews */
rawText: Scalars['String'];
reactions?: Maybe<Array<Maybe<Scalars['String']>>>;
/** Gets the replies to this comment. */
replies?: Maybe<CommentCollection>;
/** Resources that this comment targets. Can be a mixture of either one stream, or multiple commits and objects. */
resources: Array<Maybe<ResourceIdentifier>>;
resources: Array<ResourceIdentifier>;
screenshot?: Maybe<Scalars['String']>;
text: SmartTextEditorValue;
/** The time this comment was last updated. Corresponds also to the latest reply to this comment, if any. */
@@ -1725,7 +1727,7 @@ export type UseStreamAccessRequestMutationVariables = Exact<{
export type UseStreamAccessRequestMutation = { __typename?: 'Mutation', streamAccessRequestUse: boolean };
export type CommentWithRepliesFragment = { __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null };
export type CommentWithRepliesFragment = { __typename?: 'Comment', id: string, rawText: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null };
export type CreateCommentMutationVariables = Exact<{
input: CommentCreateInput;
@@ -1747,7 +1749,7 @@ export type GetCommentQueryVariables = Exact<{
}>;
export type GetCommentQuery = { __typename?: 'Query', comment?: { __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null } | null };
export type GetCommentQuery = { __typename?: 'Query', comment?: { __typename?: 'Comment', id: string, rawText: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null } | null };
export type GetCommentsQueryVariables = Exact<{
streamId: Scalars['String'];
@@ -1755,7 +1757,7 @@ export type GetCommentsQueryVariables = Exact<{
}>;
export type GetCommentsQuery = { __typename?: 'Query', comments?: { __typename?: 'CommentCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null }> } | null };
export type GetCommentsQuery = { __typename?: 'Query', comments?: { __typename?: 'CommentCollection', totalCount: number, cursor?: string | null, items: Array<{ __typename?: 'Comment', id: string, rawText: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null }, replies?: { __typename?: 'CommentCollection', items: Array<{ __typename?: 'Comment', id: string, text: { __typename?: 'SmartTextEditorValue', doc?: Record<string, unknown> | null, attachments?: Array<{ __typename?: 'BlobMetadata', id: string, fileName: string, streamId: string }> | null } }> } | null }> } | null };
export type BaseCommitFieldsFragment = { __typename?: 'Commit', id: string, authorName?: string | null, authorId?: string | null, authorAvatar?: string | null, streamId?: string | null, streamName?: string | null, sourceApplication?: string | null, message?: string | null, referencedObject: string, createdAt?: string | null, commentCount: number };
+39
View File
@@ -0,0 +1,39 @@
/**
* Extends repo root config, only put changes here that are scoped to this specific package
* (if you already are - evaluate whether you really need package scoped linting rules)
*/
/** @type {import("eslint").Linter.Config} */
const config = {
env: {
node: true,
es2022: true
},
parserOptions: {
ecmaVersion: 13
},
ignorePatterns: ['node_modules', 'dist', 'dist-cjs', 'dist-esm'],
overrides: [
{
files: '*.ts',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module'
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'prettier'
],
parser: '@typescript-eslint/parser'
},
{
files: '*.d.ts',
rules: {
'@typescript-eslint/no-explicit-any': 'off'
}
}
]
}
module.exports = config
+50
View File
@@ -0,0 +1,50 @@
{
"name": "@speckle/shared",
"version": "0.1.0",
"description": "Shared code between various Speckle JS packages",
"homepage": "https://speckle.systems",
"repository": {
"type": "git",
"url": "https://github.com/specklesystems/speckle-server.git",
"directory": "packages/shared"
},
"main": "./dist-cjs/index.js",
"types": "./dist-esm/index.d.ts",
"module": "./dist-esm/index.js",
"scripts": {
"build": "NODE_ENV=production rollup --config",
"build:dev": "rollup --config",
"dev": "rollup --config --watch",
"prepack": "yarn build",
"lint:eslint": "eslint . --ext .js,.ts",
"lint:tsc": "tsc --noEmit",
"lint": "yarn lint:eslint && yarn lint:tsc"
},
"engines": {
"node": ">=14.0.0"
},
"author": "AEC Systems",
"license": "Apache-2.0",
"keywords": [
"speckle",
"aec",
"3d"
],
"dependencies": {
"lodash": "^4.17.0"
},
"peerDependencies": {
"@tiptap/core": "^2.0.0-beta.176"
},
"devDependencies": {
"@types/lodash": "^4.14.184",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.5.0",
"rollup": "^2.79.1",
"rollup-plugin-delete": "^2.0.0",
"rollup-plugin-typescript2": "^0.34.1",
"typescript": "^4.5.4"
}
}
+23
View File
@@ -0,0 +1,23 @@
# @speckle/shared
This package holds code that otherwise would be duplicated across @speckle packages, things like helpers, constants and TS types.
## Usage
### Peer dependencies
Some dependencies are marked as peer dependencies, to ensure that package consumers can manage their versions themselves. If you use any code from this package that relies on a specific peer dependency, make sure its installed.
### How to use
```js
import { Roles, RichTextEditor } from '@speckle/shared'
```
## Development
Do `yarn build` to build or `yarn dev` to build in watch mode
### Code organization
Code should be organized according to areas of speckle, 'core' being the main one. Exports from areas other than "core" should be grouped under namespaces like "RichTextEditor".
+33
View File
@@ -0,0 +1,33 @@
const clean = require('rollup-plugin-delete')
const pkg = require('./package.json')
const typescript2 = require('rollup-plugin-typescript2')
const isProd = process.env.NODE_ENV === 'production'
const sourcemap = isProd ? false : 'inline'
/** @type {import('rollup').RollupOptions} */
module.exports = {
input: 'src/index.ts',
output: [
{
file: 'dist-esm/index.js',
format: 'esm',
sourcemap
},
{
file: 'dist-cjs/index.js',
format: 'cjs',
sourcemap
}
],
plugins: [
clean({ targets: ['dist/*', 'dist-esm/*', 'dist-cjs/*'] }),
typescript2({
tsconfigOverride: {
sourceMap: sourcemap
}
})
],
// Externalizing all deps, we don't want to bundle them in cause this is a library
external: Object.keys(pkg.dependencies || {}).map((d) => new RegExp(`^${d}(\\/.*)?$`))
}
+56
View File
@@ -0,0 +1,56 @@
import _ from 'lodash'
/**
* Speckle role constants
* - Stream - user roles in the context of a specific stream
* - Server - user roles in the context of the entire server
*/
export const Roles = Object.freeze(<const>{
Stream: {
Owner: 'stream:owner',
Contributor: 'stream:contributor',
Reviewer: 'stream:reviewer'
},
Server: {
Admin: 'server:admin',
User: 'server:user',
ArchivedUser: 'server:archived-user'
}
})
export type ServerRoles = typeof Roles['Server'][keyof typeof Roles['Server']]
export type StreamRoles = typeof Roles['Stream'][keyof typeof Roles['Stream']]
/**
* Speckle scope constants
* - Scopes define what kind of access has a user approved for a specific access token
*/
export const Scopes = Object.freeze(<const>{
Streams: {
Read: 'streams:read',
Write: 'streams:write'
},
Profile: {
Read: 'profile:read',
Email: 'profile:email',
Delete: 'profile:delete'
},
Users: {
Read: 'users:read',
Email: 'users:email',
Invite: 'users:invite'
},
Server: {
Stats: 'server:stats',
Setup: 'server:setup'
},
Tokens: {
Read: 'tokens:read',
Write: 'tokens:write'
}
})
/**
* All scopes
*/
export const AllScopes = _.flatMap(Scopes, (v) => Object.values(v))
@@ -0,0 +1,13 @@
import { isUndefined } from 'lodash'
export type Nullable<T> = T | null
export type Optional<T> = T | undefined
export type MaybeNullOrUndefined<T> = T | null | undefined
export type MaybeAsync<T> = T | Promise<T>
export type MaybeFalsy<T> = T | null | undefined | false | '' | 0
/**
* In TS undefined !== void, so use this type guard to check for both
*/
export const isUndefinedOrVoid = (val: unknown): val is void | undefined =>
isUndefined(val)
+2
View File
@@ -0,0 +1,2 @@
export * from './constants'
export * from './helpers/utilityTypes'
+2
View File
@@ -0,0 +1,2 @@
export * as RichTextEditor from './rich-text-editor'
export * from './core'
@@ -0,0 +1,101 @@
import { trim, isNumber } from 'lodash'
import type { JSONContent } from '@tiptap/core'
import { Optional } from '../../core/helpers/utilityTypes'
/**
* Used to match URLs that can appear anywhere in a string, not perfect, but crafting a perfect
* URL regex is quite complex and we only need this for legacy comments
*/
const MID_STRING_URL_RGX = /https?:\/\/\S+/gi
/**
* Check whether a doc is empty
*/
export function isDocEmpty(doc: JSONContent | null | undefined): boolean {
if (!doc) return true
return trim(documentToBasicString(doc, 1)).length < 1
}
/**
* Convert document to a basic string without all of the formatting, HTML tags, attributes etc.
* Useful for previews or text analysis.
* @param stopAtLength If set, will stop further parsing when the resulting string length
* reaches this length. Useful when you're only interested in the first few characters of the document.
*/
export function documentToBasicString(
doc: JSONContent | null | undefined,
stopAtLength: Optional<number> = undefined
): string {
if (!doc) return ''
const recursiveStringBuilder = (doc: JSONContent, currentString: string) => {
if (isNumber(stopAtLength) && currentString.length >= stopAtLength) {
return currentString
}
if (doc.text) {
currentString += doc.text
}
// if mention, add it as text as well
if (doc.type === 'mention' && doc.attrs?.label && doc.attrs.id) {
currentString += '@' + doc.attrs.label
}
for (const contentDoc of doc.content || []) {
currentString = recursiveStringBuilder(contentDoc, currentString)
}
return currentString
}
return recursiveStringBuilder(doc, '')
}
/**
* Build a rich text document out of a basic string
*/
export function convertBasicStringToDocument(text: string) {
// Extract URLs and convert to text with link marks
const urlMatches = [...text.matchAll(MID_STRING_URL_RGX)].map((m) => m[0])
const splitTexts = text.split(MID_STRING_URL_RGX)
const textNodes = []
for (const textPart of splitTexts) {
// Build text node, if text part not empty
if (trim(textPart)) {
textNodes.push({
type: 'text',
text: textPart
})
}
// Get url node to append, if any remaining
const url = urlMatches.shift()
if (url) {
textNodes.push({
type: 'text',
text: url,
marks: [
{
attrs: {
href: url,
target: '_blank'
},
type: 'link'
}
]
})
}
}
return <JSONContent>{
type: 'doc',
content: [
{
type: 'paragraph',
content: textNodes
}
]
}
}
@@ -0,0 +1 @@
export * from './helpers'
+103
View File
@@ -0,0 +1,103 @@
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Projects */
// "incremental": true, /* Enable incremental compilation */
// "composite": true, /* Enable constraints that allow a TypeScript project to be used with project references. */
// "tsBuildInfoFile": "./", /* Specify the folder for .tsbuildinfo incremental compilation files. */
// "disableSourceOfProjectReferenceRedirect": true, /* Disable preferring source files instead of declaration files when referencing composite projects */
// "disableSolutionSearching": true, /* Opt a project out of multi-project reference checking when editing. */
// "disableReferencedProjectLoad": true, /* Reduce the number of projects loaded automatically by TypeScript. */
/* Language and Environment */
"target": "es2019" /* Set the JavaScript language version for emitted JavaScript and include compatible library declarations. */,
// "lib": [], /* Specify a set of bundled library declaration files that describe the target runtime environment. */
// "jsx": "preserve", /* Specify what JSX code is generated. */
// "experimentalDecorators": true, /* Enable experimental support for TC39 stage 2 draft decorators. */
// "emitDecoratorMetadata": true, /* Emit design-type metadata for decorated declarations in source files. */
// "jsxFactory": "", /* Specify the JSX factory function used when targeting React JSX emit, e.g. 'React.createElement' or 'h' */
// "jsxFragmentFactory": "", /* Specify the JSX Fragment reference used for fragments when targeting React JSX emit e.g. 'React.Fragment' or 'Fragment'. */
// "jsxImportSource": "", /* Specify module specifier used to import the JSX factory functions when using `jsx: react-jsx*`.` */
// "reactNamespace": "", /* Specify the object invoked for `createElement`. This only applies when targeting `react` JSX emit. */
// "noLib": true, /* Disable including any library files, including the default lib.d.ts. */
// "useDefineForClassFields": true, /* Emit ECMAScript-standard-compliant class fields. */
/* Modules */
"module": "es2020" /* Specify what module code is generated. */,
"rootDir": "./src" /* Specify the root folder within your source files. */,
"moduleResolution": "node" /* Specify how TypeScript looks up a file from a given module specifier. */,
// "baseUrl": "./", /* Specify the base directory to resolve non-relative module names. */
// "paths": {}, /* Specify a set of entries that re-map imports to additional lookup locations. */
// "rootDirs": [], /* Allow multiple folders to be treated as one when resolving modules. */
// "typeRoots": [], /* Specify multiple folders that act like `./node_modules/@types`. */
// "types": [], /* Specify type package names to be included without being referenced in a source file. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
// "resolveJsonModule": true, /* Enable importing .json files */
// "noResolve": true, /* Disallow `import`s, `require`s or `<reference>`s from expanding the number of files TypeScript should add to a project. */
/* JavaScript Support */
"allowJs": false /* Allow JavaScript files to be a part of your program. Use the `checkJS` option to get errors from these files. */,
"checkJs": false /* Enable error reporting in type-checked JavaScript files. */,
// "maxNodeModuleJsDepth": 1, /* Specify the maximum folder depth used for checking JavaScript files from `node_modules`. Only applicable with `allowJs`. */
/* Emit */
"declaration": true /* Generate .d.ts files from TypeScript and JavaScript files in your project. */,
"declarationMap": true /* Create sourcemaps for d.ts files. */,
// "emitDeclarationOnly": true, /* Only output d.ts files and not JavaScript files. */
"sourceMap": true /* Create source map files for emitted JavaScript files. */,
// "outFile": "./", /* Specify a file that bundles all outputs into one JavaScript file. If `declaration` is true, also designates a file that bundles all .d.ts output. */
"outDir": "./dist" /* Specify an output folder for all emitted files. */,
// "removeComments": true, /* Disable emitting comments. */
// "noEmit": true, /* Disable emitting files from a compilation. */
// "importHelpers": true, /* Allow importing helper functions from tslib once per project, instead of including them per-file. */
// "importsNotUsedAsValues": "remove", /* Specify emit/checking behavior for imports that are only used for types */
// "downlevelIteration": true, /* Emit more compliant, but verbose and less performant JavaScript for iteration. */
// "sourceRoot": "", /* Specify the root path for debuggers to find the reference source code. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Include sourcemap files inside the emitted JavaScript. */
// "inlineSources": true, /* Include source code in the sourcemaps inside the emitted JavaScript. */
// "emitBOM": true, /* Emit a UTF-8 Byte Order Mark (BOM) in the beginning of output files. */
// "newLine": "crlf", /* Set the newline character for emitting files. */
// "stripInternal": true, /* Disable emitting declarations that have `@internal` in their JSDoc comments. */
// "noEmitHelpers": true, /* Disable generating custom helper functions like `__extends` in compiled output. */
// "noEmitOnError": true, /* Disable emitting files if any type checking errors are reported. */
// "preserveConstEnums": true, /* Disable erasing `const enum` declarations in generated code. */
// "declarationDir": "./", /* Specify the output directory for generated declaration files. */
// "preserveValueImports": true, /* Preserve unused imported values in the JavaScript output that would otherwise be removed. */
/* Interop Constraints */
// "isolatedModules": true, /* Ensure that each file can be safely transpiled without relying on other imports. */
// "allowSyntheticDefaultImports": true, /* Allow 'import x from y' when a module doesn't have a default export. */
"esModuleInterop": true /* Emit additional JavaScript to ease support for importing CommonJS modules. This enables `allowSyntheticDefaultImports` for type compatibility. */,
// "preserveSymlinks": true, /* Disable resolving symlinks to their realpath. This correlates to the same flag in node. */
"forceConsistentCasingInFileNames": true /* Ensure that casing is correct in imports. */,
/* Type Checking */
"strict": true /* Enable all strict type-checking options. */,
// "noImplicitAny": true, /* Enable error reporting for expressions and declarations with an implied `any` type.. */
// "strictNullChecks": true, /* When type checking, take into account `null` and `undefined`. */
// "strictFunctionTypes": true, /* When assigning functions, check to ensure parameters and the return values are subtype-compatible. */
// "strictBindCallApply": true, /* Check that the arguments for `bind`, `call`, and `apply` methods match the original function. */
// "strictPropertyInitialization": true, /* Check for class properties that are declared but not set in the constructor. */
// "noImplicitThis": true, /* Enable error reporting when `this` is given the type `any`. */
// "useUnknownInCatchVariables": true, /* Type catch clause variables as 'unknown' instead of 'any'. */
// "alwaysStrict": true, /* Ensure 'use strict' is always emitted. */
// "noUnusedLocals": true, /* Enable error reporting when a local variables aren't read. */
// "noUnusedParameters": true, /* Raise an error when a function parameter isn't read */
// "exactOptionalPropertyTypes": true, /* Interpret optional property types as written, rather than adding 'undefined'. */
// "noImplicitReturns": true, /* Enable error reporting for codepaths that do not explicitly return in a function. */
// "noFallthroughCasesInSwitch": true, /* Enable error reporting for fallthrough cases in switch statements. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noImplicitOverride": true, /* Ensure overriding members in derived classes are marked with an override modifier. */
// "noPropertyAccessFromIndexSignature": true, /* Enforces using indexed accessors for keys declared using an indexed type */
// "allowUnusedLabels": true, /* Disable error reporting for unused labels. */
// "allowUnreachableCode": true, /* Disable error reporting for unreachable code. */
/* Completeness */
// "skipDefaultLibCheck": true, /* Skip type checking .d.ts files that are included with TypeScript. */
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["./src/**/*"],
"exclude": ["dist", "node_modules"]
}
+2 -2
View File
@@ -24,8 +24,8 @@
},
"devDependencies": {
"@tweakpane/core": "^1.0.9",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.5.0",
"typescript": "^4.5.4",
+2 -2
View File
@@ -56,8 +56,8 @@
"@babel/eslint-parser": "^7.18.2",
"@rollup/plugin-babel": "^5.3.1",
"@types/three": "^0.136.0",
"@typescript-eslint/eslint-plugin": "^5.21.0",
"@typescript-eslint/parser": "^5.21.0",
"@typescript-eslint/eslint-plugin": "^5.39.0",
"@typescript-eslint/parser": "^5.39.0",
"core-js": "^3.21.1",
"eslint": "^8.11.0",
"eslint-config-prettier": "^8.5.0",
+4
View File
@@ -32,6 +32,10 @@
"path": "packages/objectloader",
"name": "🌐 objectloader"
},
{
"path": "packages/shared",
"name": "📚 shared"
},
{
"path": "utils/helm",
"name": "⛵ helm"
+151 -210
View File
@@ -4841,6 +4841,7 @@ __metadata:
"@graphql-codegen/typescript-operations": 2.4.2
"@mdi/font": ^5.8.55
"@rushstack/eslint-patch": ^1.1.3
"@speckle/shared": "workspace:^"
"@speckle/viewer": "workspace:^"
"@tiptap/core": ^2.0.0-beta.176
"@tiptap/extension-bold": ^2.0.0-beta.26
@@ -4862,8 +4863,8 @@ __metadata:
"@types/lodash": ^4.14.180
"@types/mixpanel-browser": ^2.38.0
"@types/node": ^17.0.43
"@typescript-eslint/eslint-plugin": ^5.21.0
"@typescript-eslint/parser": ^5.21.0
"@typescript-eslint/eslint-plugin": ^5.39.0
"@typescript-eslint/parser": ^5.39.0
"@vitejs/plugin-vue2": ^1.1.2
"@vue/apollo-composable": ^4.0.0-alpha.19
"@vue/apollo-option": ^4.0.0-alpha.20
@@ -4989,6 +4990,7 @@ __metadata:
"@graphql-tools/schema": ^9.0.4
"@sentry/node": ^6.17.9
"@sentry/tracing": ^6.17.9
"@speckle/shared": "workspace:^"
"@swc/core": ^1.2.222
"@tiptap/core": ^2.0.0-beta.176
"@types/bull": ^3.15.9
@@ -5009,8 +5011,8 @@ __metadata:
"@types/verror": ^1.10.6
"@types/yargs": ^17.0.10
"@types/zxcvbn": ^4.4.1
"@typescript-eslint/eslint-plugin": ^5.32.0
"@typescript-eslint/parser": ^5.32.0
"@typescript-eslint/eslint-plugin": ^5.39.0
"@typescript-eslint/parser": ^5.39.0
apollo-server-express: ^3.10.2
axios: ^0.25.0
bcrypt: ^5.0.0
@@ -5086,14 +5088,33 @@ __metadata:
languageName: unknown
linkType: soft
"@speckle/shared@workspace:^, @speckle/shared@workspace:packages/shared":
version: 0.0.0-use.local
resolution: "@speckle/shared@workspace:packages/shared"
dependencies:
"@types/lodash": ^4.14.184
"@typescript-eslint/eslint-plugin": ^5.39.0
"@typescript-eslint/parser": ^5.39.0
eslint: ^8.11.0
eslint-config-prettier: ^8.5.0
lodash: ^4.17.0
rollup: ^2.79.1
rollup-plugin-delete: ^2.0.0
rollup-plugin-typescript2: ^0.34.1
typescript: ^4.5.4
peerDependencies:
"@tiptap/core": ^2.0.0-beta.176
languageName: unknown
linkType: soft
"@speckle/viewer-sandbox@workspace:packages/viewer-sandbox":
version: 0.0.0-use.local
resolution: "@speckle/viewer-sandbox@workspace:packages/viewer-sandbox"
dependencies:
"@speckle/viewer": "workspace:^"
"@tweakpane/core": ^1.0.9
"@typescript-eslint/eslint-plugin": ^5.21.0
"@typescript-eslint/parser": ^5.21.0
"@typescript-eslint/eslint-plugin": ^5.39.0
"@typescript-eslint/parser": ^5.39.0
eslint: ^8.11.0
eslint-config-prettier: ^8.5.0
tweakpane: ^3.0.8
@@ -5112,8 +5133,8 @@ __metadata:
"@speckle/objectloader": "workspace:^"
"@types/flat": ^5.0.2
"@types/three": ^0.136.0
"@typescript-eslint/eslint-plugin": ^5.21.0
"@typescript-eslint/parser": ^5.21.0
"@typescript-eslint/eslint-plugin": ^5.39.0
"@typescript-eslint/parser": ^5.39.0
camera-controls: ^1.33.1
core-js: ^3.21.1
eslint: ^8.11.0
@@ -5887,6 +5908,13 @@ __metadata:
languageName: node
linkType: hard
"@types/lodash@npm:^4.14.184":
version: 4.14.184
resolution: "@types/lodash@npm:4.14.184"
checksum: 6d9a4d67f7f9d0ec3fd21174f3dd3d00629dc1227eb469450eace53adbc1f7e2330699c28d0fe093e5f0fef0f0e763098be1f779268857213224af082b62be21
languageName: node
linkType: hard
"@types/long@npm:^4.0.0":
version: 4.0.2
resolution: "@types/long@npm:4.0.2"
@@ -6309,38 +6337,14 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:^5.21.0":
version: 5.22.0
resolution: "@typescript-eslint/eslint-plugin@npm:5.22.0"
"@typescript-eslint/eslint-plugin@npm:^5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/eslint-plugin@npm:5.39.0"
dependencies:
"@typescript-eslint/scope-manager": 5.22.0
"@typescript-eslint/type-utils": 5.22.0
"@typescript-eslint/utils": 5.22.0
debug: ^4.3.2
functional-red-black-tree: ^1.0.1
ignore: ^5.1.8
regexpp: ^3.2.0
semver: ^7.3.5
tsutils: ^3.21.0
peerDependencies:
"@typescript-eslint/parser": ^5.0.0
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 3b083f7003f091c3ef7b3970dca9cfd507ab8c52a9b8a52259c630010adf765e9766f0e6fd9c901fc0e807319a4e8c003e12287b1f12a4b9eb4d7222e8d6db83
languageName: node
linkType: hard
"@typescript-eslint/eslint-plugin@npm:^5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/eslint-plugin@npm:5.32.0"
dependencies:
"@typescript-eslint/scope-manager": 5.32.0
"@typescript-eslint/type-utils": 5.32.0
"@typescript-eslint/utils": 5.32.0
"@typescript-eslint/scope-manager": 5.39.0
"@typescript-eslint/type-utils": 5.39.0
"@typescript-eslint/utils": 5.39.0
debug: ^4.3.4
functional-red-black-tree: ^1.0.1
ignore: ^5.2.0
regexpp: ^3.2.0
semver: ^7.3.7
@@ -6351,7 +6355,7 @@ __metadata:
peerDependenciesMeta:
typescript:
optional: true
checksum: 9785c34d9742b51130237bfe244924ca6dfd529bdcc5932a5cf81558f0235099c963a11125df393037db51ce451f7ab9442aba3c3a8bb2e0607569a0e31480c8
checksum: 9d6835f3c2558f2287c5a45dc7d3b17b19c6777b5915b6ad737d892e5938746a3e76c3efd0e01156da0b17432a50d1e02480efc5105e8f9c75f1a3d45e18d6ee
languageName: node
linkType: hard
@@ -6372,57 +6376,20 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^5.21.0":
version: 5.22.0
resolution: "@typescript-eslint/parser@npm:5.22.0"
"@typescript-eslint/parser@npm:^5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/parser@npm:5.39.0"
dependencies:
"@typescript-eslint/scope-manager": 5.22.0
"@typescript-eslint/types": 5.22.0
"@typescript-eslint/typescript-estree": 5.22.0
debug: ^4.3.2
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 28a7d4b73154fc97336be9a4efd5ffdc659f748232c82479909e86ed87ed8a78d23280b3aaf532ca4e735caaffac43d9576e6af2dfd11865e30a9d70c8a3f275
languageName: node
linkType: hard
"@typescript-eslint/parser@npm:^5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/parser@npm:5.32.0"
dependencies:
"@typescript-eslint/scope-manager": 5.32.0
"@typescript-eslint/types": 5.32.0
"@typescript-eslint/typescript-estree": 5.32.0
"@typescript-eslint/scope-manager": 5.39.0
"@typescript-eslint/types": 5.39.0
"@typescript-eslint/typescript-estree": 5.39.0
debug: ^4.3.4
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 3fcfa183cad125c3198fd63701c6e13dad1cc984d309e8cd40ec9a2eb857902abfd7e9ee3f030b18eb1c18c795a61ea289ef147a7f9dfac38df905e7514316af
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/scope-manager@npm:5.22.0"
dependencies:
"@typescript-eslint/types": 5.22.0
"@typescript-eslint/visitor-keys": 5.22.0
checksum: ebf2ad44f4e5a4dfd55225419804f81f68056086c20f1549adbcca4236634eac3aae461e30d6cab6539ce6f42346ed6e1fbbb2710d2cc058a3283ef91a0fe174
languageName: node
linkType: hard
"@typescript-eslint/scope-manager@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/scope-manager@npm:5.32.0"
dependencies:
"@typescript-eslint/types": 5.32.0
"@typescript-eslint/visitor-keys": 5.32.0
checksum: 69bdeb029f39d1112299dc0cb0ddef30e51bdb782fdb79cc4e72fa448e00d71e39938d3bff3fa4ee43b3416c2e3b4564de2c37252914772b07eeedafb14412d6
checksum: f55a1ef540e5c70d063e0112c0c4c950504d263ce180480973ca72c015a3e826942ebe8aa0a6bbd557def987b07d9d410784b6c96aa000679dfa3f4cb00e063c
languageName: node
linkType: hard
@@ -6436,35 +6403,13 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/type-utils@npm:5.22.0"
"@typescript-eslint/scope-manager@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/scope-manager@npm:5.39.0"
dependencies:
"@typescript-eslint/utils": 5.22.0
debug: ^4.3.2
tsutils: ^3.21.0
peerDependencies:
eslint: "*"
peerDependenciesMeta:
typescript:
optional: true
checksum: 7128085bfbeca3a9646a795a34730cdfeca110bc00240569f6a7b3dc0854680afa56e015715675a78198b414de869339bd6036cc33cb14903919780a60321a95
languageName: node
linkType: hard
"@typescript-eslint/type-utils@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/type-utils@npm:5.32.0"
dependencies:
"@typescript-eslint/utils": 5.32.0
debug: ^4.3.4
tsutils: ^3.21.0
peerDependencies:
eslint: "*"
peerDependenciesMeta:
typescript:
optional: true
checksum: 4063808ca054789bebc6adb376d15c13e38f8ea14fa2842c38ae616d77fb77681b67a04b77887cf9ceb6f801ab3fc5eddfb6325779ab821404c62f36c56310bb
"@typescript-eslint/types": 5.39.0
"@typescript-eslint/visitor-keys": 5.39.0
checksum: 8d8b55eb219a23b3de64602ea23269fb1e16120ff03c58ebb7ed571372cbc591c5f4641b91ba1cf7fd02cf13f7bb906a7bd6e3db6da3543c97fcea8c61c15c07
languageName: node
linkType: hard
@@ -6485,17 +6430,20 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/types@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/types@npm:5.22.0"
checksum: 74f822c5a3b96bba05229eea4ed370c4bd48b17f475c37f08d6ba708adf65c3aa026bb544f1d0308c96e043b30015e396fd53b1e8e4e9fbb6dc9c92d2ccc0a15
languageName: node
linkType: hard
"@typescript-eslint/types@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/types@npm:5.32.0"
checksum: 6758f54d8d7763893cd7c1753f525ef1777eee8b558bf3d54fd2a2ce691ca0cf813c68a26e4db83a1deae4e4a62b247f1195e15a1f3577f1293849f9e55a232c
"@typescript-eslint/type-utils@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/type-utils@npm:5.39.0"
dependencies:
"@typescript-eslint/typescript-estree": 5.39.0
"@typescript-eslint/utils": 5.39.0
debug: ^4.3.4
tsutils: ^3.21.0
peerDependencies:
eslint: "*"
peerDependenciesMeta:
typescript:
optional: true
checksum: 2bab5c1a8bc0956d8f9ba1fb6db56a89f8e40c4f7bb0c07b1581aa4ed4c8259a64d67bc9c6fccbdc8e62fc9330d30c3c5a84f30f28112ddb1e3995d2791a5ac2
languageName: node
linkType: hard
@@ -6506,39 +6454,10 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/typescript-estree@npm:5.22.0"
dependencies:
"@typescript-eslint/types": 5.22.0
"@typescript-eslint/visitor-keys": 5.22.0
debug: ^4.3.2
globby: ^11.0.4
is-glob: ^4.0.3
semver: ^7.3.5
tsutils: ^3.21.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 2797a79d7d32a9a547b7f1de77a353d8e8c8519791f865f5e061bfc4918d12cdaddec51afa015f5aac5d068ef525c92bd65afc83b84dc9e52e697303acf0873a
languageName: node
linkType: hard
"@typescript-eslint/typescript-estree@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/typescript-estree@npm:5.32.0"
dependencies:
"@typescript-eslint/types": 5.32.0
"@typescript-eslint/visitor-keys": 5.32.0
debug: ^4.3.4
globby: ^11.1.0
is-glob: ^4.0.3
semver: ^7.3.7
tsutils: ^3.21.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 6aee08be5d36603d038fb8340f324f5cb38519150c9b37c012f0c1ff2a4d8cf22fbc6835de31d069949c2b3d8ed3e729076a724ef29db4289d9fe73b97c9d310
"@typescript-eslint/types@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/types@npm:5.39.0"
checksum: 5f67fe02adc87d594b6cc8ec5387d64419d4bbff701f4da51bf9929cdc50bc613df865e5a2457f13e4a637e8dfdb1fdf15fe8138f8968462de9e54ea056cc1a7
languageName: node
linkType: hard
@@ -6560,35 +6479,21 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/utils@npm:5.22.0"
"@typescript-eslint/typescript-estree@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/typescript-estree@npm:5.39.0"
dependencies:
"@types/json-schema": ^7.0.9
"@typescript-eslint/scope-manager": 5.22.0
"@typescript-eslint/types": 5.22.0
"@typescript-eslint/typescript-estree": 5.22.0
eslint-scope: ^5.1.1
eslint-utils: ^3.0.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 5019485e76d754a7a60c042545fd884dc666fddf9d4223ff706bbf0c275f19ea25a6b210fb5cf7ed368b019fe538fd854a925e9c6f12007d51b1731a29d95cc1
languageName: node
linkType: hard
"@typescript-eslint/utils@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/utils@npm:5.32.0"
dependencies:
"@types/json-schema": ^7.0.9
"@typescript-eslint/scope-manager": 5.32.0
"@typescript-eslint/types": 5.32.0
"@typescript-eslint/typescript-estree": 5.32.0
eslint-scope: ^5.1.1
eslint-utils: ^3.0.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: cfd88d93508c8fb0db17d2726691e1383db390357fa0637bd8111558fbe72da5130d995294001d71b1d929d620fbce3f20a70b277a77ca21a4241b3b470dc758
"@typescript-eslint/types": 5.39.0
"@typescript-eslint/visitor-keys": 5.39.0
debug: ^4.3.4
globby: ^11.1.0
is-glob: ^4.0.3
semver: ^7.3.7
tsutils: ^3.21.0
peerDependenciesMeta:
typescript:
optional: true
checksum: 86143dd9dd33ce65a20badbce5509ae4e77e9dfe202a6966dd416a8ce8147e5b05d12ce0b8f593ed7924797f6420d0bcd558c773042466e24386cdda24f24eb8
languageName: node
linkType: hard
@@ -6608,23 +6513,19 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.22.0":
version: 5.22.0
resolution: "@typescript-eslint/visitor-keys@npm:5.22.0"
"@typescript-eslint/utils@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/utils@npm:5.39.0"
dependencies:
"@typescript-eslint/types": 5.22.0
eslint-visitor-keys: ^3.0.0
checksum: d30dfa98dcce75da49a6a204a0132d42e63228c35681cb9b3643e47a0a24a633e259832d48d101265bd85b8eb5a9f2b4858f9447646c1d3df6a2ac54258dfe8f
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.32.0":
version: 5.32.0
resolution: "@typescript-eslint/visitor-keys@npm:5.32.0"
dependencies:
"@typescript-eslint/types": 5.32.0
eslint-visitor-keys: ^3.3.0
checksum: 1f9b756d648c2346a6e8538ffde729d3d9ce6621fded3d9f15c96aa0ebf8f511daf8232470423fb36359c2113538a4daaf3336181be78a0cfbfd297af91ce9ba
"@types/json-schema": ^7.0.9
"@typescript-eslint/scope-manager": 5.39.0
"@typescript-eslint/types": 5.39.0
"@typescript-eslint/typescript-estree": 5.39.0
eslint-scope: ^5.1.1
eslint-utils: ^3.0.0
peerDependencies:
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
checksum: 460a883775c24ed1a328db15101d58e1207797c97d2347a6e1adb2e26ef56ac0b525a326d2dd74333daf00e2b2e3dd28d51e0d4c4c38cdade2d132d8b08917cb
languageName: node
linkType: hard
@@ -6638,6 +6539,16 @@ __metadata:
languageName: node
linkType: hard
"@typescript-eslint/visitor-keys@npm:5.39.0":
version: 5.39.0
resolution: "@typescript-eslint/visitor-keys@npm:5.39.0"
dependencies:
"@typescript-eslint/types": 5.39.0
eslint-visitor-keys: ^3.3.0
checksum: 941e49fd1f4d2e42cd15a52a50f6f1102e2a83b173d182b5dd43ba3d7b7f0f1457d74fcaac710da4a19c28f804c78bc265d900802f4e2c7c46a608fff3204e7c
languageName: node
linkType: hard
"@vitejs/plugin-vue2@npm:^1.1.2":
version: 1.1.2
resolution: "@vitejs/plugin-vue2@npm:1.1.2"
@@ -11375,7 +11286,7 @@ __metadata:
languageName: node
linkType: hard
"eslint-visitor-keys@npm:^3.0.0, eslint-visitor-keys@npm:^3.3.0":
"eslint-visitor-keys@npm:^3.3.0":
version: 3.3.0
resolution: "eslint-visitor-keys@npm:3.3.0"
checksum: d59e68a7c5a6d0146526b0eec16ce87fbf97fe46b8281e0d41384224375c4e52f5ffb9e16d48f4ea50785cde93f766b0c898e31ab89978d88b0e1720fbfb7808
@@ -13467,7 +13378,7 @@ __metadata:
languageName: node
linkType: hard
"ignore@npm:^5.1.1, ignore@npm:^5.1.8, ignore@npm:^5.2.0":
"ignore@npm:^5.1.1, ignore@npm:^5.2.0":
version: 5.2.0
resolution: "ignore@npm:5.2.0"
checksum: 6b1f926792d614f64c6c83da3a1f9c83f6196c2839aa41e1e32dd7b8d174cef2e329d75caabb62cb61ce9dc432f75e67d07d122a037312db7caa73166a1bdb77
@@ -15152,7 +15063,7 @@ __metadata:
languageName: node
linkType: hard
"lodash@npm:^4.11.2, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.12, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:~4.17.0":
"lodash@npm:^4.11.2, lodash@npm:^4.17.0, lodash@npm:^4.17.10, lodash@npm:^4.17.11, lodash@npm:^4.17.12, lodash@npm:^4.17.14, lodash@npm:^4.17.15, lodash@npm:^4.17.19, lodash@npm:^4.17.20, lodash@npm:^4.17.21, lodash@npm:~4.17.0":
version: 4.17.21
resolution: "lodash@npm:4.17.21"
checksum: eb835a2e51d381e561e508ce932ea50a8e5a68f4ebdd771ea240d3048244a8d13658acbd502cd4829768c56f2e16bdd4340b9ea141297d472517b83868e677f7
@@ -19359,6 +19270,22 @@ __metadata:
languageName: node
linkType: hard
"rollup-plugin-typescript2@npm:^0.34.1":
version: 0.34.1
resolution: "rollup-plugin-typescript2@npm:0.34.1"
dependencies:
"@rollup/pluginutils": ^4.1.2
find-cache-dir: ^3.3.2
fs-extra: ^10.0.0
semver: ^7.3.7
tslib: ^2.4.0
peerDependencies:
rollup: ">=1.26.3"
typescript: ">=2.4.0"
checksum: 107e66b9ab1aaf4b237564e500ea9de9f2d3f0a81be5139dc753fc76bbf00a1a2230eb1ec59145d2dfc4c4da9be8211f1f3e1370007efe1e24ce45a00905e558
languageName: node
linkType: hard
"rollup-plugin-visualizer@npm:^5.7.1":
version: 5.8.1
resolution: "rollup-plugin-visualizer@npm:5.8.1"
@@ -19392,6 +19319,20 @@ __metadata:
languageName: node
linkType: hard
"rollup@npm:^2.79.1":
version: 2.79.1
resolution: "rollup@npm:2.79.1"
dependencies:
fsevents: ~2.3.2
dependenciesMeta:
fsevents:
optional: true
bin:
rollup: dist/bin/rollup
checksum: 6a2bf167b3587d4df709b37d149ad0300692cc5deb510f89ac7bdc77c8738c9546ae3de9322b0968e1ed2b0e984571f5f55aae28fa7de4cfcb1bc5402a4e2be6
languageName: node
linkType: hard
"rollup@npm:~2.78.0":
version: 2.78.1
resolution: "rollup@npm:2.78.1"
@@ -21297,23 +21238,23 @@ __metadata:
languageName: node
linkType: hard
"typescript@npm:^4.5.4":
version: 4.6.4
resolution: "typescript@npm:4.6.4"
"typescript@npm:^4.8.4":
version: 4.8.4
resolution: "typescript@npm:4.8.4"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: e7bfcc39cd4571a63a54e5ea21f16b8445268b9900bf55aee0e02ad981be576acc140eba24f1af5e3c1457767c96cea6d12861768fb386cf3ffb34013718631a
checksum: 3e4f061658e0c8f36c820802fa809e0fd812b85687a9a2f5430bc3d0368e37d1c9605c3ce9b39df9a05af2ece67b1d844f9f6ea8ff42819f13bcb80f85629af0
languageName: node
linkType: hard
"typescript@patch:typescript@npm%3A^4.5.4#~builtin<compat/typescript>":
version: 4.6.4
resolution: "typescript@patch:typescript@npm%3A4.6.4#~builtin<compat/typescript>::version=4.6.4&hash=bda367"
"typescript@patch:typescript@npm%3A^4.8.4#~builtin<compat/typescript>":
version: 4.8.4
resolution: "typescript@patch:typescript@npm%3A4.8.4#~builtin<compat/typescript>::version=4.8.4&hash=bda367"
bin:
tsc: bin/tsc
tsserver: bin/tsserver
checksum: 1cb434fbc637d347be90e3a0c6cd05e33c38f941713c8786d3031faf1842c2c148ba91d2fac01e7276b0ae3249b8633f1660e32686cc7a8c6a8fd5361dc52c66
checksum: 563a0ef47abae6df27a9a3ab38f75fc681f633ccf1a3502b1108e252e187787893de689220f4544aaf95a371a4eb3141e4a337deb9895de5ac3c1ca76430e5f0
languageName: node
linkType: hard