From 8faa47f4156f012b94b0ecfcc734daebc84aa90e Mon Sep 17 00:00:00 2001 From: Venryx Date: Tue, 22 Jun 2021 01:46:09 -0700 Subject: [PATCH] * Made more progress on Knex migration-system setup. Backup before switching from snowpack to tsc for Packages/server. (this issue keeps happening when I try to compile the server code: https://github.com/snowpackjs/snowpack/issues/3468) --- Packages/client/Scripts/tsconfig.json | 28 +----- Packages/common/package.json | 2 +- Packages/server/Knex/@MigrationTemplate.ts | 4 + .../Knex/Migrations/20210622053410_Test1.ts | 28 ++++++ Packages/server/Knex/knexfile.ts | 36 ++++++++ Packages/server/Knex/package.json | 3 + Packages/server/README.md | 26 +++++- Packages/server/Scripts/InitDB.sql | 19 ---- Packages/server/Scripts/InitDB.ts | 52 +++++++++++ Packages/server/Scripts/tsconfig.json | 31 +++++++ Packages/server/Source/index.ts | 3 +- Packages/server/package.json | 3 +- Packages/server/snowpack.config.js | 5 +- package-scripts.js | 30 +++--- yarn.lock | 91 ++++++++++++++++++- 15 files changed, 289 insertions(+), 72 deletions(-) create mode 100644 Packages/server/Knex/@MigrationTemplate.ts create mode 100644 Packages/server/Knex/Migrations/20210622053410_Test1.ts create mode 100644 Packages/server/Knex/knexfile.ts create mode 100644 Packages/server/Knex/package.json delete mode 100644 Packages/server/Scripts/InitDB.sql create mode 100644 Packages/server/Scripts/InitDB.ts create mode 100644 Packages/server/Scripts/tsconfig.json diff --git a/Packages/client/Scripts/tsconfig.json b/Packages/client/Scripts/tsconfig.json index 420ef4d50..6d7feda67 100644 --- a/Packages/client/Scripts/tsconfig.json +++ b/Packages/client/Scripts/tsconfig.json @@ -2,37 +2,19 @@ "compilerOptions": { // general "watch": true, - //"outDir": "Source_JS", "forceConsistentCasingInFileNames": true, // creates duplicates in import-helper plugins otherwise // modules/paths "module": "ES2015", //"module": "commonjs", // needed, since ts-node does not yet support imports from es2015-modules "moduleResolution": "node", - "rootDir": ".", - "baseUrl": ".", - //"baseUrl": ".", // we need it at root so we can apply path-overrides, even when requester is outside of Source folder - "paths": { // ("paths" is relative to "baseUrl") - // remove @types/node and such (conflicts with typescript web definitions) - "@types/node": ["../Typings/empty.d.ts"], - // remove @types/react/global.d.ts, as it breaks the auto-import-finder for react-vcomponents/Text - "react/global.d.ts": ["../Typings/empty.d.ts"], - "react-vextensions/node_modules/react/global.d.ts": ["../Typings/empty.d.ts"], - "react-vcomponents/node_modules/react/global.d.ts": ["../Typings/empty.d.ts"] - //"WebpackConfig": ["./Build/WebpackConfig.ts"] - }, + //"rootDir": ".", + //"baseUrl": ".", "resolveJsonModule": true, // compiler options "target": "ES2015", - /*"target": "esnext", - "lib": [ - "es5", - "es6", - "ESNext", - "dom" - ],*/ "jsx": "react", "noImplicitAny": false, "alwaysStrict": true, // alternative: "@babel/plugin-transform-strict-mode"; went with this since doesn't require another npm package @@ -45,9 +27,5 @@ "../Typings/**/*.d.ts", "../Scripts/**/*.ts", "../Scripts/**/*.tsx", - "Config.ts", - "Build/WebpackConfig.ts", - //"../node_modules/js-vextensions/**/*.ts", - ], - "compileOnSave": true + ] } \ No newline at end of file diff --git a/Packages/common/package.json b/Packages/common/package.json index ea449c066..23e8f7744 100644 --- a/Packages/common/package.json +++ b/Packages/common/package.json @@ -5,6 +5,6 @@ "main": "./Source/index.ts", "module": "./Source/index.ts", "scripts": { - "start": "nps" + "start": "cd ../.. && npx nps" } } diff --git a/Packages/server/Knex/@MigrationTemplate.ts b/Packages/server/Knex/@MigrationTemplate.ts new file mode 100644 index 000000000..7adb1e3db --- /dev/null +++ b/Packages/server/Knex/@MigrationTemplate.ts @@ -0,0 +1,4 @@ +import {Knex} from "knex"; + +export async function up(knex: Knex) { +} \ No newline at end of file diff --git a/Packages/server/Knex/Migrations/20210622053410_Test1.ts b/Packages/server/Knex/Migrations/20210622053410_Test1.ts new file mode 100644 index 000000000..43989f252 --- /dev/null +++ b/Packages/server/Knex/Migrations/20210622053410_Test1.ts @@ -0,0 +1,28 @@ +import {Knex} from "knex"; + +// doesn't work because this file's code runs *after* knex checks for the db's existence +/*async function CreateDBIfNotExists(name: string) { + const config = require("../knexfile"); + let knex = new Knex.Client({ + client: "postgresql", + connection: { + ...config.development.connection, + //host: "localhost", + database: null, + }, + }) + + // Lets create our database if it does not exist + await knex.raw("CREATE DATABASE IF NOT EXISTS ??", name) +}*/ + +export async function up(knex: Knex) { + console.log("Starting"); + //CreateDBIfNotExists("debate-map"); + knex.schema.createTable("users_draft", t=>{ + t.text("id"); + t.text("displayName"); + t.text("photoURL"); + t.bigInteger("joinDate"); + }); +} \ No newline at end of file diff --git a/Packages/server/Knex/knexfile.ts b/Packages/server/Knex/knexfile.ts new file mode 100644 index 000000000..f369b2c6c --- /dev/null +++ b/Packages/server/Knex/knexfile.ts @@ -0,0 +1,36 @@ +require("dotenv").config({path: "../../.env"}); + +module.exports = { + development: { + client: "postgresql", + connection: { + database: "debate-map", + user: process.env.LOCALDB_USERNAME, + password: process.env.LOCALDB_PASSWORD, + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: "knex_migrations", + directory: "./Migrations", + }, + acquireConnectionTimeout: 3000, + }, + /*production: { + client: "postgresql", + connection: { + database: "debate-map", + user: process.env.LOCALDB_USERNAME, + password: process.env.LOCALDB_PASSWORD, + }, + pool: { + min: 2, + max: 10, + }, + migrations: { + tableName: "knex_migrations", + } + },*/ +}; \ No newline at end of file diff --git a/Packages/server/Knex/package.json b/Packages/server/Knex/package.json new file mode 100644 index 000000000..a2091cee3 --- /dev/null +++ b/Packages/server/Knex/package.json @@ -0,0 +1,3 @@ +{ + "type": "commonjs" +} \ No newline at end of file diff --git a/Packages/server/README.md b/Packages/server/README.md index d76bdd63f..7b849f5f8 100644 --- a/Packages/server/README.md +++ b/Packages/server/README.md @@ -22,14 +22,32 @@ max_replication_slots = 10 4) Create a Postgres database for this project, by running: `createdb debate-map` -5) Init `debate-map` db in PostgreSQL, by running `yarn start initDB`. - -6) Set environment variables for the database's username (PGUSER) and password (PGPASSWORD). +5) Init `debate-map` db in PostgreSQL, by running `yarn start server.initDB`. ### Remote server TODO +### Environment variables + +Create a `.env` file in the repo root, following this template: +``` +# GCP web-client key/id +CLIENT_ID=XXX +CLIENT_SECRET=XXX + +# local database +LOCALDB_USERNAME=XXX +LOCALDB_PASSWORD=XXX +``` + ## Editing + running -See here: \ No newline at end of file +See here: + +## Database migrations + +See here for overview: + +Actions: +* To create a new migration, run: `npx knex --knexfile Knex/knexfile.ts migrate:make MIGRATION_NAME` \ No newline at end of file diff --git a/Packages/server/Scripts/InitDB.sql b/Packages/server/Scripts/InitDB.sql deleted file mode 100644 index 42802a5dd..000000000 --- a/Packages/server/Scripts/InitDB.sql +++ /dev/null @@ -1,19 +0,0 @@ -/* -Notes: -* When you want to make a schema change, change it here first, then either run the relevant command below (if new table), or manually replicate the change in the live database. (using pgAdmin, or a manual psql command) -*/ - ---drop schema if exists app_public cascade; ---create schema app_public; - ---set search_path to app_public, public; ---ALTER DATABASE "game-dive" SET search_path TO app_public, public; -ALTER DATABASE "game-dive" SET search_path TO app_public; - -/*create table "ssb_user_fighter_rankings" ( - "id" text primary key, - "name" text not null -); -insert into "ssb_fighters" (id, name) values - ("0000000000000000000001", "Test1"), - ("0000000000000000000002", "Test2");*/ \ No newline at end of file diff --git a/Packages/server/Scripts/InitDB.ts b/Packages/server/Scripts/InitDB.ts new file mode 100644 index 000000000..5e12b6510 --- /dev/null +++ b/Packages/server/Scripts/InitDB.ts @@ -0,0 +1,52 @@ +import Knex from "knex"; +//import config from "../Knex/knexfile"; +import {createRequire} from "module"; +const require = createRequire(import.meta.url); + +const dbName = "debate-map"; + +const config = require("../Knex/knexfile"); +async function CreateDBIfNotExists(name: string) { + console.log("Test1:"); + /*let knex = new Knex.Client({ + //client: "postgresql", + client: "pg", + //connection: `postgres://${process.env.PGUSER}:${process.env.PGPASSWORD}@localhost:5432/debate-map`, + //connection: `postgres://${config.development.connection.user}:${config.development.connection.password}@localhost:5432/debate-map`, + //connection: `postgres://${config.development.connection.user}:${config.development.connection.password}@localhost:5432`, + connection: { + ...config.development.connection, + //host: "localhost", port: 5432, + host: "127.0.0.1", //port: 5432, + //host: "localhost:5432", + database: null, + }, + });*/ + const config_final = JSON.parse(JSON.stringify(config.development)); + delete config_final.connection.database; + let knex = new Knex.Client(config_final); + + console.log("Creating"); + await knex.raw("CREATE DATABASE IF NOT EXISTS ??", name); + console.log("Created"); +} + +async function Main() { + await CreateDBIfNotExists(dbName); + console.log("Created2"); + + // now that our database confirmed to exist, create another knex object (with db-name specified) so we can run our migrations + const knex = new Knex.Client({ + //client: "postgresql", + client: "pg", + connection: { + ...config.development.connection, + //host: "localhost", + database: dbName, + }, + }); + + await knex["migrate"].latest(); +} + +Main().catch(console.log).then(()=>process.exit()); \ No newline at end of file diff --git a/Packages/server/Scripts/tsconfig.json b/Packages/server/Scripts/tsconfig.json new file mode 100644 index 000000000..406ebd099 --- /dev/null +++ b/Packages/server/Scripts/tsconfig.json @@ -0,0 +1,31 @@ +{ + "compilerOptions": { + // general + "watch": true, + "forceConsistentCasingInFileNames": true, // creates duplicates in import-helper plugins otherwise + + // modules/paths + "module": "ESNext", + //"module": "commonjs", // needed, since ts-node does not yet support imports from es2015-modules + "moduleResolution": "node", + //"rootDir": ".", + //"baseUrl": ".", + + "resolveJsonModule": true, + + // compiler options + "target": "ES2015", + "jsx": "react", + "noImplicitAny": false, + "alwaysStrict": true, // alternative: "@babel/plugin-transform-strict-mode"; went with this since doesn't require another npm package + + "experimentalDecorators": true, + "allowSyntheticDefaultImports": true, + "esModuleInterop": true + }, + "include": [ + "../Typings/**/*.d.ts", + "../Scripts/**/*.ts", + "../Scripts/**/*.tsx", + ] +} \ No newline at end of file diff --git a/Packages/server/Source/index.ts b/Packages/server/Source/index.ts index 4ffada933..7218564ff 100644 --- a/Packages/server/Source/index.ts +++ b/Packages/server/Source/index.ts @@ -8,7 +8,6 @@ const postgraphile = postgraphile_["postgraphile"] as typeof import("postgraphil const makePluginHook = postgraphile_["makePluginHook"] as typeof import("postgraphile").makePluginHook; import {GeneratePatchesPlugin} from "@pg-lq/postgraphile-plugin"; import {Pool, PoolClient} from "pg"; - import {createRequire} from "module"; import {AuthenticationPlugin} from "./Mutations/Authentication"; import {SetUpAuthHandling} from "./AuthHandling"; @@ -22,7 +21,7 @@ export const variant = launchOpts.variant; const app = express(); -const dbURL = process.env.DATABASE_URL || `postgres://${process.env.PGUSER}:${process.env.PGPASSWORD}@localhost:5432/game-dive`; +const dbURL = process.env.DATABASE_URL || `postgres://${process.env.PGUSER}:${process.env.PGPASSWORD}@localhost:5432/debate-map`; const dbPort = process.env.PORT || 3105 as number; const pluginHook = makePluginHook([ diff --git a/Packages/server/package.json b/Packages/server/package.json index 9c4b47431..788c92e60 100644 --- a/Packages/server/package.json +++ b/Packages/server/package.json @@ -3,7 +3,7 @@ "type": "module", "private": true, "scripts": { - "start": "nps", + "start": "cd ../.. && npx nps", "preinstall": "npx only-allow yarn" }, "devDependencies": { @@ -25,6 +25,7 @@ "cookie-session": "^1.4.0", "dotenv": "^10.0.0", "express": "^4.17.1", + "knex": "^0.95.6", "passport": "^0.4.1", "passport-google-oauth20": "^2.0.0", "postgraphile": "^4.11.0", diff --git a/Packages/server/snowpack.config.js b/Packages/server/snowpack.config.js index d4e56d00c..3330ada3b 100644 --- a/Packages/server/snowpack.config.js +++ b/Packages/server/snowpack.config.js @@ -18,6 +18,7 @@ const config = { },*/ exclude: [ `./Scripts/**/*`, + `./Knex/**/*`, `./Build/**/*`, `./*.json`, `./*.js` @@ -40,6 +41,7 @@ const config = { //"fast-json-patch", //"postgraphile/build/postgraphile/http/mapAsyncIterator".replace(/\//g, "\\"), //"iterall", + //"util", ], external: builtinModules.concat( "express", "postgraphile", "commander", @@ -49,8 +51,9 @@ const config = { "@n1ru4l/graphql-live-query-patch", "iterall", "postgraphile/build/postgraphile/http/mapAsyncIterator", - "postgraphile/build/postgraphile/http/mapAsyncIterator.js" + "postgraphile/build/postgraphile/http/mapAsyncIterator.js", ), + polyfillNode: true, }, devOptions: { open: "none", diff --git a/package-scripts.js b/package-scripts.js index 349904b51..5dcec9294 100644 --- a/package-scripts.js +++ b/package-scripts.js @@ -1,7 +1,12 @@ -function TSScript(scriptPath) { +function TSScript(packageName, scriptSubpath) { + let cdCommand = ""; + if (packageName) { + cdCommand = `cd Packages/${packageName} && `; + } + const envPart = `TS_NODE_SKIP_IGNORE=true TS_NODE_PROJECT=Scripts/tsconfig.json TS_NODE_TRANSPILE_ONLY=true`; const nodeFlags = `--loader ts-node/esm.mjs --experimental-specifier-resolution=node`; - return `cd Packages/client && cross-env ${envPart} node ${nodeFlags} ${scriptPath}`; + return `${cdCommand}cross-env ${envPart} node ${nodeFlags} ${scriptSubpath}`; } //const memLimit = 4096; @@ -10,32 +15,20 @@ const memLimit = 8192; // in megabytes const scripts = {}; module.exports.scripts = scripts; -Object.assign(scripts, { - clean: "shx rm -rf Dist", - //compile: `cross-env ts-node --project Scripts/tsconfig.json --ignore none Scripts/Bin/Compile`, - compile: TSScript("Scripts/Bin/Compile"), - /*lint: { - default: 'eslint Source Tests Scripts', - fix: 'nps "lint --fix"' - },*/ - //dev: `nps "bakeConfig nodemon Scripts/Bin/Server --watch Scripts --max_old_space_size=${memLimit}"`, - //dev: `nps "bakeConfig ts-node-dev --project Scripts/tsconfig.json Scripts/Bin/Server"`, - //dev: `cross-env-shell NODE_ENV=development _USE_TSLOADER=true NODE_OPTIONS="--max-old-space-size=${memLimit} --experimental-modules" "npm start dev-part2"`, -}); - function GetServeCommand(nodeEnv = null) { return `cross-env-shell ${nodeEnv ? `NODE_ENV=${nodeEnv} ` : ""}_USE_TSLOADER=true NODE_OPTIONS="--max-old-space-size=${memLimit}" "npm start client.dev.part2"`; } Object.assign(scripts, { client: { dev: { + //default: `cross-env-shell NODE_ENV=development _USE_TSLOADER=true NODE_OPTIONS="--max-old-space-size=${memLimit} --experimental-modules" "npm start dev-part2"`, default: GetServeCommand("development"), staticServe: GetServeCommand(), // same as above, except with NODE_ENV=null (for static-serving of files in Dist folder) noDebug: `nps "dev --no_debug"`, //part2: `cross-env TS_NODE_OPTIONS="--experimental-modules" ts-node-dev --project Scripts/tsconfig.json Scripts/Bin/Server.ts`, //part2: `cross-env NODE_OPTIONS="--experimental-modules" ts-node --project Scripts/tsconfig.json Scripts/Bin/Server.ts`, //part2: `cross-env ts-node-dev --project Scripts/tsconfig.json --ignore none Scripts/Bin/Server.ts`, - part2: TSScript("Scripts/Bin/Server"), // for now, call directly; no ts-node-dev [watching] till figure out use with new type:module approach + part2: TSScript("client", "Scripts/Bin/Server"), // for now, call directly; no ts-node-dev [watching] till figure out use with new type:module approach //withStats: `cross-env-shell NODE_ENV=development _USE_TSLOADER=true OUTPUT_STATS=true NODE_OPTIONS="--max-old-space-size=${memLimit} --experimental-modules" "ts-node-dev --project Scripts/tsconfig.json Scripts/Bin/Server"`, withStats: `cross-env-shell NODE_ENV=development _USE_TSLOADER=true OUTPUT_STATS=true NODE_OPTIONS="--max-old-space-size=${memLimit}" "ts-node-dev --project Scripts/tsconfig.json --ignore none Scripts/Bin/Server"`, @@ -45,7 +38,7 @@ Object.assign(scripts, { run: "cypress run", }, clean: "cd Packages/client && shx rm -rf Dist", - compile: TSScript("Scripts/Bin/Compile"), + compile: TSScript("client", "Scripts/Bin/Compile"), build: { default: `cross-env-shell "npm start client.clean && npm start client.compile"`, dev: `cross-env NODE_ENV=development npm start client.build`, @@ -71,7 +64,8 @@ Object.assign(scripts, { }, server: { // setup - initDB: "psql -f ./Packages/server/Scripts/InitDB.sql debate-map", + //initDB: "psql -f ./Packages/server/Scripts/InitDB.sql debate-map", + initDB: TSScript("server", "Scripts/InitDB.ts"), // first terminal dev: "cd Packages/server && snowpack build --watch", diff --git a/yarn.lock b/yarn.lock index 542aec0be..163b82cdc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4126,6 +4126,13 @@ __metadata: languageName: node linkType: hard +"colorette@npm:1.2.1": + version: 1.2.1 + resolution: "colorette@npm:1.2.1" + checksum: 1cc21ad4b84777a424794f78b6bb6a44b614ae17dcea91762199339f8047598e6d981249eeef7ea588c99eaf062be8fcdcd4866c112998922ed854db6dde96f9 + languageName: node + linkType: hard + "colorette@npm:^1.2.1, colorette@npm:^1.2.2": version: 1.2.2 resolution: "colorette@npm:1.2.2" @@ -4177,7 +4184,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^7.0.0, commander@npm:^7.2.0": +"commander@npm:^7.0.0, commander@npm:^7.1.0, commander@npm:^7.2.0": version: 7.2.0 resolution: "commander@npm:7.2.0" checksum: bdc0eca5e25cd24af8440163d3c9a996785bbac4b49a590365699cdc1ed08cefbac8f268153208ab2bc5dc3cb1d3fb573fd1590c681e36e371342186bd331a4c @@ -4835,6 +4842,18 @@ __metadata: languageName: node linkType: hard +"debug@npm:4.3.1": + version: 4.3.1 + resolution: "debug@npm:4.3.1" + dependencies: + ms: 2.1.2 + peerDependenciesMeta: + supports-color: + optional: true + checksum: 0d41ba5177510e8b388dfd7df143ab0f9312e4abdaba312595461511dac88e9ef8101939d33b4e6d37e10341af6a5301082e4d7d6f3deb4d57bc05fc7d296fad + languageName: node + linkType: hard + "debug@npm:^3.1.0, debug@npm:^3.2.7": version: 3.2.7 resolution: "debug@npm:3.2.7" @@ -5050,6 +5069,7 @@ __metadata: cookie-session: ^1.4.0 dotenv: ^10.0.0 express: ^4.17.1 + knex: ^0.95.6 nps: ^5.10.0 passport: ^0.4.1 passport-google-oauth20: ^2.0.0 @@ -5733,6 +5753,13 @@ __metadata: languageName: node linkType: hard +"esm@npm:^3.2.25": + version: 3.2.25 + resolution: "esm@npm:3.2.25" + checksum: 12a0272aaa15ce4bc07e52cbb66d471cf56ad81ad1a3c1d9f6fa1e29e8c2712716333825e2572f9dbdfdc787e5717a75cb00ce2846e2a50e2bba6971c24402f3 + languageName: node + linkType: hard + "espree@npm:^5.0.1": version: 5.0.1 resolution: "espree@npm:5.0.1" @@ -6604,6 +6631,13 @@ fsevents@~2.1.2: languageName: node linkType: hard +"getopts@npm:2.2.5": + version: 2.2.5 + resolution: "getopts@npm:2.2.5" + checksum: cd7db413446c3a3773ec8f1bc9d3b4dcf43278a6c7360b88ff2e81637d55023d3f0009b49dbf3f73425492fa4d44aeaa66e3f831770be9366b0ad979c299e8ba + languageName: node + linkType: hard + "getos@npm:3.1.1": version: 3.1.1 resolution: "getos@npm:3.1.1" @@ -8328,6 +8362,40 @@ fsevents@~2.1.2: languageName: node linkType: hard +"knex@npm:^0.95.6": + version: 0.95.6 + resolution: "knex@npm:0.95.6" + dependencies: + colorette: 1.2.1 + commander: ^7.1.0 + debug: 4.3.1 + escalade: ^3.1.1 + esm: ^3.2.25 + getopts: 2.2.5 + interpret: ^2.2.0 + lodash: ^4.17.21 + pg-connection-string: 2.4.0 + rechoir: ^0.7.0 + resolve-from: ^5.0.0 + tarn: ^3.0.1 + tildify: 2.0.0 + peerDependenciesMeta: + mysql: + optional: true + mysql2: + optional: true + pg: + optional: true + sqlite3: + optional: true + tedious: + optional: true + bin: + knex: bin/cli.js + checksum: c4d8cae48acae446fae25f6f7a2af0553bbab5817e747d2e14b67e5dccd6f044fbdafe9a603ebc8844a53300866a9c6ef290440f5a82ae016652c789a21a755c + languageName: node + linkType: hard + "lazy-ass@npm:1.6.0": version: 1.6.0 resolution: "lazy-ass@npm:1.6.0" @@ -10470,6 +10538,13 @@ fsevents@~2.1.2: languageName: node linkType: hard +"pg-connection-string@npm:2.4.0": + version: 2.4.0 + resolution: "pg-connection-string@npm:2.4.0" + checksum: fdb3ec1c3daa8356381b1de3ed5fe03269e69d88644c4eb83a30aec1d1e320e0a8450d7ff8c04666dd06a4798c996c9dd006497f038d338790667965ec940d1d + languageName: node + linkType: hard + "pg-connection-string@npm:^2.0.0, pg-connection-string@npm:^2.5.0": version: 2.5.0 resolution: "pg-connection-string@npm:2.5.0" @@ -13796,6 +13871,13 @@ resolve@^2.0.0-next.3: languageName: node linkType: hard +"tarn@npm:^3.0.1": + version: 3.0.1 + resolution: "tarn@npm:3.0.1" + checksum: 132dd6c6c38363cacba65278c02df4e3f56706b8bd428e7b1962501d601a63b39181407035511f50257acf2f6682f6ebc8df5b71b6bbe4487fe12a239ffd59d9 + languageName: node + linkType: hard + "terser-webpack-plugin@npm:^5.1.1": version: 5.1.3 resolution: "terser-webpack-plugin@npm:5.1.3" @@ -13859,6 +13941,13 @@ resolve@^2.0.0-next.3: languageName: node linkType: hard +"tildify@npm:2.0.0": + version: 2.0.0 + resolution: "tildify@npm:2.0.0" + checksum: c5743c23c5ad4da4afa4c4282bebcd999a702ab39b728d288741b2aa3a7dd40c7c869399170a24ed4f914abb455d1dfd3098749c1b2bd643f6ce833f361892fa + languageName: node + linkType: hard + "timsort@npm:^0.3.0": version: 0.3.0 resolution: "timsort@npm:0.3.0"