diff --git a/apps/designer/app/config.ts b/apps/designer/app/config.ts index 4ceb4e50d7..7bc8840d93 100644 --- a/apps/designer/app/config.ts +++ b/apps/designer/app/config.ts @@ -8,8 +8,6 @@ const config = { googleCallbackPath: "/google/callback", githubCallbackPath: "/github/callback", authPath: "/auth", - - defaultUploadPath: "uploads", }; export default config; export type Config = typeof config; diff --git a/apps/designer/app/designer/features/sidebar-left/types.ts b/apps/designer/app/designer/features/sidebar-left/types.ts index dc892aea33..dc658bb5f1 100644 --- a/apps/designer/app/designer/features/sidebar-left/types.ts +++ b/apps/designer/app/designer/features/sidebar-left/types.ts @@ -1,17 +1,3 @@ import { panels } from "./panels"; -import { z } from "zod"; -import { NodeOnDiskFile } from "@remix-run/node"; export type TabName = keyof typeof panels | "none"; - -const SingleImageInUpload = z.instanceof(NodeOnDiskFile); - -export const ImagesUpload = z.array(SingleImageInUpload); - -export type ImagesUpload = z.infer; -export type SingleImageInUpload = z.infer; - -export const ImagesUploadedSuccess = z.object({ - Location: z.string(), -}); -export type ImagesUploadedSuccess = z.infer; diff --git a/apps/designer/app/routes/designer/$id.tsx b/apps/designer/app/routes/designer/$id.tsx index 08d68d2173..f126356d9f 100644 --- a/apps/designer/app/routes/designer/$id.tsx +++ b/apps/designer/app/routes/designer/$id.tsx @@ -1,12 +1,11 @@ import { useLoaderData } from "@remix-run/react"; - import { ActionFunction, LoaderFunction } from "@remix-run/node"; import type { Project, Asset } from "@webstudio-is/react-sdk"; import { Designer, links } from "~/designer"; import * as db from "~/shared/db"; import config from "~/config"; import env from "~/env.server"; -import { uploadAsset } from "~/shared/uploads"; +import { uploadAsset } from "@webstudio-is/asset-uploader"; export { links }; @@ -36,6 +35,7 @@ export const action: ActionFunction = async ({ request, params }) => { await uploadAsset({ request, projectId: params.id, + db, }); } }; diff --git a/apps/designer/app/shared/uploads/upload-to-disk.ts b/apps/designer/app/shared/uploads/upload-to-disk.ts deleted file mode 100644 index 317b41e50a..0000000000 --- a/apps/designer/app/shared/uploads/upload-to-disk.ts +++ /dev/null @@ -1,35 +0,0 @@ -import type { ImagesUpload } from "~/designer/features/sidebar-left/types"; -import * as db from "~/shared/db"; -import path from "path"; -import sharp from "sharp"; - -export const uploadToDisk = async ({ - formData, - projectId, - folderInPublic, -}: { - formData: FormData; - projectId: string; - folderInPublic: string; -}) => { - const imagesInfo = ImagesUpload.parse(formData.getAll("image")); - const allInfo = imagesInfo.map(async (image) => { - const arrayBuffer = await image.arrayBuffer(); - const sharpImage = sharp(arrayBuffer as Uint8Array); - - const metadata = await sharpImage.metadata(); - - const data = { - name: image.name, - path: path.join("/", folderInPublic, image.name), - size: image.size, - metadata, - }; - - const newAsset = await db.assets.create(projectId, data); - - return newAsset; - }); - - await Promise.all(allInfo); -}; diff --git a/apps/designer/app/shared/uploads/upload-to-s3.ts b/apps/designer/app/shared/uploads/upload-to-s3.ts deleted file mode 100644 index 88004d8756..0000000000 --- a/apps/designer/app/shared/uploads/upload-to-s3.ts +++ /dev/null @@ -1,17 +0,0 @@ -import * as db from "~/shared/db"; - -export const uploadToS3 = async ({ - formData, - projectId, -}: { - formData: FormData; - projectId: string; -}) => { - const imagesInfo = formData.getAll("image") as Array; - const allInfo = imagesInfo.map(async (image) => { - const uploadedImage = JSON.parse(image); - const newAsset = await db.assets.createFromS3(projectId, uploadedImage); - return newAsset; - }); - await Promise.all(allInfo); -}; diff --git a/apps/designer/package.json b/apps/designer/package.json index 66c7c14990..3c40186559 100644 --- a/apps/designer/package.json +++ b/apps/designer/package.json @@ -19,8 +19,6 @@ "storybook:build": "build-storybook" }, "dependencies": { - "@aws-sdk/client-s3": "^3.131.0", - "@aws-sdk/lib-storage": "^3.131.0", "@lexical/react": "^0.3.5", "@prisma/client": "^3.14.0", "@radix-ui/colors": "^0.1.8", @@ -128,6 +126,7 @@ "esbuild-node-externals": "^1.4.1", "esbuild-node-loader": "^0.8.0", "eslint-config-custom": "*", + "@webstudio-is/asset-uploader": "*", "jest": "^27.5.1", "prettier": "^2.6.2", "prisma": "^3.14.0", diff --git a/packages/webstudio-asset-uploader/.gitignore b/packages/webstudio-asset-uploader/.gitignore new file mode 100644 index 0000000000..4c81583b6c --- /dev/null +++ b/packages/webstudio-asset-uploader/.gitignore @@ -0,0 +1,2 @@ +lib +generated \ No newline at end of file diff --git a/packages/webstudio-asset-uploader/LICENSE b/packages/webstudio-asset-uploader/LICENSE new file mode 100644 index 0000000000..1f6edad9a7 --- /dev/null +++ b/packages/webstudio-asset-uploader/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2022 Webstudio + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/packages/webstudio-asset-uploader/README.md b/packages/webstudio-asset-uploader/README.md new file mode 100644 index 0000000000..601fd6cabe --- /dev/null +++ b/packages/webstudio-asset-uploader/README.md @@ -0,0 +1,4 @@ +# Webstudio SDK + +Webstudio SDK is a TypeScript API that lets you use your Webstudio site or some components in your custom codebase or just render a complete Remix Document. +It is currently under development, but feel free to play with the the current [landing site](https://github.com/webstudio-is/webstudio-landing) diff --git a/packages/webstudio-asset-uploader/jest.config.js b/packages/webstudio-asset-uploader/jest.config.js new file mode 100644 index 0000000000..716a7294c9 --- /dev/null +++ b/packages/webstudio-asset-uploader/jest.config.js @@ -0,0 +1,10 @@ +module.exports = { + testEnvironment: "node", + testMatch: ["/src/**/*.test.ts"], + transform: { + "^.+\\.tsx?$": "esbuild-jest", + }, + moduleNameMapper: { + "^~/(.*)$": "/src/$1", + }, +}; diff --git a/packages/webstudio-asset-uploader/package.json b/packages/webstudio-asset-uploader/package.json new file mode 100644 index 0000000000..b6270b8f28 --- /dev/null +++ b/packages/webstudio-asset-uploader/package.json @@ -0,0 +1,34 @@ +{ + "name": "@webstudio-is/asset-uploader", + "version": "0.0.1", + "description": "Webstudio Asset Uploader", + "author": "Webstudio ", + "homepage": "https://webstudio.is", + "scripts": { + "typecheck": "tsc --noEmit", + "build": "rm -fr lib && tsc", + "test": "jest", + "dev": "tsc --watch", + "checks": "yarn typecheck && yarn test", + "prepublishOnly": "yarn checks && yarn build" + }, + "devDependencies": { + "@babel/core": "^7.17.12", + "@types/jest": "^27.4.1", + "@types/node": "^17.0.21", + "jest": "^27.5.1", + "ts-node-dev": "^2.0.0", + "typescript": "^4.6.2", + "@aws-sdk/client-s3": "^3.131.0", + "@aws-sdk/lib-storage": "^3.131.0", + "zod": "^3.17.3" + }, + "main": "src/index.ts", + "types": "src/index.ts", + "files": [ + "README.md", + "!*.test.*" + ], + "license": "MIT", + "private": false +} diff --git a/apps/designer/app/shared/uploads/constants.ts b/packages/webstudio-asset-uploader/src/constants.ts similarity index 100% rename from apps/designer/app/shared/uploads/constants.ts rename to packages/webstudio-asset-uploader/src/constants.ts diff --git a/apps/designer/app/shared/uploads/array-buffer-helpers.ts b/packages/webstudio-asset-uploader/src/helpers/array-buffer-helpers.ts similarity index 100% rename from apps/designer/app/shared/uploads/array-buffer-helpers.ts rename to packages/webstudio-asset-uploader/src/helpers/array-buffer-helpers.ts diff --git a/apps/designer/app/shared/uploads/index.ts b/packages/webstudio-asset-uploader/src/index.ts similarity index 77% rename from apps/designer/app/shared/uploads/index.ts rename to packages/webstudio-asset-uploader/src/index.ts index 7fdb41770e..2297f08dff 100644 --- a/apps/designer/app/shared/uploads/index.ts +++ b/packages/webstudio-asset-uploader/src/index.ts @@ -1,20 +1,21 @@ -import { sentryException } from "../sentry"; -import { s3UploadHandler } from "~/shared/uploads/s3-upload-handler"; -import { uploadToS3 } from "~/shared/uploads/upload-to-s3"; -import { uploadToDisk } from "~/shared/uploads/upload-to-disk"; import { DEFAULT_UPLPOAD_PATH } from "./constants"; import path from "path"; import { unstable_createFileUploadHandler, unstable_parseMultipartFormData, } from "@remix-run/node"; +import { s3UploadHandler } from "./targets/s3/handler"; +import { uploadToS3 } from "./targets/s3/uploader"; +import { uploadToDisk } from "./targets/disk/upload"; export const uploadAsset = async ({ request, projectId, + db, }: { request: Request; projectId: string; + db: unknown; }) => { const IS_S3_UPLOAD = process.env.S3_ENDPOINT && @@ -38,12 +39,14 @@ export const uploadAsset = async ({ await uploadToS3({ projectId, formData, + db, }); } else { await uploadToDisk({ projectId, formData, folderInPublic, + db, }); } @@ -52,12 +55,7 @@ export const uploadAsset = async ({ }; } catch (error) { if (error instanceof Error) { - sentryException({ - message: error.message, - }); - return { - errors: error.message, - }; + throw new Error(error.message); } } }; diff --git a/packages/webstudio-asset-uploader/src/targets/disk/upload.ts b/packages/webstudio-asset-uploader/src/targets/disk/upload.ts new file mode 100644 index 0000000000..df26701717 --- /dev/null +++ b/packages/webstudio-asset-uploader/src/targets/disk/upload.ts @@ -0,0 +1,42 @@ +import path from "path"; +import sharp from "sharp"; +import { ImagesUpload } from "~/types"; + +export const uploadToDisk = async ({ + formData, + projectId, + folderInPublic, + db, +}: { + formData: FormData; + projectId: string; + folderInPublic: string; + db: any; +}) => { + try { + const imagesInfo = ImagesUpload.parse(formData.getAll("image")); + const allInfo = imagesInfo.map(async (image) => { + const arrayBuffer = await image.arrayBuffer(); + const sharpImage = sharp(arrayBuffer as Uint8Array); + + const metadata = await sharpImage.metadata(); + + const data = { + name: image.name, + path: path.join("/", folderInPublic, image.name), + size: image.size, + metadata, + }; + + const newAsset = await db.assets.create(projectId, data); + + return newAsset; + }); + + await Promise.all(allInfo); + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } + } +}; diff --git a/apps/designer/app/shared/uploads/s3-upload-handler.ts b/packages/webstudio-asset-uploader/src/targets/s3/handler.ts similarity index 87% rename from apps/designer/app/shared/uploads/s3-upload-handler.ts rename to packages/webstudio-asset-uploader/src/targets/s3/handler.ts index d6c59bc4c0..ec9eea1526 100644 --- a/apps/designer/app/shared/uploads/s3-upload-handler.ts +++ b/packages/webstudio-asset-uploader/src/targets/s3/handler.ts @@ -2,13 +2,13 @@ import { UploadHandler } from "@remix-run/node"; import { PutObjectCommandInput, S3Client } from "@aws-sdk/client-s3"; import { Upload } from "@aws-sdk/lib-storage"; import ObjectID from "bson-objectid"; -import { sentryException } from "../sentry"; -import { ImagesUploadedSuccess } from "~/designer/features/sidebar-left/types"; + import sharp from "sharp"; +import { ImagesUploadedSuccess } from "~/types"; import { getArrayBufferFromIterable, getFilenameAndExtension, -} from "./array-buffer-helpers"; +} from "~/helpers/array-buffer-helpers"; export const s3UploadHandler: UploadHandler = async ({ data, @@ -57,9 +57,7 @@ export const s3UploadHandler: UploadHandler = async ({ }); } catch (error) { if (error instanceof Error) { - sentryException({ - message: error.message, - }); + throw new Error(error.message); } } }; diff --git a/packages/webstudio-asset-uploader/src/targets/s3/uploader.ts b/packages/webstudio-asset-uploader/src/targets/s3/uploader.ts new file mode 100644 index 0000000000..5183ee77b2 --- /dev/null +++ b/packages/webstudio-asset-uploader/src/targets/s3/uploader.ts @@ -0,0 +1,23 @@ +export const uploadToS3 = async ({ + formData, + projectId, + db, +}: { + formData: FormData; + projectId: string; + db: any; +}) => { + try { + const imagesInfo = formData.getAll("image") as Array; + const allInfo = imagesInfo.map(async (image) => { + const uploadedImage = JSON.parse(image); + const newAsset = await db.assets.createFromS3(projectId, uploadedImage); + return newAsset; + }); + await Promise.all(allInfo); + } catch (error) { + if (error instanceof Error) { + throw new Error(error.message); + } + } +}; diff --git a/packages/webstudio-asset-uploader/src/types.ts b/packages/webstudio-asset-uploader/src/types.ts new file mode 100644 index 0000000000..d781bb0add --- /dev/null +++ b/packages/webstudio-asset-uploader/src/types.ts @@ -0,0 +1,14 @@ +import { z } from "zod"; +import { NodeOnDiskFile } from "@remix-run/node"; + +const SingleImageInUpload = z.instanceof(NodeOnDiskFile); + +export const ImagesUpload = z.array(SingleImageInUpload); + +export type ImagesUpload = z.infer; +export type SingleImageInUpload = z.infer; + +export const ImagesUploadedSuccess = z.object({ + Location: z.string(), +}); +export type ImagesUploadedSuccess = z.infer; diff --git a/packages/webstudio-asset-uploader/tsconfig.json b/packages/webstudio-asset-uploader/tsconfig.json new file mode 100644 index 0000000000..ca4a7d6742 --- /dev/null +++ b/packages/webstudio-asset-uploader/tsconfig.json @@ -0,0 +1,16 @@ +// Extends can't use node's resolution rn https://github.com/dividab/tsconfig-paths/issues/209#issuecomment-1177261091 +{ + "extends": "../../node_modules/tsconfig/base.json", + "include": ["./src/**/*.ts", "./src/**/*.tsx"], + "compilerOptions": { + "lib": ["DOM", "DOM.Iterable", "ES2019"], + "module": "commonjs", + "target": "ES2019", + "strict": true, + "baseUrl": ".", + "paths": { + "~/*": ["./src/*"] + }, + "outDir": "./lib" + } +} diff --git a/yarn.lock b/yarn.lock index 62cd43092e..307e66fbe4 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2045,6 +2045,13 @@ resolved "https://registry.yarnpkg.com/@colors/colors/-/colors-1.5.0.tgz#bb504579c1cae923e6576a4f5da43d25f97bdbd9" integrity sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ== +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + "@design-systems/utils@2.12.0": version "2.12.0" resolved "https://registry.yarnpkg.com/@design-systems/utils/-/utils-2.12.0.tgz#955c108be07cb8f01532207cbfea8f848fa760c9" @@ -2417,6 +2424,14 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.7", "@jridgewell/trace-mapping@^0.3.9": version "0.3.14" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.14.tgz#b231a081d8f66796e475ad588a1ef473112701ed" @@ -4634,6 +4649,26 @@ mkdirp "^1.0.4" path-browserify "^1.0.1" +"@tsconfig/node10@^1.0.7": + version "1.0.9" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2" + integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" + integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== + "@types/acorn@^4.0.0": version "4.0.6" resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22" @@ -5058,6 +5093,16 @@ resolved "https://registry.yarnpkg.com/@types/stack-utils/-/stack-utils-2.0.1.tgz#20f18294f797f2209b5f65c8e3b5c8e8261d127c" integrity sha512-Hl219/BT5fLAaz6NDkSuhzasy49dwQS/DSdu4MdggFB8zcXv7vflBI3xp7FEmkmdDkBUI2bPUNeMttp2knYdxw== +"@types/strip-bom@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@types/strip-bom/-/strip-bom-3.0.0.tgz#14a8ec3956c2e81edb7520790aecf21c290aebd2" + integrity sha512-xevGOReSYGM7g/kUBZzPqCrR/KYAo+F0yiPc85WFTJa0MSLtyFTVTU6cJu/aV4mid7IffDIWqo69THF2o4JiEQ== + +"@types/strip-json-comments@0.0.30": + version "0.0.30" + resolved "https://registry.yarnpkg.com/@types/strip-json-comments/-/strip-json-comments-0.0.30.tgz#9aa30c04db212a9a0649d6ae6fd50accc40748a1" + integrity sha512-7NQmHra/JILCd1QqpSzl8+mJRc8ZHz3uDm8YV1Ks9IhK0epEiTw8aIErbvH9PI+6XbqhyIQy3462nEsn7UVzjQ== + "@types/tapable@^1", "@types/tapable@^1.0.5": version "1.0.8" resolved "https://registry.yarnpkg.com/@types/tapable/-/tapable-1.0.8.tgz#b94a4391c85666c7b73299fd3ad79d4faa435310" @@ -5588,6 +5633,11 @@ acorn-walk@^7.1.1, acorn-walk@^7.2.0: resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc" integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA== +acorn-walk@^8.1.1: + version "8.2.0" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" + integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== + acorn@^6.4.1: version "6.4.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-6.4.2.tgz#35866fd710528e92de10cf06016498e47e39e1e6" @@ -7379,6 +7429,11 @@ create-hmac@^1.1.0, create-hmac@^1.1.4, create-hmac@^1.1.7: safe-buffer "^5.0.1" sha.js "^2.4.8" +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + cross-spawn@^6.0.0, cross-spawn@^6.0.5: version "6.0.5" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-6.0.5.tgz#4a5ec7c64dfae22c3a14124dbacdee846d80cbc4" @@ -7930,6 +7985,13 @@ duplexify@^3.4.2, duplexify@^3.5.0, duplexify@^3.6.0: readable-stream "^2.0.0" stream-shift "^1.0.0" +dynamic-dedupe@^0.3.0: + version "0.3.0" + resolved "https://registry.yarnpkg.com/dynamic-dedupe/-/dynamic-dedupe-0.3.0.tgz#06e44c223f5e4e94d78ef9db23a6515ce2f962a1" + integrity sha512-ssuANeD+z97meYOqd50e04Ze5qp4bPqo8cCkI4TRjZkzAUgIDTrXV1R8QCdINpiI+hw14+rYazvTRdQrz0/rFQ== + dependencies: + xtend "^4.0.0" + eastasianwidth@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" @@ -15009,7 +15071,7 @@ resolve.exports@^1.1.0: resolved "https://registry.yarnpkg.com/resolve.exports/-/resolve.exports-1.1.0.tgz#5ce842b94b05146c0e03076985d1d0e7e48c90c9" integrity sha512-J1l+Zxxp4XK3LUDZ9m60LRJF/mAe4z6a4xyabPHk7pvK5t35dACV32iIjJDFeWZFfZlO29w6SZ67knR0tHzJtQ== -resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2: +resolve@^1.0.0, resolve@^1.10.0, resolve@^1.14.2, resolve@^1.19.0, resolve@^1.20.0, resolve@^1.3.2: version "1.22.1" resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== @@ -15057,7 +15119,7 @@ rfdc@^1.3.0: resolved "https://registry.yarnpkg.com/rfdc/-/rfdc-1.3.0.tgz#d0b7c441ab2720d05dc4cf26e01c89631d9da08b" integrity sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA== -rimraf@^2.5.4, rimraf@^2.6.3: +rimraf@^2.5.4, rimraf@^2.6.1, rimraf@^2.6.3: version "2.7.1" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== @@ -15615,7 +15677,7 @@ source-map-resolve@^0.5.0: source-map-url "^0.4.0" urix "^0.1.0" -source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.21, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: +source-map-support@^0.5.12, source-map-support@^0.5.16, source-map-support@^0.5.17, source-map-support@^0.5.21, source-map-support@^0.5.6, source-map-support@~0.5.12, source-map-support@~0.5.20: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" integrity sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w== @@ -16008,16 +16070,16 @@ strip-indent@^3.0.0: dependencies: min-indent "^1.0.0" +strip-json-comments@^2.0.0, strip-json-comments@~2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" + integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== + strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== -strip-json-comments@~2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-2.0.1.tgz#3c531942e908c2697c0ec344858c286c7ca0a60a" - integrity sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ== - style-loader@^1.3.0: version "1.3.0" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-1.3.0.tgz#828b4a3b3b7e7aa5847ce7bae9e874512114249e" @@ -16378,6 +16440,11 @@ tr46@~0.0.3: resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" integrity sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw== +tree-kill@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/tree-kill/-/tree-kill-1.2.2.tgz#4ca09a9092c88b73a7cdc5e8a01b507b0790a0cc" + integrity sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A== + trim-newlines@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/trim-newlines/-/trim-newlines-1.0.0.tgz#5887966bb582a4503a41eb524f7d35011815a613" @@ -16421,6 +16488,22 @@ ts-morph@12.0.0: "@ts-morph/common" "~0.11.0" code-block-writer "^10.1.1" +ts-node-dev@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/ts-node-dev/-/ts-node-dev-2.0.0.tgz#bdd53e17ab3b5d822ef519928dc6b4a7e0f13065" + integrity sha512-ywMrhCfH6M75yftYvrvNarLEY+SUXtUvU8/0Z6llrHQVBx12GiFk5sStF8UdfE/yfzk9IAq7O5EEbTQsxlBI8w== + dependencies: + chokidar "^3.5.1" + dynamic-dedupe "^0.3.0" + minimist "^1.2.6" + mkdirp "^1.0.4" + resolve "^1.0.0" + rimraf "^2.6.1" + source-map-support "^0.5.12" + tree-kill "^1.2.2" + ts-node "^10.4.0" + tsconfig "^7.0.0" + ts-node@8.9.1: version "8.9.1" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-8.9.1.tgz#2f857f46c47e91dcd28a14e052482eb14cfd65a5" @@ -16432,6 +16515,25 @@ ts-node@8.9.1: source-map-support "^0.5.17" yn "3.1.1" +ts-node@^10.4.0: + version "10.9.1" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.1.tgz#e73de9102958af9e1f0b168a6ff320e25adcff4b" + integrity sha512-NtVysVPkxxrwFGUUxGYhfux8k78pQB3JqYBXlLRZgdGUqTO5wU/UyHop5p70iEbGhB7q5KmiZiU0Y3KlJrScEw== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + ts-pnp@^1.1.6: version "1.2.0" resolved "https://registry.yarnpkg.com/ts-pnp/-/ts-pnp-1.2.0.tgz#a500ad084b0798f1c3071af391e65912c86bca92" @@ -16451,6 +16553,16 @@ tsconfig-paths@^4.0.0: minimist "^1.2.6" strip-bom "^3.0.0" +tsconfig@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/tsconfig/-/tsconfig-7.0.0.tgz#84538875a4dc216e5c4a5432b3a4dec3d54e91b7" + integrity sha512-vZXmzPrL+EmC4T/4rVlT2jNVMWCi/O4DIiSj3UHg1OE5kCKbk4mfrXc6dZksLgRM/TZlKnousKH9bbTazUWRRw== + dependencies: + "@types/strip-bom" "^3.0.0" + "@types/strip-json-comments" "0.0.30" + strip-bom "^3.0.0" + strip-json-comments "^2.0.0" + tslib@2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.3.1.tgz#e8a335add5ceae51aa261d32a490158ef042ef01" @@ -17041,6 +17153,11 @@ uvu@^0.5.0: kleur "^4.0.3" sade "^1.7.3" +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + v8-compile-cache@^2.0.3: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee"