Page MenuHomeSealhub

No OneTemporary

This file is larger than 256 KB, so syntax highlighting was skipped.
diff --git a/.eslintrc.cjs b/.eslintrc.cjs
deleted file mode 100644
index eea6419..0000000
--- a/.eslintrc.cjs
+++ /dev/null
@@ -1,44 +0,0 @@
-module.exports = {
- env: { node: true },
- parser: "@typescript-eslint/parser",
- plugins: ["@typescript-eslint", "prettier"],
- extends: [
- "eslint:recommended",
- "plugin:@typescript-eslint/recommended",
- "plugin:@typescript-eslint/recommended-requiring-type-checking",
- "plugin:prettier/recommended",
- ],
- ignorePatterns: [".eslintrc.js", "src/**/*.test.ts", "@types/*"],
- parserOptions: {
- sourceType: "module",
- ecmaFeatures: {
- modules: true,
- },
- project: ["./tsconfig.json"],
- },
- rules: {
- "@typescript-eslint/require-await": 0,
- "no-await-in-loop": 2,
- "@typescript-eslint/no-unused-vars": [
- "warn",
- { args: "none", varsIgnorePattern: "^_" },
- ],
- "@typescript-eslint/no-this-alias": 0,
- "@typescript-eslint/no-empty-function": 0,
- "@typescript-eslint/no-explicit-any": 0,
- },
- settings: { jsdoc: { mode: "typescript" } },
- overrides: [
- {
- files: ["*.subtest.ts", "*.test.ts"],
- rules: {
- "@typescript-eslint/no-unsafe-member-access": 0,
- "prefer-const": 0,
- "@typescript-eslint/no-unsafe-call": 0,
- "@typescript-eslint/no-unsafe-return": 0,
- "@typescript-eslint/no-unsafe-assignment": 0,
- "no-await-in-loop": 1, // sometimes it's easier to debug when requests run sequentially
- },
- },
- ],
-};
diff --git a/eslint.config.mjs b/eslint.config.mjs
new file mode 100644
index 0000000..dc6f880
--- /dev/null
+++ b/eslint.config.mjs
@@ -0,0 +1,56 @@
+import eslint from "@eslint/js";
+import { defineConfig } from "eslint/config";
+import tseslint from "typescript-eslint";
+import eslintConfigPrettier from "eslint-config-prettier";
+
+export default defineConfig(
+ eslint.configs.recommended,
+ tseslint.configs.recommended,
+ tseslint.configs.recommendedTypeChecked,
+ eslintConfigPrettier,
+ {
+ languageOptions: {
+ parserOptions: {
+ projectService: true,
+ tsconfigRootDir: import.meta.dirname,
+ },
+ },
+ },
+ {
+ rules: {
+ "@typescript-eslint/no-unused-vars": "warn",
+ "prefer-const": "warn",
+ "no-console": ["error", { allow: ["warn", "error", "info"] }],
+ "no-await-in-loop": "error",
+ "@typescript-eslint/require-await": "off",
+ "@typescript-eslint/prefer-promise-reject-errors": "off",
+ "@typescript-eslint/no-unused-vars": [
+ "error",
+ {
+ args: "after-used",
+ argsIgnorePattern: "^_",
+ caughtErrorsIgnorePattern: "^_",
+ destructuredArrayIgnorePattern: "^_",
+ varsIgnorePattern: "^_",
+ },
+ ],
+ },
+ },
+ defineConfig({
+ files: ["src/**/*.test.ts"],
+ rules: {
+ "no-empty-pattern": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ "@typescript-eslint/no-empty-object-type": "off",
+ "@typescript-eslint/no-explicit-any": "off",
+ "prefer-const": "off",
+ "@typescript-eslint/no-unsafe-assignment": "off",
+ "@typescript-eslint/no-unsafe-member-access": "off",
+ "@typescript-eslint/no-unsafe-call": "off",
+ "no-await-in-loop": "off",
+ "@typescript-eslint/no-misused-promises": "off",
+ "@typescript-eslint/no-unsafe-argument": "off",
+ "@typescript-eslint/no-unsafe-return": "off",
+ },
+ })
+);
diff --git a/package-lock.json b/package-lock.json
index ecbbce9..d996a73 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12873 +1,12906 @@
{
"name": "@sealcode/sealgen",
"version": "0.19.0",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "@sealcode/sealgen",
"version": "0.19.0",
"license": "ISC",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
- "prettier": "^2.7.1",
+ "prettier": "^3.6.2",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"bin": {
"sealgen": "lib/cli.js"
},
"devDependencies": {
"@playwright/test": "^1.30.0",
"@types/koa__router": "^12.0.4",
"@types/md5": "^2.3.5",
"@types/mocha": "^10.0.6",
"@types/node": "^20.8.4",
"@types/prettier": "^2.7.0",
"@types/prompts": "^2.0.14",
"@types/recursive-readdir": "^2.2.4",
"@types/wcag-contrast": "^3.0.3",
"@types/ws": "^8.5.10",
"@types/yargs": "^17.0.32",
- "@typescript-eslint/eslint-plugin": "^5.58.0",
- "@typescript-eslint/parser": "^5.58.0",
+ "@typescript-eslint/eslint-plugin": "^8.44.0",
+ "@typescript-eslint/parser": "^8.44.0",
"axios": "^1.6.7",
"chalk": "^5.3.0",
- "eslint": "^7.32.0",
- "eslint-config-prettier": "^8.3.0",
- "eslint-plugin-prettier": "^3.4.1",
+ "eslint": "^9.36.0",
+ "eslint-config-prettier": "^8.10.2",
+ "eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-with-tsc-error": "^0.0.7",
"get-port": "^5.1.1",
"koa-body": "^5.0.0",
"mocha": "^10.4.0",
"mri": "^1.2.0",
"nyc": "^15.1.0",
"playwright": "^1.29.2",
"source-map-support": "^0.5.21",
"ts-node": "^10.9.1",
"typescript": "5.9",
+ "typescript-eslint": "^8.44.0",
"wait-port": "^1.0.4"
},
"peerDependencies": {
"koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24",
- "sealious": "^0.21",
+ "sealious": "^0.21.20",
"stimulus": "^3.2.2"
}
},
"node_modules/@ampproject/remapping": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
"integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
"dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.5",
"@jridgewell/trace-mapping": "^0.3.24"
},
"engines": {
"node": ">=6.0.0"
}
},
- "node_modules/@babel/code-frame": {
- "version": "7.12.11",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.12.11.tgz",
- "integrity": "sha512-Zt1yodBx1UcyiePMSkWnU4hPqhwq7hGi2nFL1LeA3EUl+q2LQx16MISgJ0+z7dnmgvP9QtIleuETGOiOH1RcIw==",
- "dev": true,
- "dependencies": {
- "@babel/highlight": "^7.10.4"
- }
- },
"node_modules/@babel/compat-data": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.28.0.tgz",
"integrity": "sha512-60X7qkglvrap8mn1lh2ebxXdZYtUcpd7gsmy9kLaBJ4i/WdY8PqTSdxyA8qraikqKQK5C1KRBKXqznrVapyNaw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.0.tgz",
"integrity": "sha512-UlLAnTPrFdNGoFtbSXwcGFQBtQZJCNjaN6hQNP3UPvuNXT1i82N26KL3dZeIpNalWywr9IuQuncaAfUaS1g6sQ==",
"dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.0",
"@babel/helper-compilation-targets": "^7.27.2",
"@babel/helper-module-transforms": "^7.27.3",
"@babel/helpers": "^7.27.6",
"@babel/parser": "^7.28.0",
"@babel/template": "^7.27.2",
"@babel/traverse": "^7.28.0",
"@babel/types": "^7.28.0",
"convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
"json5": "^2.2.3",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/babel"
}
},
"node_modules/@babel/core/node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core/node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
"integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
"dev": true
},
"node_modules/@babel/core/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/generator": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.0.tgz",
"integrity": "sha512-lJjzvrbEeWrhB4P3QBsH7tey117PjLZnDbLiQEKjQ/fNJTjuq4HSqgFA+UNSwZT8D7dxxbnuSBMsa1lrWzKlQg==",
"dev": true,
"dependencies": {
"@babel/parser": "^7.28.0",
"@babel/types": "^7.28.0",
"@jridgewell/gen-mapping": "^0.3.12",
"@jridgewell/trace-mapping": "^0.3.28",
"jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz",
"integrity": "sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ==",
"dev": true,
"dependencies": {
"@babel/compat-data": "^7.27.2",
"@babel/helper-validator-option": "^7.27.1",
"browserslist": "^4.24.0",
"lru-cache": "^5.1.1",
"semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
"dev": true,
"dependencies": {
"yallist": "^3.0.2"
}
},
"node_modules/@babel/helper-compilation-targets/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/@babel/helper-globals": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"dev": true,
"dependencies": {
"@babel/traverse": "^7.27.1",
"@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
"version": "7.27.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.27.3.tgz",
"integrity": "sha512-dSOvYwvyLsWBeIRyOeHXp5vPj5l1I011r52FM1+r1jCERv+aFXYk4whgQccYEGYxK2H3ZAIA8nuPkQ0HaUo3qg==",
"dev": true,
"dependencies": {
"@babel/helper-module-imports": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1",
"@babel/traverse": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-string-parser": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-identifier": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
"integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.2.tgz",
"integrity": "sha512-/V9771t+EgXz62aCcyofnQhGM8DQACbRhvzKFsXKC9QM+5MadF8ZmIm0crDMaz3+o0h0zXfJnd4EhbYbxsrcFw==",
"dev": true,
"dependencies": {
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.2"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/highlight": {
- "version": "7.25.9",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.25.9.tgz",
- "integrity": "sha512-llL88JShoCsth8fF8R4SJnIn+WLvR6ccFxu1H3FlMhDontdcmZWf2HgIZ7AIqV3Xcck1idlohrN4EUBQz6klbw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-validator-identifier": "^7.25.9",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/@babel/highlight/node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
- "dev": true,
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/@babel/parser": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.0.tgz",
"integrity": "sha512-jVZGvOxOuNSsuQuLRTh13nU0AogFlw32w/MT+LV6D3sP5WdbW61E77RnkbaO2dUvmPAYrBDJXGn5gGS6tH4j8g==",
"dev": true,
"dependencies": {
"@babel/types": "^7.28.0"
},
"bin": {
"parser": "bin/babel-parser.js"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@babel/runtime": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.2.tgz",
"integrity": "sha512-KHp2IflsnGywDjBWDkR9iEqiWSpc8GIi0lgTT3mOElT0PP1tG26P4tmFI2YvAdzgq9RGyoHZQEIEdZy6Ec5xCA==",
"peer": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
"version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/parser": "^7.27.2",
"@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template/node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
"version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.0.tgz",
"integrity": "sha512-mGe7UK5wWyh0bKRfupsUchrQGqvDbZDbKJw+kcRGSmdHVYrv+ltd0pnpDTVpiTqnaBru9iEvA8pz8W46v0Amwg==",
"dev": true,
"dependencies": {
"@babel/code-frame": "^7.27.1",
"@babel/generator": "^7.28.0",
"@babel/helper-globals": "^7.28.0",
"@babel/parser": "^7.28.0",
"@babel/template": "^7.27.2",
"@babel/types": "^7.28.0",
"debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse/node_modules/@babel/code-frame": {
"version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"dependencies": {
"@babel/helper-validator-identifier": "^7.27.1",
"js-tokens": "^4.0.0",
"picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
"version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"dev": true,
"dependencies": {
"@babel/helper-string-parser": "^7.27.1",
"@babel/helper-validator-identifier": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@cspotcode/source-map-support": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
"integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
"dev": true,
"dependencies": {
"@jridgewell/trace-mapping": "0.3.9"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
"version": "0.3.9",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
"integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.0.3",
"@jridgewell/sourcemap-codec": "^1.4.10"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz",
"integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==",
"cpu": [
"ppc64"
],
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz",
"integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-arm64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz",
"integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/android-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz",
"integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"android"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-arm64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz",
"integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/darwin-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz",
"integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-arm64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz",
"integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/freebsd-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz",
"integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz",
"integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==",
"cpu": [
"arm"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-arm64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz",
"integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ia32": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz",
"integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-loong64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz",
"integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==",
"cpu": [
"loong64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-mips64el": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz",
"integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==",
"cpu": [
"mips64el"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-ppc64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz",
"integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==",
"cpu": [
"ppc64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-riscv64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz",
"integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==",
"cpu": [
"riscv64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-s390x": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz",
"integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==",
"cpu": [
"s390x"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/linux-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz",
"integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/netbsd-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz",
"integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/openbsd-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz",
"integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/sunos-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz",
"integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-arm64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz",
"integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==",
"cpu": [
"arm64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-ia32": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz",
"integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==",
"cpu": [
"ia32"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@esbuild/win32-x64": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz",
"integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==",
"cpu": [
"x64"
],
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=12"
}
},
"node_modules/@eslint-community/eslint-utils": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.7.0.tgz",
- "integrity": "sha512-dyybb3AcajC7uha6CvhdVRJqaKyn7w2YKqKyAN37NKYgZT36w+iRb0Dymmc5qEJ549c/S31cMMSFd75bteCpCw==",
+ "version": "4.9.0",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.0.tgz",
+ "integrity": "sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"eslint-visitor-keys": "^3.4.3"
},
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
},
"peerDependencies": {
"eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
"node_modules/@eslint-community/regexpp": {
"version": "4.12.1",
"resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
"integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
"dev": true,
"engines": {
"node": "^12.0.0 || ^14.0.0 || >=16.0.0"
}
},
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.0.tgz",
+ "integrity": "sha512-ENIdc4iLu0d93HeYirvKmrzshzofPw6VkZRKQGe9Nv46ZnWUzcF1xV01dcvEg/1wXUR61OmmlSfyeyO7EvjLxQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.6",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.3.1.tgz",
+ "integrity": "sha512-xR93k9WhrDYpXHORXpxVL5oHj3Era7wo6k/Wd8/IsQNnZUTzkGS29lyn3nAT05v6ltUuTFVCCYDEGfy2Or/sPA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.15.2.tgz",
+ "integrity": "sha512-78Md3/Rrxh83gCxoUc0EiciuOHsIITzLy53m3d9UyiW8y9Dj2D29FeETqyKA+BRK76tnTp6RXWb3pCay8Oyomg==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
"node_modules/@eslint/eslintrc": {
- "version": "0.4.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-0.4.3.tgz",
- "integrity": "sha512-J6KFFz5QCYUJq3pf0mjEcCJVERbzv71PUIDczuh9JkwGEzced6CO5ADLHB1rbf/+oPBtoPfMYNOpGDzCANlbXw==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ajv": "^6.12.4",
- "debug": "^4.1.1",
- "espree": "^7.3.0",
- "globals": "^13.9.0",
- "ignore": "^4.0.6",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
"import-fresh": "^3.2.1",
- "js-yaml": "^3.13.1",
- "minimatch": "^3.0.4",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
"strip-json-comments": "^3.1.1"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/@eslint/eslintrc/node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/@eslint/eslintrc/node_modules/ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "node_modules/@eslint/js": {
+ "version": "9.36.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.36.0.tgz",
+ "integrity": "sha512-uhCbYtYynH30iZErszX78U+nR3pJU3RHGQ57NXy5QupD4SBVwDeU8TNBy+MjMngc1UyIW9noKqsRqfjQTBU2dw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 4"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.6.tgz",
+ "integrity": "sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.3.5.tgz",
+ "integrity": "sha512-Z5kJ+wU3oA7MMIqVR9tyZRtjYPr4OC004Q4Rw7pgOKUOKkJfZ3O24nz3WYfGRpMDNmcOi3TwQOmgm7B7Tpii0w==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.15.2",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
"node_modules/@hotwired/stimulus": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/@hotwired/stimulus/-/stimulus-3.2.2.tgz",
"integrity": "sha512-eGeIqNOQpXoPAIP7tC1+1Yc1yl1xnwYqg+3mzqxyrbE5pg5YFBZcA6YoTiByJB6DKAEsiWtl6tjTJS4IYtbB7A==",
"license": "MIT",
"peer": true
},
"node_modules/@hotwired/stimulus-webpack-helpers": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/@hotwired/stimulus-webpack-helpers/-/stimulus-webpack-helpers-1.0.1.tgz",
"integrity": "sha512-wa/zupVG0eWxRYJjC1IiPBdt3Lruv0RqGN+/DTMmUWUyMAEB27KXmVY6a8YpUVTM7QwVuaLNGW4EqDgrS2upXQ==",
"license": "MIT",
"peer": true,
"peerDependencies": {
"@hotwired/stimulus": ">= 3.0"
}
},
- "node_modules/@humanwhocodes/config-array": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.5.0.tgz",
- "integrity": "sha512-FagtKFz74XrTl7y6HCzQpwDfXP0yhxe9lHLD1UZxjvZIcbyRz8zTFF/yYNfSfzU414eDwZ1SrO0Qvtyf+wFMQg==",
- "deprecated": "Use @eslint/config-array instead",
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.7",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.7.tgz",
+ "integrity": "sha512-/zUx+yOsIrG4Y43Eh2peDeKCxlRt/gET6aHfaKpuq267qXdYDFViVHfMaLyygZOnl0kGWxFIgsBy8QFuTLUXEQ==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@humanwhocodes/object-schema": "^1.2.0",
- "debug": "^4.1.1",
- "minimatch": "^3.0.4"
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.4.0"
},
"engines": {
- "node": ">=10.10.0"
+ "node": ">=18.18.0"
}
},
- "node_modules/@humanwhocodes/object-schema": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz",
- "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
- "deprecated": "Use @eslint/object-schema instead",
- "dev": true
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
},
"node_modules/@isaacs/cliui": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
"integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
"peer": true,
"dependencies": {
"string-width": "^5.1.2",
"string-width-cjs": "npm:string-width@^4.2.0",
"strip-ansi": "^7.0.1",
"strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
"wrap-ansi": "^8.1.0",
"wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-regex": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
"integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
"peer": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-regex?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/ansi-styles": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
"integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
"peer": true,
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/emoji-regex": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
"peer": true
},
"node_modules/@isaacs/cliui/node_modules/string-width": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
"integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
"peer": true,
"dependencies": {
"eastasianwidth": "^0.2.0",
"emoji-regex": "^9.2.2",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@isaacs/cliui/node_modules/strip-ansi": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
"peer": true,
"dependencies": {
"ansi-regex": "^6.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
"node_modules/@isaacs/cliui/node_modules/wrap-ansi": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
"integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
"peer": true,
"dependencies": {
"ansi-styles": "^6.1.0",
"string-width": "^5.0.1",
"strip-ansi": "^7.0.1"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
"integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
"dev": true,
"dependencies": {
"camelcase": "^5.3.1",
"find-up": "^4.1.0",
"get-package-type": "^0.1.0",
"js-yaml": "^3.13.1",
"resolve-from": "^5.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"dependencies": {
"p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/@istanbuljs/schema": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
"integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.12",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.12.tgz",
"integrity": "sha512-OuLGC46TjB5BbN1dH8JULVVZY4WTdkF7tV9Ys6wLL1rubZnCMstOhNHueU5bLCrnRuDhKPDM4g6sw4Bel5Gzqg==",
"dev": true,
"dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0",
"@jridgewell/trace-mapping": "^0.3.24"
}
},
"node_modules/@jridgewell/resolve-uri": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.5.4",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.4.tgz",
"integrity": "sha512-VT2+G1VQs/9oz078bLrYbecdZKs912zQlkelYpuf+SXF+QvZDYJlbx/LSx+meSAwdDFnF8FVXW92AVjjkVmgFw==",
"dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.29",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.29.tgz",
"integrity": "sha512-uw6guiW/gcAGPDhLmd77/6lW8QLeiV5RUTsAX46Db6oLhGaVj4lhnPwb184s1bkc8kdVg/+h988dro8GRDpmYQ==",
"dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "^3.1.0",
"@jridgewell/sourcemap-codec": "^1.4.14"
}
},
"node_modules/@koa/router": {
"version": "12.0.2",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-12.0.2.tgz",
"integrity": "sha512-sYcHglGKTxGF+hQ6x67xDfkE9o+NhVlRHBqq6gLywaMc6CojK/5vFZByphdonKinYlMLkEkacm+HEse9HzwgTA==",
"dependencies": {
"debug": "^4.3.4",
"http-errors": "^2.0.0",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.3.0"
},
"engines": {
"node": ">= 12"
}
},
"node_modules/@mongodb-js/saslprep": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.3.0.tgz",
"integrity": "sha512-zlayKCsIjYb7/IdfqxorK5+xUMyi4vOKcFy10wKJYc63NSdKI8mNME+uJqfatkPmOSMMUiojrL58IePKBm3gvQ==",
"peer": true,
"dependencies": {
"sparse-bitfield": "^3.0.3"
}
},
"node_modules/@noble/hashes": {
"version": "1.8.0",
"resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.8.0.tgz",
"integrity": "sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A==",
"dev": true,
"engines": {
"node": "^14.21.3 || >=16"
},
"funding": {
"url": "https://paulmillr.com/funding/"
}
},
"node_modules/@nodelib/fs.scandir": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
"integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.stat": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/@nodelib/fs.walk": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
"dev": true,
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/@one-ini/wasm": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz",
"integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==",
"peer": true
},
"node_modules/@paralleldrive/cuid2": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz",
"integrity": "sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA==",
"dev": true,
"dependencies": {
"@noble/hashes": "^1.1.5"
}
},
+ "node_modules/@pkgr/core": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
+ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
"node_modules/@playwright/test": {
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.54.2.tgz",
"integrity": "sha512-A+znathYxPf+72riFd1r1ovOLqsIIB0jKIoPjyK2kqEIe30/6jF6BC7QNluHuwUmsD2tv1XZVugN8GqfTMOxsA==",
"dev": true,
"dependencies": {
"playwright": "1.54.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/@sealcode/file-manager": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@sealcode/file-manager/-/file-manager-1.0.2.tgz",
"integrity": "sha512-BOMgC90QffE9cVFKkLVTjDbUJ5WB9YqcmS4fwqFxgnnC3YlH9xb9rff3iGXSkKOHm0kCeSjq0Ohasxtq/z72WQ==",
"dependencies": {
"@types/mime-types": "^2.1.4",
"@types/uuid": "^9.0.8",
"locreq": "^3.0.0",
"mime-types": "^2.1.35",
"uuid": "^9.0.1"
}
},
"node_modules/@sealcode/ts-predicates": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.4.3.tgz",
"integrity": "sha512-UNSEacu7Ye8q0N8AJCJy37oJvv3w2OXKGkUnP7xO5lOY9DQviDPRDQhVaZdJ3/xMzXLm4UE3389ihctrPaov/A=="
},
"node_modules/@tsconfig/node10": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
"integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
"dev": true
},
"node_modules/@tsconfig/node12": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
"integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
"dev": true
},
"node_modules/@tsconfig/node14": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
"integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
"dev": true
},
"node_modules/@tsconfig/node16": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
"integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
"dev": true
},
"node_modules/@types/accepts": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz",
"integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/body-parser": {
"version": "1.19.6",
"resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
"integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
"node_modules/@types/boom": {
"version": "7.3.5",
"resolved": "https://registry.npmjs.org/@types/boom/-/boom-7.3.5.tgz",
"integrity": "sha512-jBS0kU2s9W2sx+ILEyO4kxqIYLllqcUXTaVrBctvGptZ+4X3TWkkgY9+AmxdMPKrgiDDdLcfsaQCTu7bniLvgw==",
"peer": true
},
"node_modules/@types/bson": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/@types/bson/-/bson-4.2.4.tgz",
"integrity": "sha512-SG23E3JDH6y8qF20a4G9txLuUl+TCV16gxsKyntmGiJez2V9VBJr1Y8WxTBBD6OgBVcvspQ7sxgdNMkXFVcaEA==",
"deprecated": "This is a stub types definition. bson provides its own type definitions, so you do not need this installed.",
"peer": true,
"dependencies": {
"bson": "*"
}
},
"node_modules/@types/clone": {
"version": "0.1.30",
"resolved": "https://registry.npmjs.org/@types/clone/-/clone-0.1.30.tgz",
"integrity": "sha512-vcxBr+ybljeSiasmdke1cQ9ICxoEwaBgM1OQ/P5h4MPj/kRyLcDl5L8PrftlbyV1kBbJIs3M3x1A1+rcWd4mEA==",
"peer": true
},
"node_modules/@types/color": {
"version": "3.0.6",
"resolved": "https://registry.npmjs.org/@types/color/-/color-3.0.6.tgz",
"integrity": "sha512-NMiNcZFRUAiUUCCf7zkAelY8eV3aKqfbzyFQlXpPIEeoNDbsEHGpb854V3gzTsGKYj830I5zPuOwU/TP5/cW6A==",
"peer": true,
"dependencies": {
"@types/color-convert": "*"
}
},
"node_modules/@types/color-convert": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/@types/color-convert/-/color-convert-2.0.4.tgz",
"integrity": "sha512-Ub1MmDdyZ7mX//g25uBAoH/mWGd9swVbt8BseymnaE18SU4po/PjmCrHxqIIRjBo3hV/vh1KGr0eMxUhp+t+dQ==",
"peer": true,
"dependencies": {
"@types/color-name": "^1.1.0"
}
},
"node_modules/@types/color-hash": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/@types/color-hash/-/color-hash-1.0.5.tgz",
"integrity": "sha512-miV7Z8zvOnRn0ZjbP/D/qb1VWHrWkKOnfC764SJvnCeIziW4pZy3tPK/542seSgccGAXlPQd/seuNyVAS/p5Ug==",
"peer": true
},
"node_modules/@types/color-name": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/@types/color-name/-/color-name-1.1.5.tgz",
"integrity": "sha512-j2K5UJqGTxeesj6oQuGpMgifpT5k9HprgQd8D1Y0lOFqKHl3PJu5GMeS4Y5EgjS55AE6OQxf8mPED9uaGbf4Cg==",
"peer": true
},
"node_modules/@types/connect": {
"version": "3.4.38",
"resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
"integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/content-disposition": {
"version": "0.5.9",
"resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.9.tgz",
"integrity": "sha512-8uYXI3Gw35MhiVYhG3s295oihrxRyytcRHjSjqnqZVDDy/xcGBRny7+Xj1Wgfhv5QzRtN2hB2dVRBUX9XW3UcQ=="
},
"node_modules/@types/cookies": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.1.tgz",
"integrity": "sha512-E/DPgzifH4sM1UMadJMWd6mO2jOd4g1Ejwzx8/uRCDpJis1IrlyQEcGAYEomtAqRYmD5ORbNXMeI9U0RiVGZbg==",
"dependencies": {
"@types/connect": "*",
"@types/express": "*",
"@types/keygrip": "*",
"@types/node": "*"
}
},
"node_modules/@types/escape-html": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/@types/escape-html/-/escape-html-1.0.4.tgz",
"integrity": "sha512-qZ72SFTgUAZ5a7Tj6kf2SHLetiH5S6f8G5frB2SPQ3EyF02kxdyBFf4Tz4banE3xCgGnKgWLt//a6VuYHKYJTg==",
"peer": true
},
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/express": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.3.tgz",
"integrity": "sha512-wGA0NX93b19/dZC1J18tKWVIYWyyF2ZjT9vin/NRu0qzzvfVzWjs04iq2rQ3H65vCTQYlRqs3YHfY7zjdV+9Kw==",
"dependencies": {
"@types/body-parser": "*",
"@types/express-serve-static-core": "^5.0.0",
"@types/serve-static": "*"
}
},
"node_modules/@types/express-serve-static-core": {
"version": "5.0.7",
"resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.7.tgz",
"integrity": "sha512-R+33OsgWw7rOhD1emjU7dzCDHucJrgJXMA5PYCzJxVil0dsyx5iBEPHqpPfiKNJQb7lZ1vxwoLR4Z87bBUpeGQ==",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
"@types/range-parser": "*",
"@types/send": "*"
}
},
"node_modules/@types/formidable": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-2.0.6.tgz",
"integrity": "sha512-L4HcrA05IgQyNYJj6kItuIkXrInJvsXTPC5B1i64FggWKKqSL+4hgt7asiSNva75AoLQjq29oPxFfU4GAQ6Z2w==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/http-assert": {
"version": "1.5.6",
"resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.6.tgz",
"integrity": "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw=="
},
"node_modules/@types/http-errors": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
"integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg=="
},
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
"integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
"dev": true
},
"node_modules/@types/keygrip": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz",
"integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ=="
},
"node_modules/@types/koa": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/@types/koa/-/koa-3.0.0.tgz",
"integrity": "sha512-MOcVYdVYmkSutVHZZPh8j3+dAjLyR5Tl59CN0eKgpkE1h/LBSmPAsQQuWs+bKu7WtGNn+hKfJH9Gzml+PulmDg==",
"dependencies": {
"@types/accepts": "*",
"@types/content-disposition": "*",
"@types/cookies": "*",
"@types/http-assert": "*",
"@types/http-errors": "^2",
"@types/keygrip": "*",
"@types/koa-compose": "*",
"@types/node": "*"
}
},
"node_modules/@types/koa__router": {
"version": "12.0.4",
"resolved": "https://registry.npmjs.org/@types/koa__router/-/koa__router-12.0.4.tgz",
"integrity": "sha512-Y7YBbSmfXZpa/m5UGGzb7XadJIRBRnwNY9cdAojZGp65Cpe5MAP3mOZE7e3bImt8dfKS4UFcR16SLH8L/z7PBw==",
"dev": true,
"dependencies": {
"@types/koa": "*"
}
},
"node_modules/@types/koa-compose": {
"version": "3.2.8",
"resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz",
"integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==",
"dependencies": {
"@types/koa": "*"
}
},
"node_modules/@types/koa-mount": {
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/@types/koa-mount/-/koa-mount-4.0.5.tgz",
"integrity": "sha512-pV1njJ7r94iqAFzT9D5sGSYKUHFGudCLAnmr4WFli7V5tJf5MAgRQK9leTPJ4gjvgr+hnTf86fZsKoFN358c7w==",
"peer": true,
"dependencies": {
"@types/koa": "*"
}
},
"node_modules/@types/koa-qs": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/@types/koa-qs/-/koa-qs-2.0.3.tgz",
"integrity": "sha512-HS4oAQaUKUZJPHggg3DeHiuUwSSotieNRuS2ZlUZO14216Fhf7QDNx8mjR/ZwXaSBr/R46KFtE0OAvsF3yP44A==",
"peer": true,
"dependencies": {
"@types/koa": "*"
}
},
"node_modules/@types/koa-send": {
"version": "4.1.6",
"resolved": "https://registry.npmjs.org/@types/koa-send/-/koa-send-4.1.6.tgz",
"integrity": "sha512-vgnNGoOJkx7FrF0Jl6rbK1f8bBecqAchKpXtKuXzqIEdXTDO6dsSTjr+eZ5m7ltSjH4K/E7auNJEQCAd0McUPA==",
"peer": true,
"dependencies": {
"@types/koa": "*"
}
},
"node_modules/@types/koa-static": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/@types/koa-static/-/koa-static-4.0.4.tgz",
"integrity": "sha512-j1AUzzl7eJYEk9g01hNTlhmipFh8RFbOQmaMNLvLcNNAkPw0bdTs3XTa3V045XFlrWN0QYnblbDJv2RzawTn6A==",
"peer": true,
"dependencies": {
"@types/koa": "*",
"@types/koa-send": "*"
}
},
"node_modules/@types/luxon": {
"version": "3.3.8",
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.3.8.tgz",
"integrity": "sha512-jYvz8UMLDgy3a5SkGJne8H7VA7zPV2Lwohjx0V8V31+SqAjNmurWMkk9cQhfvlcnXWudBpK9xPM1n4rljOcHYQ==",
"peer": true
},
"node_modules/@types/md5": {
"version": "2.3.5",
"resolved": "https://registry.npmjs.org/@types/md5/-/md5-2.3.5.tgz",
"integrity": "sha512-/i42wjYNgE6wf0j2bcTX6kuowmdL/6PE4IVitMpm2eYKBUuYCprdcWVK+xEF0gcV6ufMCRhtxmReGfc6hIK7Jw==",
"dev": true
},
"node_modules/@types/mime": {
"version": "1.3.5",
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
"integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w=="
},
"node_modules/@types/mime-types": {
"version": "2.1.4",
"resolved": "https://registry.npmjs.org/@types/mime-types/-/mime-types-2.1.4.tgz",
"integrity": "sha512-lfU4b34HOri+kAY5UheuFMWPDOI+OPceBSHZKp69gEyTL/mmJ4cnU6Y/rlme3UL3GyOn6Y42hyIEw0/q8sWx5w=="
},
"node_modules/@types/mjml": {
"version": "4.7.4",
"resolved": "https://registry.npmjs.org/@types/mjml/-/mjml-4.7.4.tgz",
"integrity": "sha512-vyi1vzWgMzFMwZY7GSZYX0GU0dmtC8vLHwpgk+NWmwbwRSrlieVyJ9sn5elodwUfklJM7yGl0zQeet1brKTWaQ==",
"peer": true,
"dependencies": {
"@types/mjml-core": "*"
}
},
"node_modules/@types/mjml-core": {
"version": "4.15.2",
"resolved": "https://registry.npmjs.org/@types/mjml-core/-/mjml-core-4.15.2.tgz",
"integrity": "sha512-Q7SxFXgoX979HP57DEVsRI50TV8x1V4lfCA4Up9AvfINDM5oD/X9ARgfoyX1qS987JCnDLv85JjkqAjt3hZSiQ==",
"peer": true
},
"node_modules/@types/mocha": {
"version": "10.0.10",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-10.0.10.tgz",
"integrity": "sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q==",
"dev": true
},
"node_modules/@types/mongodb": {
"version": "3.6.20",
"resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.6.20.tgz",
"integrity": "sha512-WcdpPJCakFzcWWD9juKoZbRtQxKIMYF/JIAM4JrNHrMcnJL6/a2NWjXxW7fo9hxboxxkg+icff8d7+WIEvKgYQ==",
"peer": true,
"dependencies": {
"@types/bson": "*",
"@types/node": "*"
}
},
"node_modules/@types/node": {
"version": "20.19.10",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.19.10.tgz",
"integrity": "sha512-iAFpG6DokED3roLSP0K+ybeDdIX6Bc0Vd3mLW5uDqThPWtNos3E+EqOM11mPQHKzfWHqEBuLjIlsBQQ8CsISmQ==",
"dependencies": {
"undici-types": "~6.21.0"
}
},
"node_modules/@types/nodemailer": {
"version": "6.4.17",
"resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-6.4.17.tgz",
"integrity": "sha512-I9CCaIp6DTldEg7vyUTZi8+9Vo0hi1/T8gv3C89yk1rSAAzoKQ8H8ki/jBYJSFoH/BisgLP8tkZMlQ91CIquww==",
"peer": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/object-hash": {
"version": "1.3.4",
"resolved": "https://registry.npmjs.org/@types/object-hash/-/object-hash-1.3.4.tgz",
"integrity": "sha512-xFdpkAkikBgqBdG9vIlsqffDV8GpvnPEzs0IUtr1v3BEB97ijsFQ4RXVbUZwjFThhB4MDSTUfvmxUD5PGx0wXA==",
"peer": true
},
"node_modules/@types/prettier": {
"version": "2.7.3",
"resolved": "https://registry.npmjs.org/@types/prettier/-/prettier-2.7.3.tgz",
"integrity": "sha512-+68kP9yzs4LMp7VNh8gdzMSPZFL44MLGqiHWvttYJe+6qnuVr4Ek9wSBQoveqY/r+LwjCcU29kNVkidwim+kYA==",
"dev": true
},
"node_modules/@types/prompts": {
"version": "2.4.9",
"resolved": "https://registry.npmjs.org/@types/prompts/-/prompts-2.4.9.tgz",
"integrity": "sha512-qTxFi6Buiu8+50/+3DGIWLHM6QuWsEKugJnnP6iv2Mc4ncxE4A/OJkjuVOA+5X0X1S/nq5VJRa8Lu+nwcvbrKA==",
"dev": true,
"dependencies": {
"@types/node": "*",
"kleur": "^3.0.3"
}
},
"node_modules/@types/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ=="
},
"node_modules/@types/range-parser": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
"integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ=="
},
"node_modules/@types/recursive-readdir": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/@types/recursive-readdir/-/recursive-readdir-2.2.4.tgz",
"integrity": "sha512-84REEGT3lcgopvpkmGApzmU5UEG0valme5rQS/KGiguTkJ70/Au8UYZTyrzoZnY9svuX9351+1uvrRPzWDD/uw==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/sanitize-html": {
"version": "2.16.0",
"resolved": "https://registry.npmjs.org/@types/sanitize-html/-/sanitize-html-2.16.0.tgz",
"integrity": "sha512-l6rX1MUXje5ztPT0cAFtUayXF06DqPhRyfVXareEN5gGCFaP/iwsxIyKODr9XDhfxPpN6vXUFNfo5kZMXCxBtw==",
"peer": true,
"dependencies": {
"htmlparser2": "^8.0.0"
}
},
- "node_modules/@types/semver": {
- "version": "7.7.0",
- "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.7.0.tgz",
- "integrity": "sha512-k107IF4+Xr7UHjwDc7Cfd6PRQfbdkiRabXGRjo07b4WyPahFBZCZ1sE+BNxYIJPPg73UkfOsVOLwqVc/6ETrIA==",
- "dev": true
- },
"node_modules/@types/send": {
"version": "0.17.5",
"resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.5.tgz",
"integrity": "sha512-z6F2D3cOStZvuk2SaP6YrwkNO65iTZcwA2ZkSABegdkAh/lf+Aa/YQndZVfmEXT5vgAp6zv06VQ3ejSVjAny4w==",
"dependencies": {
"@types/mime": "^1",
"@types/node": "*"
}
},
"node_modules/@types/serve-static": {
"version": "1.15.8",
"resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.8.tgz",
"integrity": "sha512-roei0UY3LhpOJvjbIP6ZZFngyLKl5dskOtDhxY5THRSpO+ZI+nzJ+m5yUMzGrp89YRa7lvknKkMYjqQFGwA7Sg==",
"dependencies": {
"@types/http-errors": "*",
"@types/node": "*",
"@types/send": "*"
}
},
"node_modules/@types/uuid": {
"version": "9.0.8",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz",
"integrity": "sha512-jg+97EGIcY9AGHJJRaaPVgetKDsrTgbRjQ5Msgjh/DQKEFl0DtyRr/VCOyD1T2R1MNeWPK/u7JoGhlDZnKBAfA=="
},
"node_modules/@types/wcag-contrast": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/@types/wcag-contrast/-/wcag-contrast-3.0.3.tgz",
"integrity": "sha512-oprevfwJSLfpQK4KaWsRKJuNoebV76+xhmbXiWJGy+FkS34LpCgCMNIwRXWTb8xmmSxUE2ycFOYE7uyRVRm3LA==",
"dev": true
},
"node_modules/@types/webidl-conversions": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz",
"integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==",
"peer": true
},
"node_modules/@types/whatwg-url": {
"version": "11.0.5",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-11.0.5.tgz",
"integrity": "sha512-coYR071JRaHa+xoEvvYqvnIHaVqaYrLPbsufM9BF63HkwI5Lgmy2QR8Q5K/lYDYo5AK82wOvSOS0UsLTpTG7uQ==",
"peer": true,
"dependencies": {
"@types/webidl-conversions": "*"
}
},
"node_modules/@types/ws": {
"version": "8.18.1",
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
"integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
"dev": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/yargs": {
"version": "17.0.33",
"resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
"integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
"dev": true,
"dependencies": {
"@types/yargs-parser": "*"
}
},
"node_modules/@types/yargs-parser": {
"version": "21.0.3",
"resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
"integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
"dev": true
},
"node_modules/@typescript-eslint/eslint-plugin": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz",
- "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.44.0.tgz",
+ "integrity": "sha512-EGDAOGX+uwwekcS0iyxVDmRV9HX6FLSM5kzrAToLTsr9OWCIKG/y3lQheCq18yZ5Xh78rRKJiEpP0ZaCs4ryOQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@eslint-community/regexpp": "^4.4.0",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/type-utils": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
- "debug": "^4.3.4",
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.44.0",
+ "@typescript-eslint/type-utils": "8.44.0",
+ "@typescript-eslint/utils": "8.44.0",
+ "@typescript-eslint/visitor-keys": "8.44.0",
"graphemer": "^1.4.0",
- "ignore": "^5.2.0",
- "natural-compare-lite": "^1.4.0",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "@typescript-eslint/parser": "^5.0.0",
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "@typescript-eslint/parser": "^8.44.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
}
},
"node_modules/@typescript-eslint/experimental-utils": {
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/experimental-utils/-/experimental-utils-4.33.0.tgz",
"integrity": "sha512-zeQjOoES5JFjTnAhI5QY7ZviczMzDptls15GFsI6jyUOq0kOf9+WonkhtlIhh0RgHRnqj5gdNxW5j1EvAyYg6Q==",
"dev": true,
"dependencies": {
"@types/json-schema": "^7.0.7",
"@typescript-eslint/scope-manager": "4.33.0",
"@typescript-eslint/types": "4.33.0",
"@typescript-eslint/typescript-estree": "4.33.0",
"eslint-scope": "^5.1.1",
"eslint-utils": "^3.0.0"
},
"engines": {
"node": "^10.12.0 || >=12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
"eslint": "*"
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/scope-manager": {
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-4.33.0.tgz",
"integrity": "sha512-5IfJHpgTsTZuONKbODctL4kKuQje/bzBRkwHE8UOZ4f89Zeddg+EGZs8PD8NcN4LdM3ygHWYB3ukPAYjvl/qbQ==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "4.33.0",
"@typescript-eslint/visitor-keys": "4.33.0"
},
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/types": {
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-4.33.0.tgz",
"integrity": "sha512-zKp7CjQzLQImXEpLt2BUw1tvOMPfNoTAfb8l51evhYbOEEzdWyQNmHWWGPR6hwKJDAi+1VXSBmnhL9kyVTTOuQ==",
"dev": true,
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/typescript-estree": {
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-4.33.0.tgz",
"integrity": "sha512-rkWRY1MPFzjwnEVHsxGemDzqqddw2QbTJlICPD9p9I9LfsO8fdmfQPOX3uKfUaGRDFJbfrtm/sXhVXN4E+bzCA==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "4.33.0",
"@typescript-eslint/visitor-keys": "4.33.0",
"debug": "^4.3.1",
"globby": "^11.0.3",
"is-glob": "^4.0.1",
"semver": "^7.3.5",
"tsutils": "^3.21.0"
},
"engines": {
"node": "^10.12.0 || >=12.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependenciesMeta": {
"typescript": {
"optional": true
}
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/@typescript-eslint/visitor-keys": {
"version": "4.33.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-4.33.0.tgz",
"integrity": "sha512-uqi/2aSz9g2ftcHWf8uLPJA70rUv6yuMW5Bohw+bwcuzaxQIHaKFZCKGoGXIrc9vkTJ3+0txM73K0Hq3d5wgIg==",
"dev": true,
"dependencies": {
"@typescript-eslint/types": "4.33.0",
"eslint-visitor-keys": "^2.0.0"
},
"engines": {
"node": "^8.10.0 || ^10.13.0 || >=11.10.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-utils": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz",
"integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==",
"dev": true,
"dependencies": {
"eslint-visitor-keys": "^2.0.0"
},
"engines": {
"node": "^10.0.0 || ^12.0.0 || >= 14.0.0"
},
"funding": {
"url": "https://github.com/sponsors/mysticatea"
},
"peerDependencies": {
"eslint": ">=5"
}
},
"node_modules/@typescript-eslint/experimental-utils/node_modules/eslint-visitor-keys": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
"integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/@typescript-eslint/parser": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz",
- "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.44.0.tgz",
+ "integrity": "sha512-VGMpFQGUQWYT9LfnPcX8ouFojyrZ/2w3K5BucvxL/spdNehccKhB4jUyB1yBCXpr2XFm0jkECxgrpXBW2ipoAw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
+ "@typescript-eslint/scope-manager": "8.44.0",
+ "@typescript-eslint/types": "8.44.0",
+ "@typescript-eslint/typescript-estree": "8.44.0",
+ "@typescript-eslint/visitor-keys": "8.44.0",
"debug": "^4.3.4"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.44.0.tgz",
+ "integrity": "sha512-ZeaGNraRsq10GuEohKTo4295Z/SuGcSq2LzfGlqiuEvfArzo/VRrT0ZaJsVPuKZ55lVbNk8U6FcL+ZMH8CoyVA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.44.0",
+ "@typescript-eslint/types": "^8.44.0",
+ "debug": "^4.3.4"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/scope-manager": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz",
- "integrity": "sha512-VXuvVvZeQCQb5Zgf4HAxc04q5j+WrNAtNh9OwCsCgpKqESMTu3tF/jhZ3xG6T4NZwWl65Bg8KuS2uEvhSfLl0w==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.44.0.tgz",
+ "integrity": "sha512-87Jv3E+al8wpD+rIdVJm/ItDBe/Im09zXIjFoipOjr5gHUhJmTzfFLuTJ/nPTMc2Srsroy4IBXwcTCHyRR7KzA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0"
+ "@typescript-eslint/types": "8.44.0",
+ "@typescript-eslint/visitor-keys": "8.44.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.44.0.tgz",
+ "integrity": "sha512-x5Y0+AuEPqAInc6yd0n5DAcvtoQ/vyaGwuX5HE9n6qAefk1GaedqrLQF8kQGylLUb9pnZyLf+iEiL9fr8APDtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/type-utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.62.0.tgz",
- "integrity": "sha512-xsSQreu+VnfbqQpW5vnCJdq1Z3Q0U31qiWmRhr98ONQmcp/yhiPJFPq8MXiJVLiksmOKSjIldZzkebzHuCGzew==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.44.0.tgz",
+ "integrity": "sha512-9cwsoSxJ8Sak67Be/hD2RNt/fsqmWnNE1iHohG8lxqLSNY8xNfyY7wloo5zpW3Nu9hxVgURevqfcH6vvKCt6yg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/typescript-estree": "5.62.0",
- "@typescript-eslint/utils": "5.62.0",
+ "@typescript-eslint/types": "8.44.0",
+ "@typescript-eslint/typescript-estree": "8.44.0",
+ "@typescript-eslint/utils": "8.44.0",
"debug": "^4.3.4",
- "tsutils": "^3.21.0"
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "*"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/types": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz",
- "integrity": "sha512-87NVngcbVXUahrRTqIK27gD2t5Cu1yuCXxbLcFtCzZGlfyVWWh8mLHkoxzjsB6DDNnvdL+fW8MiwPEJyGJQDgQ==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.44.0.tgz",
+ "integrity": "sha512-ZSl2efn44VsYM0MfDQe68RKzBz75NPgLQXuGypmym6QVOWL5kegTZuZ02xRAT9T+onqvM6T8CdQk0OwYMB6ZvA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
"node_modules/@typescript-eslint/typescript-estree": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.62.0.tgz",
- "integrity": "sha512-CmcQ6uY7b9y694lKdRB8FEel7JbU/40iSAPomu++SjLMntB+2Leay2LO6i8VnJk58MtE9/nQSFIH6jpyRWyYzA==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.44.0.tgz",
+ "integrity": "sha512-lqNj6SgnGcQZwL4/SBJ3xdPEfcBuhCG8zdcwCPgYcmiPLgokiNDKlbPzCwEwu7m279J/lBYWtDYL+87OEfn8Jw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/visitor-keys": "5.62.0",
+ "@typescript-eslint/project-service": "8.44.0",
+ "@typescript-eslint/tsconfig-utils": "8.44.0",
+ "@typescript-eslint/types": "8.44.0",
+ "@typescript-eslint/visitor-keys": "8.44.0",
"debug": "^4.3.4",
- "globby": "^11.1.0",
+ "fast-glob": "^3.3.2",
"is-glob": "^4.0.3",
- "semver": "^7.3.7",
- "tsutils": "^3.21.0"
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^2.1.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/@typescript-eslint/utils": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz",
- "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.44.0.tgz",
+ "integrity": "sha512-nktOlVcg3ALo0mYlV+L7sWUD58KG4CMj1rb2HUVOO4aL3K/6wcD+NERqd0rrA5Vg06b42YhF6cFxeixsp9Riqg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@eslint-community/eslint-utils": "^4.2.0",
- "@types/json-schema": "^7.0.9",
- "@types/semver": "^7.3.12",
- "@typescript-eslint/scope-manager": "5.62.0",
- "@typescript-eslint/types": "5.62.0",
- "@typescript-eslint/typescript-estree": "5.62.0",
- "eslint-scope": "^5.1.1",
- "semver": "^7.3.7"
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.44.0",
+ "@typescript-eslint/types": "8.44.0",
+ "@typescript-eslint/typescript-estree": "8.44.0"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
},
"peerDependencies": {
- "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
}
},
"node_modules/@typescript-eslint/visitor-keys": {
- "version": "5.62.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz",
- "integrity": "sha512-07ny+LHRzQXepkGg6w0mFY41fVUNBrL2Roj/++7V1txKugfjm/Ci/qSND03r2RhlJhJYMcTn9AhhSSqQp0Ysyw==",
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.44.0.tgz",
+ "integrity": "sha512-zaz9u8EJ4GBmnehlrpoKvj/E3dNbuQ7q0ucyZImm3cLqJ8INTc970B1qEqDX/Rzq65r3TvVTN7kHWPBoyW7DWw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@typescript-eslint/types": "5.62.0",
- "eslint-visitor-keys": "^3.3.0"
+ "@typescript-eslint/types": "8.44.0",
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/typescript-eslint"
}
},
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/abbrev": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz",
"integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==",
"peer": true,
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/accepts": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"peer": true,
"dependencies": {
"mime-types": "~2.1.34",
"negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
"dev": true,
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
- },
- "node_modules/acorn-walk": {
- "version": "8.3.4",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
- "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "dev": true,
- "dependencies": {
- "acorn": "^8.11.0"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-walk/node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
"dev": true,
- "bin": {
- "acorn": "bin/acorn"
+ "dependencies": {
+ "acorn": "^8.11.0"
},
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/aggregate-error": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
"integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
"dev": true,
"dependencies": {
"clean-stack": "^2.0.0",
"indent-string": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/ajv": {
"version": "6.12.6",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
"integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/epoberezkin"
}
},
"node_modules/ansi-colors": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
"integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
"engines": {
"node": ">=6"
}
},
"node_modules/ansi-gray": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/ansi-gray/-/ansi-gray-0.1.1.tgz",
"integrity": "sha512-HrgGIZUl8h2EHuZaU9hTR/cU5nhKxpVE1V6kdGsQ8e4zirElJ5fvtfc8N7Q1oq1aatO275i8pUFUCpNWCAnVWw==",
"dependencies": {
"ansi-wrap": "0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ansi-regex": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/ansi-styles": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dependencies": {
"color-convert": "^2.0.1"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/chalk/ansi-styles?sponsor=1"
}
},
"node_modules/ansi-styles/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/ansi-styles/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
},
"node_modules/ansi-wrap": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/ansi-wrap/-/ansi-wrap-0.1.0.tgz",
"integrity": "sha512-ZyznvL8k/FZeQHr2T6LzcJ/+vBApDnMNZvfVFy3At0knswWd6rJ3/0Hhmpu8oqa6C92npmozs890sX9Dl6q+Qw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/anymatch": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/append-transform": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/append-transform/-/append-transform-2.0.0.tgz",
"integrity": "sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg==",
"dev": true,
"dependencies": {
"default-require-extensions": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/archive-type": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz",
"integrity": "sha512-6cAWDM0lUYTbb7F436FAjbBYnsn5E3L2AgTOLzrFfLt7FVM6uJwKUvllE8VjLKTmKCU8PqtWlUAezEYjg5iGqA==",
"dependencies": {
"file-type": "^3.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/archy": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz",
"integrity": "sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw==",
"dev": true
},
"node_modules/arg": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
"integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
"dev": true
},
"node_modules/argparse": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
"integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
"dev": true,
"dependencies": {
"sprintf-js": "~1.0.2"
}
},
"node_modules/arr-diff": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz",
"integrity": "sha512-dtXTVMkh6VkEEA7OhXnN1Ecb8aAGFdZ1LFxtOCoqj4qkyOJMt7+qs6Ahdy6p/NQCPYsRSXXivhSB/J5E9jmYKA==",
"dependencies": {
"arr-flatten": "^1.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/arr-flatten": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
"integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/array-differ": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/array-differ/-/array-differ-1.0.0.tgz",
"integrity": "sha512-LeZY+DZDRnvP7eMuQ6LHfCzUGxAAIViUBliK24P3hWXL6y4SortgR6Nim6xrkfSLlmH0+k+9NYNwVC2s53ZrYQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/array-union": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
"integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/array-uniq": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
"integrity": "sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/array-unique": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz",
"integrity": "sha512-G2n5bG5fSUCpnsXz4+8FUkYsGPkNfLn9YvS66U5qbTIXI2Ynnlo4Bi42bWv+omKUCqz+ejzfClwne0alJWJPhg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/asap": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/asap/-/asap-2.0.6.tgz",
"integrity": "sha512-BSHWgDSAiKs50o2Re8ppvp3seVHXSRM44cdSsT9FfNEUUZLOGWVCsiWaRPWM1Znn+mqZ1OfVZ3z3DWEzSp7hRA==",
"dev": true
},
"node_modules/asn1": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
"integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
"dependencies": {
"safer-buffer": "~2.1.0"
}
},
"node_modules/assert-plus": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
"integrity": "sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
"engines": {
"node": ">=0.8"
}
},
- "node_modules/astral-regex": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz",
- "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/asynckit": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
"integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
},
"node_modules/available-typed-arrays": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
"integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
"dependencies": {
"possible-typed-array-names": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/aws-sign2": {
"version": "0.7.0",
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
"integrity": "sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
"engines": {
"node": "*"
}
},
"node_modules/aws4": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz",
"integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw=="
},
"node_modules/axios": {
"version": "1.11.0",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.11.0.tgz",
"integrity": "sha512-1Lx3WLFQWm3ooKDYZD1eXmoGO9fxYQjrycfHFC8P0sCfQVXyROp0p9PFWBehewBOdCwHc+f/b8I0fMto5eSfwA==",
"dev": true,
"dependencies": {
"follow-redirects": "^1.15.6",
"form-data": "^4.0.4",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/b4a": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz",
"integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==",
"peer": true
},
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
"integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true
},
"node_modules/bcrypt-pbkdf": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
"integrity": "sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
"dependencies": {
"tweetnacl": "^0.14.3"
}
},
"node_modules/beeper": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/beeper/-/beeper-1.1.1.tgz",
"integrity": "sha512-3vqtKL1N45I5dV0RdssXZG7X6pCqQrWPNOlBPZPrd+QkE2HEhR57Z04m0KtpbsZH73j+a3F8UD1TQnn+ExTvIA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/better-queue": {
"version": "3.8.12",
"resolved": "https://registry.npmjs.org/better-queue/-/better-queue-3.8.12.tgz",
"integrity": "sha512-D9KZ+Us+2AyaCz693/9AyjTg0s8hEmkiM/MB3i09cs4MdK1KgTSGJluXRYmOulR69oLZVo2XDFtqsExDt8oiLA==",
"peer": true,
"dependencies": {
"better-queue-memory": "^1.0.1",
"node-eta": "^0.9.0",
"uuid": "^9.0.0"
}
},
"node_modules/better-queue-memory": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/better-queue-memory/-/better-queue-memory-1.0.4.tgz",
"integrity": "sha512-SWg5wFIShYffEmJpI6LgbL8/3Dqhku7xI1oEiy6FroP9DbcZlG0ZDjxvPdP9t7hTGW40IpIcC6zVoGT1oxjOuA==",
"peer": true
},
"node_modules/binary-extensions": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
"integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/bl": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/bl/-/bl-1.2.3.tgz",
"integrity": "sha512-pvcNpa0UU69UT341rO6AYy4FVAIkUHuZXRIWbq+zHnsVcRzDDjIAhGuuYoi0d//cwIwtt4pkpKycWEfjdV+vww==",
"dependencies": {
"readable-stream": "^2.3.5",
"safe-buffer": "^5.1.1"
}
},
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
"integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
"peer": true
},
"node_modules/boom": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/boom/-/boom-7.3.0.tgz",
"integrity": "sha512-Swpoyi2t5+GhOEGw8rEsKvTxFLIDiiKoUc2gsoV6Lyr43LHBIzch3k2MvYUs8RTROrIkVJ3Al0TkaOGjnb+B6A==",
"deprecated": "This module has moved and is now available at @hapi/boom. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
"peer": true,
"dependencies": {
"hoek": "6.x.x"
}
},
"node_modules/brace-expansion": {
"version": "1.1.12",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
}
},
"node_modules/braces": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
"integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
"dependencies": {
"fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/browser-stdout": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz",
"integrity": "sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw==",
"dev": true
},
"node_modules/browserslist": {
"version": "4.25.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.25.2.tgz",
"integrity": "sha512-0si2SJK3ooGzIawRu61ZdPCO1IncZwS8IzuX73sPZsXW6EQ/w/DAfPyKI8l1ETTCr2MnvqWitmlCUxgdul45jA==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"caniuse-lite": "^1.0.30001733",
"electron-to-chromium": "^1.5.199",
"node-releases": "^2.0.19",
"update-browserslist-db": "^1.1.3"
},
"bin": {
"browserslist": "cli.js"
},
"engines": {
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
"node_modules/bson": {
"version": "6.10.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-6.10.4.tgz",
"integrity": "sha512-WIsKqkSC0ABoBJuT1LEX+2HEvNmNKKgnTAyd0fL8qzK4SH2i9NXg+t08YtdZp/V9IZ33cxe3iV4yM0qg8lMQng==",
"peer": true,
"engines": {
"node": ">=16.20.1"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true,
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/buffer-alloc": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz",
"integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==",
"dependencies": {
"buffer-alloc-unsafe": "^1.1.0",
"buffer-fill": "^1.0.0"
}
},
"node_modules/buffer-alloc-unsafe": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz",
"integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg=="
},
"node_modules/buffer-crc32": {
"version": "0.2.13",
"resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz",
"integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==",
"engines": {
"node": "*"
}
},
"node_modules/buffer-fill": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz",
"integrity": "sha512-T7zexNBwiiaCOGDg9xNX9PBmjrubblRkENuptryuI64URkXDFum9il/JGL8Lm8wYfAXpredVXXZz7eMHilimiQ=="
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
"integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
},
"node_modules/buffer-to-vinyl": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz",
"integrity": "sha512-t6B4HXJ3YdJ/lXKhK3nlGW1aAvpQH2FMyHh25SmfdYkQAU3/R2MYo4VrY1DlQuZd8zLNOqWPxZFJILRuTkqaEQ==",
"dependencies": {
"file-type": "^3.1.0",
"readable-stream": "^2.0.2",
"uuid": "^2.0.1",
"vinyl": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/buffer-to-vinyl/node_modules/uuid": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz",
"integrity": "sha512-FULf7fayPdpASncVy4DLh3xydlXEJJpvIELjYjNeQWYUZ9pclcpvCZSr2gkmN2FrrGcI7G/cJsIEwk5/8vfXpg==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details."
},
"node_modules/bytes": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/cache-content-type": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/cache-content-type/-/cache-content-type-1.0.1.tgz",
"integrity": "sha512-IKufZ1o4Ut42YUrZSo8+qnMTrFuKkvyoLXUywKz9GJ5BrhOFGhLdkx9sG4KAnVvbY6kEcSFjLQul+DVmBm2bgA==",
"peer": true,
"dependencies": {
"mime-types": "^2.1.18",
"ylru": "^1.2.0"
},
"engines": {
"node": ">= 6.0.0"
}
},
"node_modules/caching-transform": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/caching-transform/-/caching-transform-4.0.0.tgz",
"integrity": "sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA==",
"dev": true,
"dependencies": {
"hasha": "^5.0.0",
"make-dir": "^3.0.0",
"package-hash": "^4.0.0",
"write-file-atomic": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/call-bind": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
"integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.0",
"es-define-property": "^1.0.0",
"get-intrinsic": "^1.2.4",
"set-function-length": "^1.2.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/call-bind-apply-helpers": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
"integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
"dependencies": {
"es-errors": "^1.3.0",
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/call-bound": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
"integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"get-intrinsic": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/camel-case": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
"integrity": "sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
"peer": true,
"dependencies": {
"no-case": "^2.2.0",
"upper-case": "^1.1.1"
}
},
"node_modules/camelcase": {
"version": "5.3.1",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/caniuse-lite": {
"version": "1.0.30001733",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001733.tgz",
"integrity": "sha512-e4QKw/O2Kavj2VQTKZWrwzkt3IxOmIlU6ajRb6LP64LHpBo1J67k2Hi4Vu/TgJWsNtynurfS0uK3MaUTCPfu5Q==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/caniuse-lite"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
]
},
"node_modules/capture-stack-trace": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.2.tgz",
"integrity": "sha512-X/WM2UQs6VMHUtjUDnZTRI+i1crWteJySFzr9UpGoQa4WQffXVTTXuekjl7TjZRlcF2XfjgITT0HxZ9RnxeT0w==",
"engines": {
"node": ">=0.10.0"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/caseless": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
"integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw=="
},
"node_modules/caw": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz",
"integrity": "sha512-GIAlMoessjWW8p0mkStU4kMvV35toVCAyOWhUajk7O0d7wJI8F9TDjfrkSoO26b0d1QsnDLmw5I3X+yd6OKorQ==",
"dependencies": {
"get-proxy": "^1.0.1",
"is-obj": "^1.0.0",
"object-assign": "^3.0.0",
"tunnel-agent": "^0.4.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/caw/node_modules/object-assign": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
"integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/chalk": {
"version": "5.5.0",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-5.5.0.tgz",
"integrity": "sha512-1tm8DTaJhPBG3bIkVeZt1iZM9GfSX2lzOeDVZH9R9ffRHpmHvxZ/QhgQH/aDTkswQVt+YHdXAdS/In/30OjCbg==",
"dev": true,
"engines": {
"node": "^12.17.0 || ^14.13 || >=16.0.0"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/charenc": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
"integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
"engines": {
"node": "*"
}
},
"node_modules/cheerio": {
"version": "1.0.0-rc.12",
"resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz",
"integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==",
"peer": true,
"dependencies": {
"cheerio-select": "^2.1.0",
"dom-serializer": "^2.0.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"htmlparser2": "^8.0.1",
"parse5": "^7.0.0",
"parse5-htmlparser2-tree-adapter": "^7.0.0"
},
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/cheeriojs/cheerio?sponsor=1"
}
},
"node_modules/cheerio-select": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
"integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
"peer": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-select": "^5.1.0",
"css-what": "^6.1.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/chokidar": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
"integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
"glob-parent": "~5.1.2",
"is-binary-path": "~2.1.0",
"is-glob": "~4.0.1",
"normalize-path": "~3.0.0",
"readdirp": "~3.6.0"
},
"engines": {
"node": ">= 8.10.0"
},
"funding": {
"url": "https://paulmillr.com/funding/"
},
"optionalDependencies": {
"fsevents": "~2.3.2"
}
},
"node_modules/chownr": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
"integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
"peer": true
},
"node_modules/classnames": {
"version": "2.5.1",
"resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
"integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
},
"node_modules/clean-css": {
"version": "4.2.4",
"resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
"integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
"peer": true,
"dependencies": {
"source-map": "~0.6.0"
},
"engines": {
"node": ">= 4.0"
}
},
"node_modules/clean-stack": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
"integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/cli-spinner": {
"version": "0.2.10",
"resolved": "https://registry.npmjs.org/cli-spinner/-/cli-spinner-0.2.10.tgz",
"integrity": "sha512-U0sSQ+JJvSLi1pAYuJykwiA8Dsr15uHEy85iCJ6A+0DjVxivr3d+N2Wjvodeg89uP5K6TswFkKBfAD7B3YSn/Q==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/cliui": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
"integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.1",
"wrap-ansi": "^7.0.0"
},
"engines": {
"node": ">=12"
}
},
"node_modules/clone": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/clone/-/clone-2.1.2.tgz",
"integrity": "sha512-3Pe/CF1Nn94hyhIYpjtiLhdCoEoz0DqQ+988E9gmeEdQZlojxnOb74wctFyuwWQHzqyf9X7C7MG8juUpqBJT8w==",
"peer": true,
"engines": {
"node": ">=0.8"
}
},
"node_modules/clone-stats": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/clone-stats/-/clone-stats-0.0.1.tgz",
"integrity": "sha512-dhUqc57gSMCo6TX85FLfe51eC/s+Im2MLkAgJwfaRRexR2tA4dd3eLEW4L6efzHc2iNorrRRXITifnDLlRrhaA=="
},
"node_modules/co": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
"integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
"peer": true,
"engines": {
"iojs": ">= 1.0.0",
"node": ">= 0.12.0"
}
},
"node_modules/co-body": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/co-body/-/co-body-5.2.0.tgz",
"integrity": "sha512-sX/LQ7LqUhgyaxzbe7IqwPeTr2yfpfUIQ/dgpKo6ZI4y4lpQA0YxAomWIY+7I7rHWcG02PG+OuPREzMW/5tszQ==",
"dependencies": {
"inflation": "^2.0.0",
"qs": "^6.4.0",
"raw-body": "^2.2.0",
"type-is": "^1.6.14"
}
},
"node_modules/color": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/color/-/color-5.0.0.tgz",
"integrity": "sha512-16BlyiuyLq3MLxpRWyOTiWsO3ii/eLQLJUQXBSNcxMBBSnyt1ee9YUdaozQp03ifwm5woztEZGDbk9RGVuCsdw==",
"peer": true,
"dependencies": {
"color-convert": "^3.0.1",
"color-string": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/color-convert": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-3.1.0.tgz",
"integrity": "sha512-TVoqAq8ZDIpK5lsQY874DDnu65CSsc9vzq0wLpNQ6UMBq81GSZocVazPiBbYGzngzBOIRahpkTzCLVe2at4MfA==",
"peer": true,
"dependencies": {
"color-name": "^2.0.0"
},
"engines": {
"node": ">=14.6"
}
},
"node_modules/color-hash": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/color-hash/-/color-hash-1.1.1.tgz",
"integrity": "sha512-OOZ2pKPuon1H7/77G0+xzSRDgITsik/kYzfJxmCBEI4ozM6UFhZ1aaZ6OhASbDwolHUq5PTRnhDle9FR72tqbw==",
"peer": true
},
"node_modules/color-name": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-2.0.0.tgz",
"integrity": "sha512-SbtvAMWvASO5TE2QP07jHBMXKafgdZz8Vrsrn96fiL+O92/FN/PLARzUW5sKt013fjAprK2d2iCn2hk2Xb5oow==",
"peer": true,
"engines": {
"node": ">=12.20"
}
},
"node_modules/color-string": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-2.0.1.tgz",
"integrity": "sha512-5z9FbYTZPAo8iKsNEqRNv+OlpBbDcoE+SY9GjLfDUHEfcNNV7tS9eSAlFHEaub/r5tBL9LtskAeq1l9SaoZ5tQ==",
"peer": true,
"dependencies": {
"color-name": "^2.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/color-support": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
"integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
"bin": {
"color-support": "bin.js"
}
},
"node_modules/colord": {
"version": "2.9.3",
"resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
"integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
},
"node_modules/colors": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz",
"integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==",
"engines": {
"node": ">=0.1.90"
}
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
"dependencies": {
"delayed-stream": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
"integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
"dev": true
},
"node_modules/commonmark": {
"version": "0.31.2",
"resolved": "https://registry.npmjs.org/commonmark/-/commonmark-0.31.2.tgz",
"integrity": "sha512-2fRLTyb9r/2835k5cwcAwOj0DEc44FARnMp5veGsJ+mEAZdi52sNopLu07ZyElQUz058H43whzlERDIaaSw4rg==",
"peer": true,
"dependencies": {
"entities": "~3.0.1",
"mdurl": "~1.0.1",
"minimist": "~1.2.8"
},
"bin": {
"commonmark": "bin/commonmark"
},
"engines": {
"node": "*"
}
},
"node_modules/compare-versions": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz",
"integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==",
"dev": true
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
},
"node_modules/concat-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
"integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
"engines": [
"node >= 0.8"
],
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^2.2.2",
"typedarray": "^0.0.6"
}
},
"node_modules/config-chain": {
"version": "1.1.13",
"resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz",
"integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==",
"peer": true,
"dependencies": {
"ini": "^1.3.4",
"proto-list": "~1.2.1"
}
},
"node_modules/content-disposition": {
"version": "0.5.4",
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"peer": true,
"dependencies": {
"safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
},
"node_modules/cookies": {
"version": "0.9.1",
"resolved": "https://registry.npmjs.org/cookies/-/cookies-0.9.1.tgz",
"integrity": "sha512-TG2hpqe4ELx54QER/S3HQ9SRVnQnGBtKUz5bLQWtYAQ+o6GpgMs6sYUvaiJjVxb+UXwhRhAEP3m7LbsIZ77Hmw==",
"peer": true,
"dependencies": {
"depd": "~2.0.0",
"keygrip": "~1.1.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
"integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
},
"node_modules/create-error-class": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz",
"integrity": "sha512-gYTKKexFO3kh200H1Nit76sRwRtOY32vQd3jpAQKpLtZqyNsSQNfI4N7o3eP2wUjV35pTWKRYqFUDBvUha/Pkw==",
"dependencies": {
"capture-stack-trace": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/create-require": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
"integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
"dev": true
},
"node_modules/cron": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/cron/-/cron-2.4.4.tgz",
"integrity": "sha512-MHlPImXJj3K7x7lyUHjtKEOl69CSlTOWxS89jiFgNkzXfvhVjhMz/nc7/EIfN9vgooZp8XTtXJ1FREdmbyXOiQ==",
"peer": true,
"dependencies": {
"@types/luxon": "~3.3.0",
"luxon": "~3.3.0"
}
},
"node_modules/cross-spawn": {
"version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
"integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dependencies": {
"path-key": "^3.1.0",
"shebang-command": "^2.0.0",
"which": "^2.0.1"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/crypt": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
"integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
"engines": {
"node": "*"
}
},
"node_modules/css-select": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
"integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
"peer": true,
"dependencies": {
"boolbase": "^1.0.0",
"css-what": "^6.1.0",
"domhandler": "^5.0.2",
"domutils": "^3.0.1",
"nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/css-what": {
"version": "6.2.2",
"resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
"integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
"peer": true,
"engines": {
"node": ">= 6"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
"node_modules/csv-stringify": {
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/csv-stringify/-/csv-stringify-6.6.0.tgz",
"integrity": "sha512-YW32lKOmIBgbxtu3g5SaiqWNwa/9ISQt2EcgOq0+RAIFufFp9is6tqNnKahqE5kuKvrnYAzs28r+s6pXJR8Vcw==",
"peer": true
},
"node_modules/cuint": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/cuint/-/cuint-0.2.2.tgz",
"integrity": "sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==",
"peer": true
},
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
"integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
"dependencies": {
"assert-plus": "^1.0.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/dateformat": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/dateformat/-/dateformat-2.2.0.tgz",
"integrity": "sha512-GODcnWq3YGoTnygPfi02ygEiRxqUxpJwuRHjdhJYuxpcZmDq4rjBiXYmbCCzStxo176ixfLT6i4NPwQooRySnw==",
"engines": {
"node": "*"
}
},
"node_modules/debug": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dependencies": {
"ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
},
"peerDependenciesMeta": {
"supports-color": {
"optional": true
}
}
},
"node_modules/decamelize": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz",
"integrity": "sha512-QCl8WTT4FSft5F+0M0InHKO6UYFfYhw5++vktTKpmUsQ6YUMPcBwMu7Sp3P0lMGk00hTNHohdhfdi9+OswLJuQ==",
"dependencies": {
"buffer-to-vinyl": "^1.0.0",
"concat-stream": "^1.4.6",
"decompress-tar": "^3.0.0",
"decompress-tarbz2": "^3.0.0",
"decompress-targz": "^3.0.0",
"decompress-unzip": "^3.0.0",
"stream-combiner2": "^1.1.1",
"vinyl-assign": "^1.0.1",
"vinyl-fs": "^2.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-response": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
"integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
"peer": true,
"dependencies": {
"mimic-response": "^3.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/decompress-tar": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz",
"integrity": "sha512-YuF7b9jA2bnBhf0/HQ/5UDgX5Ogzw1xJz6mWOFRctyOcmZPjJx3jjde9tCBjysvYscutRTPi35Q20mPDA74SKQ==",
"dependencies": {
"is-tar": "^1.0.0",
"object-assign": "^2.0.0",
"strip-dirs": "^1.0.0",
"tar-stream": "^1.1.1",
"through2": "^0.6.1",
"vinyl": "^0.4.3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-tar/node_modules/clone": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
"integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==",
"engines": {
"node": "*"
}
},
"node_modules/decompress-tar/node_modules/object-assign": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz",
"integrity": "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-tar/node_modules/vinyl": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
"integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==",
"dependencies": {
"clone": "^0.2.0",
"clone-stats": "^0.0.1"
},
"engines": {
"node": ">= 0.9"
}
},
"node_modules/decompress-tarbz2": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz",
"integrity": "sha512-UVCUT54LTEf8uqoytmEMVSwTVl/rZJ0o6bUJsJ7psRmICUzCsz9BJ31drbX0NtgwD9cFzIwKProa2yThmVBKvQ==",
"dependencies": {
"is-bzip2": "^1.0.0",
"object-assign": "^2.0.0",
"seek-bzip": "^1.0.3",
"strip-dirs": "^1.0.0",
"tar-stream": "^1.1.1",
"through2": "^0.6.1",
"vinyl": "^0.4.3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-tarbz2/node_modules/clone": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
"integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==",
"engines": {
"node": "*"
}
},
"node_modules/decompress-tarbz2/node_modules/object-assign": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz",
"integrity": "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-tarbz2/node_modules/vinyl": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
"integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==",
"dependencies": {
"clone": "^0.2.0",
"clone-stats": "^0.0.1"
},
"engines": {
"node": ">= 0.9"
}
},
"node_modules/decompress-targz": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz",
"integrity": "sha512-umeSWvrmd9/qcmGaf0oAc+Gx7La0B4Uxo+HXoo0HqrjEbCzn7SMiWvmE5sS56B+GqaoJ8z64ORZCRaOzKCYi/w==",
"dependencies": {
"is-gzip": "^1.0.0",
"object-assign": "^2.0.0",
"strip-dirs": "^1.0.0",
"tar-stream": "^1.1.1",
"through2": "^0.6.1",
"vinyl": "^0.4.3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-targz/node_modules/clone": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz",
"integrity": "sha512-g62n3Kb9cszeZvmvBUqP/dsEJD/+80pDA8u8KqHnAPrVnQ2Je9rVV6opxkhuWCd1kCn2gOibzDKxCtBvD3q5kA==",
"engines": {
"node": "*"
}
},
"node_modules/decompress-targz/node_modules/object-assign": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz",
"integrity": "sha512-CdsOUYIh5wIiozhJ3rLQgmUTgcyzFwZZrqhkKhODMoGtPKM+wt0h0CNIoauJWMsS9822EdzPsF/6mb4nLvPN5g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-targz/node_modules/vinyl": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz",
"integrity": "sha512-pmza4M5VA15HOImIQYWhoXGlGNafCm0QK5BpBUXkzzEwrRxKqBsbAhTfkT2zMcJhUX1G1Gkid0xaV8WjOl7DsA==",
"dependencies": {
"clone": "^0.2.0",
"clone-stats": "^0.0.1"
},
"engines": {
"node": ">= 0.9"
}
},
"node_modules/decompress-unzip": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz",
"integrity": "sha512-rclee6Q/+aChW77vbHmtGNZi3ko1Qhsp9Brs5mVyhBSeg+K4n+6MHo47y/+7GsmYZuEqVJ46LjwT3/N8N50jZQ==",
"dependencies": {
"is-zip": "^1.0.0",
"read-all-stream": "^3.0.0",
"stat-mode": "^0.2.0",
"strip-dirs": "^1.0.0",
"through2": "^2.0.0",
"vinyl": "^1.0.0",
"yauzl": "^2.2.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/decompress-unzip/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/deep-equal": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz",
"integrity": "sha512-bHtC0iYvWhyaTzvV3CZgPeZQqCOBGyGsVV7v4eevpdkLHfiSrXUdBG+qAuSz4RI70sszvjQ1QSZ98An1yNwpSw==",
"peer": true
},
"node_modules/deep-extend": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
"integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/deep-is": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
"integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
"dev": true
},
"node_modules/deepmerge": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
"integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/default-require-extensions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/default-require-extensions/-/default-require-extensions-3.0.1.tgz",
"integrity": "sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw==",
"dev": true,
"dependencies": {
"strip-bom": "^4.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/define-data-property": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
"dependencies": {
"es-define-property": "^1.0.0",
"es-errors": "^1.3.0",
"gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
"integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/delegates": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
"peer": true
},
"node_modules/depd": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/destr": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz",
"integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA=="
},
"node_modules/destroy": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"peer": true,
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/detect-libc": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.4.tgz",
"integrity": "sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==",
"peer": true,
"engines": {
"node": ">=8"
}
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
"peer": true
},
"node_modules/dezalgo": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/dezalgo/-/dezalgo-1.0.4.tgz",
"integrity": "sha512-rXSP0bf+5n0Qonsb+SVVfNfIsimO4HEtmnIpPHY8Q1UCzKlQrDMfdobr8nJOOsRgWCyMRqeSBQzmWUMq7zvVig==",
"dev": true,
"dependencies": {
"asap": "^2.0.0",
"wrappy": "1"
}
},
"node_modules/diff": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/diff/-/diff-5.2.0.tgz",
"integrity": "sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/dir-glob": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
"integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
"dependencies": {
"path-type": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
- "dev": true,
- "dependencies": {
- "esutils": "^2.0.2"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
"node_modules/dom-serializer": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
"integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
"peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.2",
"entities": "^4.2.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/dom-serializer/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/domelementtype": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
"integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"peer": true
},
"node_modules/domhandler": {
"version": "5.0.3",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
"integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
"peer": true,
"dependencies": {
"domelementtype": "^2.3.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/domutils": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
"integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
"peer": true,
"dependencies": {
"dom-serializer": "^2.0.0",
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/dot-prop": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-8.0.2.tgz",
"integrity": "sha512-xaBe6ZT4DHPkg0k4Ytbvn5xoxgpG0jOS1dYxSOwAHPuNLjP3/OzN0gH55SrLqpx8cBfSaVt91lXYkApjb+nYdQ==",
"peer": true,
"dependencies": {
"type-fest": "^3.8.0"
},
"engines": {
"node": ">=16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/dot-prop/node_modules/type-fest": {
"version": "3.13.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz",
"integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==",
"peer": true,
"engines": {
"node": ">=14.16"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/download": {
"version": "4.4.3",
"resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz",
"integrity": "sha512-yOTsksXxUQ9b/p/HA3g9L97JZThcAKq8v3+Afwhf/kIoV0spu6pOvj+OKQbyGKYAwBGqSPbO+x1pCFSg5ce9OA==",
"dependencies": {
"caw": "^1.0.1",
"concat-stream": "^1.4.7",
"each-async": "^1.0.0",
"filenamify": "^1.0.1",
"got": "^5.0.0",
"gulp-decompress": "^1.2.0",
"gulp-rename": "^1.2.0",
"is-url": "^1.2.0",
"object-assign": "^4.0.1",
"read-all-stream": "^3.0.0",
"readable-stream": "^2.0.2",
"stream-combiner2": "^1.1.1",
"vinyl": "^1.0.0",
"vinyl-fs": "^2.2.0",
"ware": "^1.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/dunder-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
"integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.1",
"es-errors": "^1.3.0",
"gopd": "^1.2.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/duplexer2": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz",
"integrity": "sha512-asLFVfWWtJ90ZyOUHMqk7/S2w2guQKxUI2itj3d92ADHhxUSbCMGi1f1cBcJ7xM1To+pE/Khbwo1yuNbMEPKeA==",
"dependencies": {
"readable-stream": "^2.0.2"
}
},
"node_modules/duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
"integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
"dependencies": {
"end-of-stream": "^1.0.0",
"inherits": "^2.0.1",
"readable-stream": "^2.0.0",
"stream-shift": "^1.0.0"
}
},
"node_modules/each-async": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz",
"integrity": "sha512-0hJGub96skwr+sUojv7zQ0kc9i4jn3SwLiLk8Jr7KDz7aaaMzkN5UX3a/9ZhzC0OfZVyXHhlHcjC0KVOiKZ+HQ==",
"dependencies": {
"onetime": "^1.0.0",
"set-immediate-shim": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/eastasianwidth": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
"integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
"peer": true
},
"node_modules/ecc-jsbn": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
"integrity": "sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
"dependencies": {
"jsbn": "~0.1.0",
"safer-buffer": "^2.1.0"
}
},
"node_modules/editorconfig": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz",
"integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==",
"peer": true,
"dependencies": {
"@one-ini/wasm": "0.1.1",
"commander": "^10.0.0",
"minimatch": "9.0.1",
"semver": "^7.5.3"
},
"bin": {
"editorconfig": "bin/editorconfig"
},
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"peer": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/editorconfig/node_modules/commander": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
"integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
"peer": true,
"engines": {
"node": ">=14"
}
},
"node_modules/editorconfig/node_modules/minimatch": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz",
"integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==",
"peer": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/ee-first": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
"peer": true
},
"node_modules/ejs": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/ejs/-/ejs-1.0.0.tgz",
"integrity": "sha512-hK3tEqj0pP7UF5UHKNiRvm3zCaYk7UI4EBJ6wwN5O2qX1WdSovmqvUHEbNOJuglXzVkk/H0r7vgst3mVcQXrPA==",
"deprecated": "Critical security bugs fixed in 2.5.5"
},
"node_modules/electron-to-chromium": {
"version": "1.5.199",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.199.tgz",
"integrity": "sha512-3gl0S7zQd88kCAZRO/DnxtBKuhMO4h0EaQIN3YgZfV6+pW+5+bf2AdQeHNESCoaQqo/gjGVYEf2YM4O5HJQqpQ==",
"dev": true
},
"node_modules/emittery": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/emittery/-/emittery-0.8.1.tgz",
"integrity": "sha512-uDfvUjVrfGJJhymx/kz6prltenw1u7WrCg1oa94zYY8xxVpLLUu045LAT0dhDZdXG58/EpPL/5kA180fQ/qudg==",
"peer": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sindresorhus/emittery?sponsor=1"
}
},
"node_modules/emoji-regex": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
},
"node_modules/encodeurl": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
"peer": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/end-of-stream": {
"version": "1.4.5",
"resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
"integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
"dependencies": {
"once": "^1.4.0"
}
},
- "node_modules/enquirer": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz",
- "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==",
- "dev": true,
- "dependencies": {
- "ansi-colors": "^4.1.1",
- "strip-ansi": "^6.0.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
"node_modules/entities": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-3.0.1.tgz",
"integrity": "sha512-WiyBqoomrwMdFG1e0kqvASYfnlb0lp8M5o5Fw2OFq1hNZxxcNk8Ik0Xm7LxzBhuidnZB/UtBqVCgUz3kBOP51Q==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/es-define-property": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
"integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-errors": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
"integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
"dependencies": {
"es-errors": "^1.3.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es-set-tostringtag": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
"integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
"dev": true,
"dependencies": {
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.6",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/es6-error": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.1.1.tgz",
"integrity": "sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==",
"dev": true
},
"node_modules/es6-promise": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
"integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg=="
},
"node_modules/esbuild": {
"version": "0.20.2",
"resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz",
"integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==",
"hasInstallScript": true,
"bin": {
"esbuild": "bin/esbuild"
},
"engines": {
"node": ">=12"
},
"optionalDependencies": {
"@esbuild/aix-ppc64": "0.20.2",
"@esbuild/android-arm": "0.20.2",
"@esbuild/android-arm64": "0.20.2",
"@esbuild/android-x64": "0.20.2",
"@esbuild/darwin-arm64": "0.20.2",
"@esbuild/darwin-x64": "0.20.2",
"@esbuild/freebsd-arm64": "0.20.2",
"@esbuild/freebsd-x64": "0.20.2",
"@esbuild/linux-arm": "0.20.2",
"@esbuild/linux-arm64": "0.20.2",
"@esbuild/linux-ia32": "0.20.2",
"@esbuild/linux-loong64": "0.20.2",
"@esbuild/linux-mips64el": "0.20.2",
"@esbuild/linux-ppc64": "0.20.2",
"@esbuild/linux-riscv64": "0.20.2",
"@esbuild/linux-s390x": "0.20.2",
"@esbuild/linux-x64": "0.20.2",
"@esbuild/netbsd-x64": "0.20.2",
"@esbuild/openbsd-x64": "0.20.2",
"@esbuild/sunos-x64": "0.20.2",
"@esbuild/win32-arm64": "0.20.2",
"@esbuild/win32-ia32": "0.20.2",
"@esbuild/win32-x64": "0.20.2"
}
},
"node_modules/escalade": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
"integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
"engines": {
"node": ">=6"
}
},
"node_modules/escape-goat": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-4.0.0.tgz",
"integrity": "sha512-2Sd4ShcWxbx6OY1IHyla/CVNwvg7XwZVoXZHcSu9w9SReNP1EzzD5T8NWKIR38fIqEns9kDWKUQTXXAmlDrdPg==",
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
"peer": true
},
"node_modules/escape-string-regexp": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/eslint": {
- "version": "7.32.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-7.32.0.tgz",
- "integrity": "sha512-VHZ8gX+EDfz+97jGcgyGCyRia/dPOd6Xh9yPv8Bl1+SoaIwD+a/vlrOmGRUyOYu7MwUhc7CxqeaDZU13S4+EpA==",
- "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "version": "9.36.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.36.0.tgz",
+ "integrity": "sha512-hB4FIzXovouYzwzECDcUkJ4OcfOEkXTv2zRY6B9bkwjx/cprAq0uvm1nl7zvQ0/TsUk0zQiN4uPfJpB9m+rPMQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "7.12.11",
- "@eslint/eslintrc": "^0.4.3",
- "@humanwhocodes/config-array": "^0.5.0",
- "ajv": "^6.10.0",
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.0",
+ "@eslint/config-helpers": "^0.3.1",
+ "@eslint/core": "^0.15.2",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.36.0",
+ "@eslint/plugin-kit": "^0.3.5",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
"chalk": "^4.0.0",
- "cross-spawn": "^7.0.2",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "enquirer": "^2.3.5",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
"escape-string-regexp": "^4.0.0",
- "eslint-scope": "^5.1.1",
- "eslint-utils": "^2.1.0",
- "eslint-visitor-keys": "^2.0.0",
- "espree": "^7.3.1",
- "esquery": "^1.4.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
"esutils": "^2.0.2",
"fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^6.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.1.2",
- "globals": "^13.6.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
"imurmurhash": "^0.1.4",
"is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.4.1",
"lodash.merge": "^4.6.2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.2",
"natural-compare": "^1.4.0",
- "optionator": "^0.9.1",
- "progress": "^2.0.0",
- "regexpp": "^3.1.0",
- "semver": "^7.2.1",
- "strip-ansi": "^6.0.0",
- "strip-json-comments": "^3.1.0",
- "table": "^6.0.9",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
+ "optionator": "^0.9.3"
},
"bin": {
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://opencollective.com/eslint"
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
}
},
"node_modules/eslint-config-prettier": {
"version": "8.10.2",
"resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-8.10.2.tgz",
"integrity": "sha512-/IGJ6+Dka158JnP5n5YFMOszjDWrXggGz1LaK/guZq9vZTmniaKlHcsscvkAhn9y4U+BU3JuUdYvtAMcv30y4A==",
"dev": true,
+ "license": "MIT",
"bin": {
"eslint-config-prettier": "bin/cli.js"
},
"peerDependencies": {
"eslint": ">=7.0.0"
}
},
"node_modules/eslint-plugin-prettier": {
- "version": "3.4.1",
- "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-3.4.1.tgz",
- "integrity": "sha512-htg25EUYUeIhKHXjOinK4BgCcDwtLHjqaxCDsMy5nbnUMkKFvIhMVCp+5GFUXQ4Nr8lBsPqtGAqBenbpFqAA2g==",
+ "version": "5.5.4",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.5.4.tgz",
+ "integrity": "sha512-swNtI95SToIz05YINMA6Ox5R057IMAmWZ26GqPxusAp1TZzj+IdY9tXNWWD3vkF/wEqydCONcwjTFpxybBqZsg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "prettier-linter-helpers": "^1.0.0"
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.11.7"
},
"engines": {
- "node": ">=6.0.0"
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
},
"peerDependencies": {
- "eslint": ">=5.0.0",
- "prettier": ">=1.13.0"
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
+ "prettier": ">=3.0.0"
},
"peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
"eslint-config-prettier": {
"optional": true
}
}
},
"node_modules/eslint-plugin-with-tsc-error": {
"version": "0.0.7",
"resolved": "https://registry.npmjs.org/eslint-plugin-with-tsc-error/-/eslint-plugin-with-tsc-error-0.0.7.tgz",
"integrity": "sha512-DfFrR/RoOm6n79rJyi+nQbd1I02Mi1pIX2rWbOQ4kcAhhpgdit6+tUdmxVf2mbYpP/k8ZK2I4WJpQSSmlO26tA==",
"dev": true,
"dependencies": {
"@typescript-eslint/experimental-utils": "^4.9.0",
"compare-versions": "^3.6.0"
},
"peerDependencies": {
"@typescript-eslint/parser": "*",
"eslint": "*",
"typescript": "*"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
"dev": true,
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
},
"engines": {
"node": ">=8.0.0"
}
},
- "node_modules/eslint-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-2.1.0.tgz",
- "integrity": "sha512-w94dQYoauyvlDc43XnGB8lU3Zt713vNChgt4EWwhXAP2XkBvndfxF0AgIqKOOasjPIPzj9JqgwkwbCYD0/V3Zg==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^1.1.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
- "node_modules/eslint-utils/node_modules/eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/eslint-visitor-keys": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
"integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
"dev": true,
"engines": {
"node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
"funding": {
"url": "https://opencollective.com/eslint"
}
},
"node_modules/eslint/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
"node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
- "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">= 4"
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
}
},
"node_modules/eslint/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/esm": {
"version": "3.2.25",
"resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz",
"integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==",
"engines": {
"node": ">=6"
}
},
"node_modules/espree": {
- "version": "7.3.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-7.3.1.tgz",
- "integrity": "sha512-v3JCNCE64umkFpmkFGqzVKsOT0tN1Zr+ueqLZfpV1Ob8e+CEgPWa+OxCoGH3tnhimMKIaBm4m/vaRpJ/krRz2g==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^7.4.0",
- "acorn-jsx": "^5.3.1",
- "eslint-visitor-keys": "^1.3.0"
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=4"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
"dev": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
},
"engines": {
"node": ">=4"
}
},
"node_modules/esquery": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
"integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
"dev": true,
"dependencies": {
"estraverse": "^5.1.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/esquery/node_modules/estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/esrecurse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
"dev": true,
"dependencies": {
"estraverse": "^5.2.0"
},
"engines": {
"node": ">=4.0"
}
},
"node_modules/esrecurse/node_modules/estraverse": {
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/estraverse": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true,
"engines": {
"node": ">=4.0"
}
},
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/expand-brackets": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz",
"integrity": "sha512-hxx03P2dJxss6ceIeri9cmYOT4SRs3Zk3afZwWpOsRqLqprhTR8u++SlC+sFGsQr7WGFPdMF7Gjc1njDLDK6UA==",
"dependencies": {
"is-posix-bracket": "^0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/expand-range": {
"version": "1.8.2",
"resolved": "https://registry.npmjs.org/expand-range/-/expand-range-1.8.2.tgz",
"integrity": "sha512-AFASGfIlnIbkKPQwX1yHaDjFvh/1gyKJODme52V6IORh69uEYgZp0o9C+qsIGNVEiuuhQU0CSSl++Rlegg1qvA==",
"dependencies": {
"fill-range": "^2.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/expand-range/node_modules/fill-range": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-2.2.4.tgz",
"integrity": "sha512-cnrcCbj01+j2gTG921VZPnHbjmdAf8oQV/iGeV2kZxGSyfYjjTyY79ErsK1WJWMpw6DaApEX72binqJE+/d+5Q==",
"dependencies": {
"is-number": "^2.1.0",
"isobject": "^2.0.0",
"randomatic": "^3.0.0",
"repeat-element": "^1.1.2",
"repeat-string": "^1.5.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/expand-range/node_modules/is-number": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-2.1.0.tgz",
"integrity": "sha512-QUzH43Gfb9+5yckcrSA0VBDwEtDUchrk4F6tfJZQuNzDJbEDB9cZNzSfXGQ1jqmdDY/kl41lUOWM9syA8z8jlg==",
"dependencies": {
"kind-of": "^3.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/expand-template": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
"integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
"peer": true,
"engines": {
"node": ">=6"
}
},
"node_modules/extend": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
"integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g=="
},
"node_modules/extend-shallow": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
"integrity": "sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
"dependencies": {
"is-extendable": "^0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/extglob": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz",
"integrity": "sha512-1FOj1LOwn42TMrruOHGt18HemVnbwAmAak7krWk+wa93KXxGbK+2jpezm+ytJYDaBX0/SPLZFHKM7m+tKobWGg==",
"dependencies": {
"is-extglob": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/extglob/node_modules/is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/extsprintf": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
"integrity": "sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
"engines": [
"node >=0.6.0"
]
},
"node_modules/fancy-log": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/fancy-log/-/fancy-log-1.3.3.tgz",
"integrity": "sha512-k9oEhlyc0FrVh25qYuSELjr8oxsCoc4/LEZfg2iJJrfEk/tZL9bCoJE47gqAvI2m/AUjluCS4+3I0eTx8n3AEw==",
"dependencies": {
"ansi-gray": "^0.1.1",
"color-support": "^1.1.3",
"parse-node-version": "^1.0.0",
"time-stamp": "^1.0.0"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/fast-deep-equal": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
"integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
},
"node_modules/fast-diff": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
"integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
"dev": true
},
"node_modules/fast-fifo": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
"peer": true
},
"node_modules/fast-glob": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
"integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
"dev": true,
"dependencies": {
"@nodelib/fs.stat": "^2.0.2",
"@nodelib/fs.walk": "^1.2.3",
"glob-parent": "^5.1.2",
"merge2": "^1.3.0",
"micromatch": "^4.0.8"
},
"engines": {
"node": ">=8.6.0"
}
},
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true
},
- "node_modules/fast-uri": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.6.tgz",
- "integrity": "sha512-Atfo14OibSv5wAp4VWNsFYE1AchQRTv9cBGWET4pZWHzYshFSS9NQI6I57rdKn9croWVMbYFbLhJ+yJvmZIIHw==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ]
- },
"node_modules/fastq": {
"version": "1.19.1",
"resolved": "https://registry.npmjs.org/fastq/-/fastq-1.19.1.tgz",
"integrity": "sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ==",
"dev": true,
"dependencies": {
"reusify": "^1.0.4"
}
},
"node_modules/fd-slicer": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz",
"integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==",
"dependencies": {
"pend": "~1.2.0"
}
},
"node_modules/file-entry-cache": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz",
- "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==",
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "flat-cache": "^3.0.4"
+ "flat-cache": "^4.0.0"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16.0.0"
}
},
"node_modules/file-type": {
"version": "3.9.0",
"resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz",
"integrity": "sha512-RLoqTXE8/vPmMuTI88DAzhMYC99I8BWv7zYP4A1puo5HIjEJ5EX48ighy4ZyKMG9EDXxBgW6e++cn7d1xuFghA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/filename-regex": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz",
"integrity": "sha512-BTCqyBaWBTsauvnHiE8i562+EdJj+oUpkqWp2R1iCoR8f6oo8STRu3of7WJJ0TqWtxN50a5YFpzYK4Jj9esYfQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/filename-reserved-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz",
"integrity": "sha512-UZArj7+U+2reBBVCvVmRlyq9D7EYQdUtuNN+1iz7pF1jGcJ2L0TjiRCxsTZfj2xFbM4c25uGCUDpKTHA7L2TKg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/filenamify": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz",
"integrity": "sha512-DKVP0WQcB7WaIMSwDETqImRej2fepPqvXQjaVib7LRZn9Rxn5UbvK2tYTqGf1A1DkIprQQkG4XSQXSOZp7Q3GQ==",
"dependencies": {
"filename-reserved-regex": "^1.0.0",
"strip-outer": "^1.0.0",
"trim-repeated": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/fill-range": {
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
"integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
"dependencies": {
"to-regex-range": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/filru": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/filru/-/filru-2.1.0.tgz",
"integrity": "sha512-rcVnKdKbZxaQfrKbN6D8HDR0UGjC4Y7cA/xARjcyTp25kds9PiGWpwTx85Z86of/cOA3Wp5h7k7rnZmMN9oUqQ==",
"peer": true,
"dependencies": {
"debug": "^3.1.0",
"mkdirp": "^0.5.1",
"xxhashjs": "^0.2.1"
},
"engines": {
"node": ">=6.4.0"
}
},
"node_modules/filru/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"peer": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/find-cache-dir": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
"integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
"dev": true,
"dependencies": {
"commondir": "^1.0.1",
"make-dir": "^3.0.2",
"pkg-dir": "^4.1.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
"node_modules/find-remove": {
"version": "0.2.12",
"resolved": "https://registry.npmjs.org/find-remove/-/find-remove-0.2.12.tgz",
"integrity": "sha512-7OUNswjWeQxELHkpGgioN6MhX5tf82kIlbPoufcOLW7O8siBU/POXv4/giKxXe4Xb1LHKlG16Rw1Nk74pg3LCQ==",
"dependencies": {
"fmerge": "1.2.0",
"rimraf": "2.5.2"
},
"engines": {
"node": ">=0.10.24"
}
},
"node_modules/find-remove/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/find-remove/node_modules/rimraf": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.5.2.tgz",
"integrity": "sha512-IlPt1Uu2VoNSXQ2VvrVSdanffKsqS2ozRsJNEDSBFnS3Kt5hpOcHoLFHyOEPS43+ZCwH3BbmW/JvGPWGD3CS8g==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dependencies": {
"glob": "^7.0.0"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/find-up": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
"integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
"dependencies": {
"locate-path": "^6.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/first-chunk-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/first-chunk-stream/-/first-chunk-stream-1.0.0.tgz",
"integrity": "sha512-ArRi5axuv66gEsyl3UuK80CzW7t56hem73YGNYxNWTGNKFJUadSb9Gu9SHijYEUi8ulQMf1bJomYNwSCPHhtTQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/flat": {
"version": "5.0.2",
"resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
"integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"dev": true,
"bin": {
"flat": "cli.js"
}
},
"node_modules/flat-cache": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz",
- "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==",
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"flatted": "^3.2.9",
- "keyv": "^4.5.3",
- "rimraf": "^3.0.2"
+ "keyv": "^4.5.4"
},
"engines": {
- "node": "^10.12.0 || >=12.0.0"
+ "node": ">=16"
}
},
"node_modules/flatted": {
"version": "3.3.3",
"resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
"integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/fmerge": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fmerge/-/fmerge-1.2.0.tgz",
"integrity": "sha512-ByFA9Pg++TFyB+MlYTEQ/FF/hpEVYjr56xWOpSzCxsjkwfWC7miNIgJAFj3cNbhtn/vusqyen55M8Bg7t3lYiA==",
"hasInstallScript": true
},
"node_modules/follow-redirects": {
"version": "1.15.11",
"resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
"integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
"dev": true,
"funding": [
{
"type": "individual",
"url": "https://github.com/sponsors/RubenVerborgh"
}
],
"engines": {
"node": ">=4.0"
},
"peerDependenciesMeta": {
"debug": {
"optional": true
}
}
},
"node_modules/fonsta": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/fonsta/-/fonsta-1.1.1.tgz",
"integrity": "sha512-zlIvKEwxFnNGHbwqMZAeixGLgqchNmeQrkIv8M0+grbQfi3oY7OmEbYDicggmwYniTehgmwqiUy+d9M89CSOIg==",
"dependencies": {
"cli-spinner": "^0.2.5",
"colors": "^1.1.2",
"commander": "^2.9.0",
"download": "^4.4.3",
"es6-promise": "^3.2.1",
"find-remove": "^0.2.11",
"fs-extra": "^0.30.0",
"mkdirp": "^0.5.1",
"node-font-face-generator": "0.1.5",
"request": "^2.72.0",
"rimraf": "^2.5.2"
},
"bin": {
"fonsta": "bin/fonsta"
},
"engines": {
"node": ">=0.10.20"
}
},
"node_modules/fonsta/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fonsta/node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/for-each": {
"version": "0.3.5",
"resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
"integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
"dependencies": {
"is-callable": "^1.2.7"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/for-in": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
"integrity": "sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/for-own": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/for-own/-/for-own-0.1.5.tgz",
"integrity": "sha512-SKmowqGTJoPzLO1T0BBJpkfp3EMacCMOuH40hOUbrbzElVktk4DioXVM99QkLCyKoiuOmyjgcWMpVz2xjE7LZw==",
"dependencies": {
"for-in": "^1.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/foreground-child": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-2.0.0.tgz",
"integrity": "sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA==",
"dev": true,
"dependencies": {
"cross-spawn": "^7.0.0",
"signal-exit": "^3.0.2"
},
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/forever-agent": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
"integrity": "sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
"engines": {
"node": "*"
}
},
"node_modules/form-data": {
"version": "4.0.4",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.4.tgz",
"integrity": "sha512-KrGhL9Q4zjj0kiUt5OO4Mr/A/jlI2jDYs5eHBpYHPcBEVSiipAvn2Ko2HnPe20rmcuuvMHNdZFp+4IlGTMF0Ow==",
"dev": true,
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.8",
"es-set-tostringtag": "^2.1.0",
"hasown": "^2.0.2",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/formidable": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-2.1.5.tgz",
"integrity": "sha512-Oz5Hwvwak/DCaXVVUtPn4oLMLLy1CdclLKO1LFgU7XzDpVMUU5UjlSLpGMocyQNNk8F6IJW9M/YdooSn2MRI+Q==",
"dev": true,
"dependencies": {
"@paralleldrive/cuid2": "^2.2.2",
"dezalgo": "^1.0.4",
"once": "^1.4.0",
"qs": "^6.11.0"
},
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/fresh": {
"version": "0.5.2",
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/fromentries": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/fromentries/-/fromentries-1.3.2.tgz",
"integrity": "sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/fs-constants": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow=="
},
"node_modules/fs-extra": {
"version": "0.30.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-0.30.0.tgz",
"integrity": "sha512-UvSPKyhMn6LEd/WpUaV9C9t3zATuqoqfWc3QdPhPLb58prN9tqYPlPWi8Krxi44loBoUzlobqZ3+8tGpxxSzwA==",
"dependencies": {
"graceful-fs": "^4.1.2",
"jsonfile": "^2.1.0",
"klaw": "^1.0.0",
"path-is-absolute": "^1.0.0",
"rimraf": "^2.2.8"
}
},
"node_modules/fs-extra/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/fs-extra/node_modules/rimraf": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
"integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
}
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
"integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw=="
},
"node_modules/fsevents": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
"integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/function-bind": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
- "dev": true
- },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
"integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
"dependencies": {
"call-bind-apply-helpers": "^1.0.2",
"es-define-property": "^1.0.1",
"es-errors": "^1.3.0",
"es-object-atoms": "^1.1.1",
"function-bind": "^1.1.2",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-symbols": "^1.1.0",
"hasown": "^2.0.2",
"math-intrinsics": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/get-package-type": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
"integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
"dev": true,
"engines": {
"node": ">=8.0.0"
}
},
"node_modules/get-port": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz",
"integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==",
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/get-proto": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
"integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
"dependencies": {
"dunder-proto": "^1.0.1",
"es-object-atoms": "^1.0.0"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/get-proxy": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz",
"integrity": "sha512-3cJ+77wC52qD2PqWNXtB2HkU6tQXc/X3hSMtSN0Y8c8nbYMMxF7vpsjH4H0iSt+28l/NK13DKl8iKAVGkqDFnA==",
"dependencies": {
"rc": "^1.1.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/get-stdin": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz",
"integrity": "sha512-F5aQMywwJ2n85s4hJPTT9RPxGmubonuB10MNYo17/xph174n2MIR33HRguhzVag10O/npM7SPk73LMZNP+FaWw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/getpass": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
"integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
"dependencies": {
"assert-plus": "^1.0.0"
}
},
"node_modules/github-from-package": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
"integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
"peer": true
},
"node_modules/glob": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz",
"integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^5.0.1",
"once": "^1.3.0"
},
"engines": {
"node": ">=12"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/glob-base": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/glob-base/-/glob-base-0.3.0.tgz",
"integrity": "sha512-ab1S1g1EbO7YzauaJLkgLp7DZVAqj9M/dvKlTt8DkXA2tiOIcSMrlVI2J1RZyB5iJVccEscjGn+kpOG9788MHA==",
"dependencies": {
"glob-parent": "^2.0.0",
"is-glob": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-base/node_modules/glob-parent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-2.0.0.tgz",
"integrity": "sha512-JDYOvfxio/t42HKdxkAYaCiBN7oYiuxykOxKxdaUW5Qn0zaYN3gRQWolrwdnf0shM9/EP0ebuuTmyoXNr1cC5w==",
"dependencies": {
"is-glob": "^2.0.0"
}
},
"node_modules/glob-base/node_modules/is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-base/node_modules/is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
"dependencies": {
"is-extglob": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-parent": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
"dependencies": {
"is-glob": "^4.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/glob-stream": {
"version": "5.3.5",
"resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz",
"integrity": "sha512-piN8XVAO2sNxwVLokL4PswgJvK/uQ6+awwXUVRTGF+rRfgCZpn4hOqxiRuTEbU/k3qgKl0DACYQ/0Sge54UMQg==",
"dependencies": {
"extend": "^3.0.0",
"glob": "^5.0.3",
"glob-parent": "^3.0.0",
"micromatch": "^2.3.7",
"ordered-read-streams": "^0.3.0",
"through2": "^0.6.0",
"to-absolute-glob": "^0.1.1",
"unique-stream": "^2.0.2"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/glob-stream/node_modules/braces": {
"version": "1.8.5",
"resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz",
"integrity": "sha512-xU7bpz2ytJl1bH9cgIurjpg/n8Gohy9GTw81heDYLJQ4RU60dlyJsa+atVF2pI0yMMvKxI9HkKwjePCj5XI1hw==",
"dependencies": {
"expand-range": "^1.8.1",
"preserve": "^0.2.0",
"repeat-element": "^1.1.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-stream/node_modules/glob": {
"version": "5.0.15",
"resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz",
"integrity": "sha512-c9IPMazfRITpmAAKi22dK1VKxGDX9ehhqfABDriL/lzO92xcUKEJPQHrVA/2YHSNFB4iFlykVmWvwo48nr3OxA==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dependencies": {
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "2 || 3",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
}
},
"node_modules/glob-stream/node_modules/glob-parent": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
"integrity": "sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
"dependencies": {
"is-glob": "^3.1.0",
"path-dirname": "^1.0.0"
}
},
"node_modules/glob-stream/node_modules/is-glob": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
"integrity": "sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
"dependencies": {
"is-extglob": "^2.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-stream/node_modules/micromatch": {
"version": "2.3.11",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz",
"integrity": "sha512-LnU2XFEk9xxSJ6rfgAry/ty5qwUTyHYOBU0g4R6tIw5ljwgGIBmiKhRWLw5NpMOnrgUNcDJ4WMp8rl3sYVHLNA==",
"dependencies": {
"arr-diff": "^2.0.0",
"array-unique": "^0.2.1",
"braces": "^1.8.2",
"expand-brackets": "^0.1.4",
"extglob": "^0.3.1",
"filename-regex": "^2.0.0",
"is-extglob": "^1.0.0",
"is-glob": "^2.0.1",
"kind-of": "^3.0.2",
"normalize-path": "^2.0.1",
"object.omit": "^2.0.0",
"parse-glob": "^3.0.4",
"regex-cache": "^0.4.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-stream/node_modules/micromatch/node_modules/is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-stream/node_modules/micromatch/node_modules/is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
"dependencies": {
"is-extglob": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob-stream/node_modules/normalize-path": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
"integrity": "sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
"dependencies": {
"remove-trailing-separator": "^1.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/glob/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/glob/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/globals": {
- "version": "13.24.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz",
- "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==",
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
- "dependencies": {
- "type-fest": "^0.20.2"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globalyzer": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/globalyzer/-/globalyzer-0.1.0.tgz",
"integrity": "sha512-40oNTM9UfG6aBmuKxk/giHn5nQ8RVz/SS4Ir6zgzOv9/qC3kKZ9v4etGTcJbEl/NyVQH7FGU7d+X1egr57Md2Q=="
},
"node_modules/globby": {
"version": "11.1.0",
"resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
"integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
"dependencies": {
"array-union": "^2.1.0",
"dir-glob": "^3.0.1",
"fast-glob": "^3.2.9",
"ignore": "^5.2.0",
"merge2": "^1.4.1",
"slash": "^3.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/globrex": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/globrex/-/globrex-0.1.2.tgz",
"integrity": "sha512-uHJgbwAMwNFf5mLst7IWLNg14x1CkeqglJb/K3doi4dw6q2IvAAmM/Y81kevy83wP+Sst+nutFTYOGg3d1lsxg=="
},
"node_modules/glogg": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/glogg/-/glogg-1.0.2.tgz",
"integrity": "sha512-5mwUoSuBk44Y4EshyiqcH95ZntbDdTQqA3QYSrxmzj28Ai0vXBGMH1ApSANH14j2sIRtqCEyg6PfsuP7ElOEDA==",
"dependencies": {
"sparkles": "^1.0.0"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/google-fonts-helper": {
"version": "3.7.3",
"resolved": "https://registry.npmjs.org/google-fonts-helper/-/google-fonts-helper-3.7.3.tgz",
"integrity": "sha512-dENZeK6RMvkCOFoKbLbS+pyoDgpmk4U6BYmfXnztMar2d8SjEG6valxql/Lkyi7bu5F+3FTdE+gAEYSYZ5zzMA==",
"dependencies": {
"deepmerge": "^4.3.1",
"hookable": "^5.5.3",
"ofetch": "^1.4.1",
"ufo": "^1.5.4"
}
},
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
"integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/got": {
"version": "5.6.0",
"resolved": "https://registry.npmjs.org/got/-/got-5.6.0.tgz",
"integrity": "sha512-MnypzkaW8dldA8AbJFjMs7y14+ykd2V8JCLKSvX1Gmzx1alH3Y+3LArywHDoAF2wS3pnZp4gacoYtvqBeF6drQ==",
"dependencies": {
"create-error-class": "^3.0.1",
"duplexer2": "^0.1.4",
"is-plain-obj": "^1.0.0",
"is-redirect": "^1.0.0",
"is-retry-allowed": "^1.0.0",
"is-stream": "^1.0.0",
"lowercase-keys": "^1.0.0",
"node-status-codes": "^1.0.0",
"object-assign": "^4.0.1",
"parse-json": "^2.1.0",
"pinkie-promise": "^2.0.0",
"read-all-stream": "^3.0.0",
"readable-stream": "^2.0.5",
"timed-out": "^2.0.0",
"unzip-response": "^1.0.0",
"url-parse-lax": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/graceful-fs": {
"version": "4.2.11",
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
},
"node_modules/graphemer": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
"integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
"dev": true
},
"node_modules/gulp-decompress": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz",
"integrity": "sha512-ChTv+4/4BwAdQLUgQoAvLFjYFvxYF6p9Mmf/b19/Lp7yNCvb8+KRkdXV8Gd7XErxtrEh8XDCCVon3DgqW4TgfA==",
"dependencies": {
"archive-type": "^3.0.0",
"decompress": "^3.0.0",
"gulp-util": "^3.0.1",
"readable-stream": "^2.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-rename": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/gulp-rename/-/gulp-rename-1.4.0.tgz",
"integrity": "sha512-swzbIGb/arEoFK89tPY58vg3Ok1bw+d35PfUNwWqdo7KM4jkmuGA78JiDNqR+JeZFaeeHnRg9N7aihX3YPmsyg==",
"engines": {
"node": ">=4"
}
},
"node_modules/gulp-sourcemaps": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz",
"integrity": "sha512-NjRy6+Qb5K1xbwOvPviD3uA4KSq2zsalPL+4vxPQPuL+kKzHjXJL10/kLaESic3LmBto8VIBHr3gIN3F9AjnhA==",
"dependencies": {
"convert-source-map": "^1.1.1",
"graceful-fs": "^4.1.2",
"strip-bom": "^2.0.0",
"through2": "^2.0.0",
"vinyl": "^1.0.0"
}
},
"node_modules/gulp-sourcemaps/node_modules/strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
"dependencies": {
"is-utf8": "^0.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-sourcemaps/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/gulp-util": {
"version": "3.0.8",
"resolved": "https://registry.npmjs.org/gulp-util/-/gulp-util-3.0.8.tgz",
"integrity": "sha512-q5oWPc12lwSFS9h/4VIjG+1NuNDlJ48ywV2JKItY4Ycc/n1fXJeYPVQsfu5ZrhQi7FGSDBalwUCLar/GyHXKGw==",
"deprecated": "gulp-util is deprecated - replace it, following the guidelines at https://medium.com/gulpjs/gulp-util-ca3b1f9f9ac5",
"dependencies": {
"array-differ": "^1.0.0",
"array-uniq": "^1.0.2",
"beeper": "^1.0.0",
"chalk": "^1.0.0",
"dateformat": "^2.0.0",
"fancy-log": "^1.1.0",
"gulplog": "^1.0.0",
"has-gulplog": "^0.1.0",
"lodash._reescape": "^3.0.0",
"lodash._reevaluate": "^3.0.0",
"lodash._reinterpolate": "^3.0.0",
"lodash.template": "^3.0.0",
"minimist": "^1.1.0",
"multipipe": "^0.1.2",
"object-assign": "^3.0.0",
"replace-ext": "0.0.1",
"through2": "^2.0.0",
"vinyl": "^0.5.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/gulp-util/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-util/node_modules/ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-util/node_modules/chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"dependencies": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-util/node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/gulp-util/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/gulp-util/node_modules/object-assign": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz",
"integrity": "sha512-jHP15vXVGeVh1HuaA2wY6lxk+whK/x4KBG88VXeRma7CCun7iGD5qPc4eYykQ9sdQvg8jkwFKsSxHln2ybW3xQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-util/node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/gulp-util/node_modules/supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/gulp-util/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/gulp-util/node_modules/vinyl": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.5.3.tgz",
"integrity": "sha512-P5zdf3WB9uzr7IFoVQ2wZTmUwHL8cMZWJGzLBNCHNZ3NB6HTMsYABtt7z8tAGIINLXyAob9B9a1yzVGMFOYKEA==",
"dependencies": {
"clone": "^1.0.0",
"clone-stats": "^0.0.1",
"replace-ext": "0.0.1"
},
"engines": {
"node": ">= 0.9"
}
},
"node_modules/gulplog": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/gulplog/-/gulplog-1.0.0.tgz",
"integrity": "sha512-hm6N8nrm3Y08jXie48jsC55eCZz9mnb4OirAStEk2deqeyhXU3C1otDVh+ccttMuc1sBi6RX6ZJ720hs9RCvgw==",
"dependencies": {
"glogg": "^1.0.0"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/handlebars": {
"version": "4.7.8",
"resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
"integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
"peer": true,
"dependencies": {
"minimist": "^1.2.5",
"neo-async": "^2.6.2",
"source-map": "^0.6.1",
"wordwrap": "^1.0.0"
},
"bin": {
"handlebars": "bin/handlebars"
},
"engines": {
"node": ">=0.4.7"
},
"optionalDependencies": {
"uglify-js": "^3.1.4"
}
},
"node_modules/har-schema": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
"integrity": "sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
"engines": {
"node": ">=4"
}
},
"node_modules/har-validator": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
"integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
"deprecated": "this library is no longer supported",
"dependencies": {
"ajv": "^6.12.3",
"har-schema": "^2.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/has-ansi": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/has-ansi/-/has-ansi-2.0.0.tgz",
"integrity": "sha512-C8vBJ8DwUCx19vhm7urhTuUsr4/IyP6l4VzNQDv+ryHQObW3TTTp9yB68WpYgRe2bbaGuZ/se74IqFeVnMnLZg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/has-ansi/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
"engines": {
"node": ">=8"
}
},
"node_modules/has-gulplog": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/has-gulplog/-/has-gulplog-0.1.0.tgz",
"integrity": "sha512-+F4GzLjwHNNDEAJW2DC1xXfEoPkRDmUdJ7CBYw4MpqtDwOnqdImJl7GWlpqx+Wko6//J8uKTnIe4wZSv7yCqmw==",
"dependencies": {
"sparkles": "^1.0.0"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/has-property-descriptors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
"dependencies": {
"es-define-property": "^1.0.0"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
"integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/has-tostringtag": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
"integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
"dependencies": {
"has-symbols": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/hasha": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/hasha/-/hasha-5.2.2.tgz",
"integrity": "sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ==",
"dev": true,
"dependencies": {
"is-stream": "^2.0.0",
"type-fest": "^0.8.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hasha/node_modules/is-stream": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hasha/node_modules/type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/hasown": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
"dependencies": {
"function-bind": "^1.1.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/he": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
"integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
"bin": {
"he": "bin/he"
}
},
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
"peer": true,
"engines": {
"node": "*"
}
},
"node_modules/hoek": {
"version": "6.1.3",
"resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz",
"integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==",
"deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.",
"peer": true
},
"node_modules/hookable": {
"version": "5.5.3",
"resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz",
"integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ=="
},
"node_modules/html-escaper": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
"integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
"dev": true
},
"node_modules/html-minifier": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-4.0.0.tgz",
"integrity": "sha512-aoGxanpFPLg7MkIl/DDFYtb0iWz7jMFGqFhvEDZga6/4QTjneiD8I/NXL1x5aaoCp7FSIT6h/OhykDdPsbtMig==",
"peer": true,
"dependencies": {
"camel-case": "^3.0.0",
"clean-css": "^4.2.1",
"commander": "^2.19.0",
"he": "^1.2.0",
"param-case": "^2.1.1",
"relateurl": "^0.2.7",
"uglify-js": "^3.5.1"
},
"bin": {
"html-minifier": "cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/htmlparser2": {
"version": "8.0.2",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz",
"integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.0.1",
"entities": "^4.4.0"
}
},
"node_modules/htmlparser2/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/http-assert": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/http-assert/-/http-assert-1.5.0.tgz",
"integrity": "sha512-uPpH7OKX4H25hBmU6G1jWNaqJGpTXxey+YOUizJUAgu0AjLUeC8D73hTrhvDS5D+GJN1DN1+hhc/eF/wpxtp0w==",
"peer": true,
"dependencies": {
"deep-equal": "~1.0.1",
"http-errors": "~1.8.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/http-assert/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/http-assert/node_modules/http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/http-assert/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/http-errors": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
"dependencies": {
"depd": "2.0.0",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": "2.0.1",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/http-signature": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
"integrity": "sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
"dependencies": {
"assert-plus": "^1.0.0",
"jsprim": "^1.2.2",
"sshpk": "^1.7.0"
},
"engines": {
"node": ">=0.8",
"npm": ">=1.3.7"
}
},
"node_modules/husky": {
"version": "9.1.7",
"resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
"integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
"bin": {
"husky": "bin.js"
},
"engines": {
"node": ">=18"
},
"funding": {
"url": "https://github.com/sponsors/typicode"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true
},
"node_modules/ignore": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
"integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
"engines": {
"node": ">= 4"
}
},
"node_modules/import-fresh": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
"engines": {
"node": ">=0.8.19"
}
},
"node_modules/indent-string": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
"integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/inflation": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/inflation/-/inflation-2.1.0.tgz",
"integrity": "sha512-t54PPJHG1Pp7VQvxyVCJ9mBbjG3Hqryges9bXoOO6GExCPa+//i/d5GSuFtpx3ALLd7lgIAur6zrIlBQyJuMlQ==",
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
}
},
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
},
"node_modules/ini": {
"version": "1.3.8",
"resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
"integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew=="
},
"node_modules/interpret": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz",
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"peer": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/is-absolute": {
"version": "0.1.7",
"resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz",
"integrity": "sha512-Xi9/ZSn4NFapG8RP98iNPMOeaV3mXPisxKxzKtHVqr3g56j/fBn+yZmnxSVAA8lmZbl2J9b/a4kJvfU3hqQYgA==",
"dependencies": {
"is-relative": "^0.1.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
"dependencies": {
"binary-extensions": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/is-buffer": {
"version": "1.1.6",
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
"integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
},
"node_modules/is-bzip2": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz",
"integrity": "sha512-v5DA9z/rmk4UdJtb3N1jYqjvCA5roRVf5Q6vprHOcF6U/98TmAJ/AvbPeRMEOYWDW4eMr/pJj5Fnfe0T2wL1Bg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-callable": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
"integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-core-module": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"peer": true,
"dependencies": {
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-dotfile": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-dotfile/-/is-dotfile-1.0.3.tgz",
"integrity": "sha512-9YclgOGtN/f8zx0Pr4FQYMdibBiTaH3sn52vjYip4ZSf6C4/6RfTEZ+MR4GvKhCxdPh21Bg42/WL55f6KSnKpg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-equal-shallow": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-equal-shallow/-/is-equal-shallow-0.1.3.tgz",
"integrity": "sha512-0EygVC5qPvIyb+gSz7zdD5/AAoS6Qrx1e//6N4yv4oNm30kqvdmG66oZFWVlQHUWe5OjP08FuTw2IdT0EOTcYA==",
"dependencies": {
"is-primitive": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-extendable": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
"integrity": "sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
"integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-fullwidth-code-point": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
"integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
"engines": {
"node": ">=8"
}
},
"node_modules/is-generator-function": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.0.tgz",
"integrity": "sha512-nPUB5km40q9e8UfN/Zc24eLlzdSf9OfKByBw9CIdw4H1giPMeA0OIJvbchsCu4npfI2QcMVBsGEBHKZ7wLTWmQ==",
"peer": true,
"dependencies": {
"call-bound": "^1.0.3",
"get-proto": "^1.0.0",
"has-tostringtag": "^1.0.2",
"safe-regex-test": "^1.1.0"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-glob": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
"dependencies": {
"is-extglob": "^2.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-gzip": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz",
"integrity": "sha512-rcfALRIb1YewtnksfRIHGcIY93QnK8BIQ/2c9yDYcG/Y6+vRoJuTWBmmSEbyLLYtXm7q35pHOHbZFQBaLrhlWQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-natural-number": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz",
"integrity": "sha512-88gG/Fur5/8RkhB6UonqOuwQfNJvuaDStW/+r6oIB/hOQPUQe7DiiDQq0fitGOnARt+mQl/S6rg6Vku+i0sA4w=="
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
"engines": {
"node": ">=0.12.0"
}
},
"node_modules/is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-plain-obj": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
"integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-posix-bracket": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz",
"integrity": "sha512-Yu68oeXJ7LeWNmZ3Zov/xg/oDBnBK2RNxwYY1ilNJX+tKKZqgPK+qOn/Gs9jEu66KDY9Netf5XLKNGzas/vPfQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-primitive": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-primitive/-/is-primitive-2.0.0.tgz",
"integrity": "sha512-N3w1tFaRfk3UrPfqeRyD+GYDASU3W5VinKhlORy8EWVf/sIdDL9GAcew85XmktCfH+ngG7SRXEVDoO18WMdB/Q==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-redirect": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
"integrity": "sha512-cr/SlUEe5zOGmzvj9bUyC4LVvkNVAXu4GytXLNMr1pny+a65MpQ9IJzFHD5vi7FyJgb4qt27+eS3TuQnqB+RQw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-regex": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
"integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2",
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-relative": {
"version": "0.1.3",
"resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz",
"integrity": "sha512-wBOr+rNM4gkAZqoLRJI4myw5WzzIdQosFAAbnvfXP5z1LyzgAI3ivOKehC5KfqlQJZoihVhirgtCBj378Eg8GA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-retry-allowed": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.2.0.tgz",
"integrity": "sha512-RUbUeKwvm3XG2VYamhJL1xFktgjvPzL0Hq8C+6yrWIswDy3BIXGqCxhxkc30N9jqK311gVU137K8Ei55/zVJRg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-tar": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz",
"integrity": "sha512-8sR603bS6APKxcdkQ1e5rAC9JDCxM3OlbGJDWv5ajhHqIh6cTaqcpeOTch1iIeHYY4nHEFTgmCiGSLfvmODH4w==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-typed-array": {
"version": "1.1.15",
"resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
"integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
"dependencies": {
"which-typed-array": "^1.1.16"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-typedarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
"integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA=="
},
"node_modules/is-unicode-supported": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
"integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-url": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz",
"integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww=="
},
"node_modules/is-utf8": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz",
"integrity": "sha512-rMYPYvCzsXywIsldgLaSoPlw5PfoB/ssr7hY4pLfcodrA5M/eArza1a9VmTiNIBNMjOGr1Ow9mTyU2o69U6U9Q=="
},
"node_modules/is-valid-glob": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz",
"integrity": "sha512-CvG8EtJZ8FyzVOGPzrDorzyN65W1Ld8BVnqshRCah6pFIsprGx3dKgFtjLn/Vw9kGqR4OlR84U7yhT9ZVTyWIQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-what": {
"version": "4.1.16",
"resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz",
"integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==",
"engines": {
"node": ">=12.13"
},
"funding": {
"url": "https://github.com/sponsors/mesqueeb"
}
},
"node_modules/is-windows": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
"integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/is-zip": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz",
"integrity": "sha512-aym/dLqHZVMW/+bbNrA/eTeWTyW4fE6koLSoFSsM2GF3/pho7aPCcmHFWFLvzHu7MDuf67domYn36GDwU/cJkQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/isarray": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
"integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
},
"node_modules/isobject": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
"integrity": "sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
"dependencies": {
"isarray": "1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/isstream": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
"integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g=="
},
"node_modules/istanbul-lib-coverage": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-hook": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz",
"integrity": "sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ==",
"dev": true,
"dependencies": {
"append-transform": "^2.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-instrument": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-4.0.3.tgz",
"integrity": "sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==",
"dev": true,
"dependencies": {
"@babel/core": "^7.7.5",
"@istanbuljs/schema": "^0.1.2",
"istanbul-lib-coverage": "^3.0.0",
"semver": "^6.3.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-instrument/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/istanbul-lib-processinfo": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz",
"integrity": "sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg==",
"dev": true,
"dependencies": {
"archy": "^1.0.0",
"cross-spawn": "^7.0.3",
"istanbul-lib-coverage": "^3.2.0",
"p-map": "^3.0.0",
"rimraf": "^3.0.0",
"uuid": "^8.3.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-processinfo/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"dev": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/istanbul-lib-report": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
"integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
"dev": true,
"dependencies": {
"istanbul-lib-coverage": "^3.0.0",
"make-dir": "^4.0.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/istanbul-lib-report/node_modules/make-dir": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
"integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
"dev": true,
"dependencies": {
"semver": "^7.5.3"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/istanbul-lib-report/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/istanbul-lib-source-maps": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
"integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
"dev": true,
"dependencies": {
"debug": "^4.1.1",
"istanbul-lib-coverage": "^3.0.0",
"source-map": "^0.6.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/istanbul-reports": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
"integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
"dev": true,
"dependencies": {
"html-escaper": "^2.0.0",
"istanbul-lib-report": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/jackspeak": {
"version": "3.4.3",
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
"integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
"peer": true,
"dependencies": {
"@isaacs/cliui": "^8.0.2"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
},
"optionalDependencies": {
"@pkgjs/parseargs": "^0.11.0"
}
},
"node_modules/js-beautify": {
"version": "1.15.4",
"resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.15.4.tgz",
"integrity": "sha512-9/KXeZUKKJwqCXUdBxFJ3vPh467OCckSBmYDwSK/EtV090K+iMJ7zx2S3HLVDIWFQdqMIsZWbnaGiba18aWhaA==",
"peer": true,
"dependencies": {
"config-chain": "^1.1.13",
"editorconfig": "^1.0.4",
"glob": "^10.4.2",
"js-cookie": "^3.0.5",
"nopt": "^7.2.1"
},
"bin": {
"css-beautify": "js/bin/css-beautify.js",
"html-beautify": "js/bin/html-beautify.js",
"js-beautify": "js/bin/js-beautify.js"
},
"engines": {
"node": ">=14"
}
},
"node_modules/js-beautify/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"peer": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/js-beautify/node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"peer": true,
"dependencies": {
"cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-beautify/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"peer": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-beautify/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"peer": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-beautify/node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"peer": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/js-convert-case": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/js-convert-case/-/js-convert-case-4.2.0.tgz",
"integrity": "sha512-i4mHCxiBNj6ajjMnZnC70qAOMA8gb+YgYipy2VR7a+Q5EBgEQ2/SgSAUBdNEyObk++B4AIUiFWeDEX2ggOd8cQ=="
},
"node_modules/js-cookie": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/js-cookie/-/js-cookie-3.0.5.tgz",
"integrity": "sha512-cEiJEAEoIbWfCZYKWhVwFuvPX1gETRYPw6LlaTKoxD3s2AkXzkCjnp6h0V77ozyqj0jakteJ4YqDJT830+lVGw==",
"peer": true,
"engines": {
"node": ">=14"
}
},
"node_modules/js-tokens": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
"integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==",
"dev": true
},
"node_modules/js-yaml": {
"version": "3.14.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
"integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
"dev": true,
"dependencies": {
"argparse": "^1.0.7",
"esprima": "^4.0.0"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/jsbn": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
"integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg=="
},
"node_modules/jsesc": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
"node": ">=6"
}
},
"node_modules/json-buffer": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
"integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-schema": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
"integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA=="
},
"node_modules/json-schema-traverse": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
"integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
},
"node_modules/json-stable-stringify-without-jsonify": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
"integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw=="
},
"node_modules/json-stringify-safe": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
"integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA=="
},
"node_modules/json5": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"bin": {
"json5": "lib/cli.js"
},
"engines": {
"node": ">=6"
}
},
"node_modules/jsonfile": {
"version": "2.4.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-2.4.0.tgz",
"integrity": "sha512-PKllAqbgLgxHaj8TElYymKCAgrASebJrWpTnEkOaTowt23VKXXN0sUeriJ+eh7y6ufb/CC5ap11pz71/cM0hUw==",
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/jsprim": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
"integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
"dependencies": {
"assert-plus": "1.0.0",
"extsprintf": "1.3.0",
"json-schema": "0.4.0",
"verror": "1.10.0"
},
"engines": {
"node": ">=0.6.0"
}
},
"node_modules/juice": {
"version": "10.0.1",
"resolved": "https://registry.npmjs.org/juice/-/juice-10.0.1.tgz",
"integrity": "sha512-ZhJT1soxJCkOiO55/mz8yeBKTAJhRzX9WBO+16ZTqNTONnnVlUPyVBIzQ7lDRjaBdTbid+bAnyIon/GM3yp4cA==",
"peer": true,
"dependencies": {
"cheerio": "1.0.0-rc.12",
"commander": "^6.1.0",
"mensch": "^0.3.4",
"slick": "^1.12.2",
"web-resource-inliner": "^6.0.1"
},
"bin": {
"juice": "bin/juice"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/juice/node_modules/commander": {
"version": "6.2.1",
"resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
"integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
"peer": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/keygrip": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
"integrity": "sha512-iYSchDJ+liQ8iwbSI2QqsQOvqv58eJCEanyJPJi+Khyu8smkcKSFUCbPwzFcL7YVtZ6eONjqRX/38caJ7QjRAQ==",
"peer": true,
"dependencies": {
"tsscmp": "1.0.6"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/keyv": {
"version": "4.5.4",
"resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
"integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"json-buffer": "3.0.1"
}
},
"node_modules/kind-of": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
"integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
"dependencies": {
"is-buffer": "^1.1.5"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/klaw": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
"integrity": "sha512-TED5xi9gGQjGpNnvRWknrwAB1eL5GciPfVFOt3Vk1OJCVDQbzuSfrF3hkUQKlsgKrG1F+0t5W0m+Fje1jIt8rw==",
"optionalDependencies": {
"graceful-fs": "^4.1.9"
}
},
"node_modules/kleur": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
"integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
"engines": {
"node": ">=6"
}
},
"node_modules/koa": {
"version": "2.16.2",
"resolved": "https://registry.npmjs.org/koa/-/koa-2.16.2.tgz",
"integrity": "sha512-+CCssgnrWKx9aI3OeZwroa/ckG4JICxvIFnSiOUyl2Uv+UTI+xIw0FfFrWS7cQFpoePpr9o8csss7KzsTzNL8Q==",
"peer": true,
"dependencies": {
"accepts": "^1.3.5",
"cache-content-type": "^1.0.0",
"content-disposition": "~0.5.2",
"content-type": "^1.0.4",
"cookies": "~0.9.0",
"debug": "^4.3.2",
"delegates": "^1.0.0",
"depd": "^2.0.0",
"destroy": "^1.0.4",
"encodeurl": "^1.0.2",
"escape-html": "^1.0.3",
"fresh": "~0.5.2",
"http-assert": "^1.3.0",
"http-errors": "^1.6.3",
"is-generator-function": "^1.0.7",
"koa-compose": "^4.1.0",
"koa-convert": "^2.0.0",
"on-finished": "^2.3.0",
"only": "~0.0.2",
"parseurl": "^1.3.2",
"statuses": "^1.5.0",
"type-is": "^1.6.16",
"vary": "^1.1.2"
},
"engines": {
"node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
}
},
"node_modules/koa-body": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-body/-/koa-body-5.0.0.tgz",
"integrity": "sha512-nHwEODrQGiyKBILCWO8QSS40C87cKr2cp3y/Cw8u9Z8w5t0CdSkGm3+y9WK5BIAlPpo9tTw5RtSbxpVyG79vmw==",
"dev": true,
"dependencies": {
"@types/formidable": "^2.0.4",
"co-body": "^5.1.1",
"formidable": "^2.0.1"
}
},
"node_modules/koa-compose": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/koa-compose/-/koa-compose-4.1.0.tgz",
"integrity": "sha512-8ODW8TrDuMYvXRwra/Kh7/rJo9BtOfPc6qO8eAfC80CnCvSjSl0bkRM24X6/XBBEyj0v1nRUQ1LyOy3dbqOWXw=="
},
"node_modules/koa-convert": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/koa-convert/-/koa-convert-2.0.0.tgz",
"integrity": "sha512-asOvN6bFlSnxewce2e/DK3p4tltyfC4VM7ZwuTuepI7dEQVcvpyFuBcEARu1+Hxg8DIwytce2n7jrZtRlPrARA==",
"peer": true,
"dependencies": {
"co": "^4.6.0",
"koa-compose": "^4.1.0"
},
"engines": {
"node": ">= 10"
}
},
"node_modules/koa-mount": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/koa-mount/-/koa-mount-4.2.0.tgz",
"integrity": "sha512-2iHQc7vbA9qLeVq5gKAYh3m5DOMMlMfIKjW/REPAS18Mf63daCJHHVXY9nbu7ivrnYn5PiPC4CE523Tf5qvjeQ==",
"peer": true,
"dependencies": {
"debug": "^4.0.1",
"koa-compose": "^4.1.0"
},
"engines": {
"node": ">= 7.6.0"
}
},
"node_modules/koa-qs": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/koa-qs/-/koa-qs-3.0.0.tgz",
"integrity": "sha512-05IB5KirwMs3heWW26iTz46HuMAtrlrRMus/aNH1BRDocLyF/099EtCB0MIfQpRuT0TISvaTsWwSy2gctIWiGA==",
"peer": true,
"dependencies": {
"merge-descriptors": "^1.0.1",
"qs": "^6.9.4"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/koa-responsive-image-router": {
"version": "0.2.37",
"resolved": "https://registry.npmjs.org/koa-responsive-image-router/-/koa-responsive-image-router-0.2.37.tgz",
"integrity": "sha512-JEjQv7VFCSwF/NqwTsGVsbg8e1MaiEHLaw3vwyRABsJHExJftzNQqcd8cFUXEzgOz/+GpwJOUQRNCi6c+lFfwg==",
"peer": true,
"dependencies": {
"@koa/router": "^10.0.0",
"@sealcode/ts-predicates": "^0.5.3",
"@types/mocha": "^9.0.0",
"better-queue": "^3.8.12",
"filru": "^2.1.0",
"koa": "^2.13.1",
"koa-router": "^10.0.0",
"locreq": "^2.4.1",
"lru-cache": "^10.0.1",
"multiple-scripts-tmux": "^1.1.2",
"node-cache": "^5.1.2",
"object-fit-math": "^1.0.0",
"object-hash": "^3.0.0",
"pick-port": "^2.1.0",
"sharp": "^0.32.5",
"smartcrop-sharp": "^2.0.8"
},
"engines": {
"node": ">=21.0.0"
}
},
"node_modules/koa-responsive-image-router/node_modules/@koa/router": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/@koa/router/-/router-10.1.1.tgz",
"integrity": "sha512-ORNjq5z4EmQPriKbR0ER3k4Gh7YGNhWDL7JBW+8wXDrHLbWYKYSJaOJ9aN06npF5tbTxe2JBOsurpJDAvjiXKw==",
"deprecated": "**IMPORTANT 10x+ PERFORMANCE UPGRADE**: Please upgrade to v12.0.1+ as we have fixed an issue with debuglog causing 10x slower router benchmark performance, see https://github.com/koajs/router/pull/173",
"peer": true,
"dependencies": {
"debug": "^4.1.1",
"http-errors": "^1.7.3",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.1.0"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/koa-responsive-image-router/node_modules/@sealcode/ts-predicates": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.5.3.tgz",
"integrity": "sha512-EZI7e8EY8gI1pw2bKdevjl+fBJbcSlpNkCZ8XoEOV3cHakPujiT6M4l775RDkfxJSbLX7jhOBkhgPNDfmCpZbg==",
"peer": true
},
"node_modules/koa-responsive-image-router/node_modules/@types/mocha": {
"version": "9.1.1",
"resolved": "https://registry.npmjs.org/@types/mocha/-/mocha-9.1.1.tgz",
"integrity": "sha512-Z61JK7DKDtdKTWwLeElSEBcWGRLY8g95ic5FoQqI9CMx0ns/Ghep3B4DfcEimiKMvtamNVULVNKEsiwV3aQmXw==",
"peer": true
},
"node_modules/koa-responsive-image-router/node_modules/@types/node": {
"version": "14.18.63",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
"integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
"peer": true
},
"node_modules/koa-responsive-image-router/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-responsive-image-router/node_modules/http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-responsive-image-router/node_modules/locreq": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/locreq/-/locreq-2.4.1.tgz",
"integrity": "sha512-Itfhlus87Q9GcQKEK5LXZngD5YpUbANC9mr5UFghLSBIg6gVVG21AWX45+JVyaqBxILQkB+dBW0i2KlSVzGfeQ==",
"peer": true,
"dependencies": {
"@types/node": "^14.14.16"
}
},
"node_modules/koa-responsive-image-router/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-router": {
"version": "10.1.1",
"resolved": "https://registry.npmjs.org/koa-router/-/koa-router-10.1.1.tgz",
"integrity": "sha512-z/OzxVjf5NyuNO3t9nJpx7e1oR3FSBAauiwXtMQu4ppcnuNZzTaQ4p21P8A6r2Es8uJJM339oc4oVW+qX7SqnQ==",
"deprecated": "Please use @koa/router instead, starting from v9! ",
"peer": true,
"dependencies": {
"debug": "^4.1.1",
"http-errors": "^1.7.3",
"koa-compose": "^4.1.0",
"methods": "^1.1.2",
"path-to-regexp": "^6.1.0"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/koa-router/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-router/node_modules/http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-router/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-send": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/koa-send/-/koa-send-5.0.1.tgz",
"integrity": "sha512-tmcyQ/wXXuxpDxyNXv5yNNkdAMdFRqwtegBXUaowiQzUKqJehttS0x2j0eOZDQAyloAth5w6wwBImnFzkUz3pQ==",
"peer": true,
"dependencies": {
"debug": "^4.1.1",
"http-errors": "^1.7.3",
"resolve-path": "^1.4.0"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/koa-send/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-send/node_modules/http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-send/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa-static": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/koa-static/-/koa-static-5.0.0.tgz",
"integrity": "sha512-UqyYyH5YEXaJrf9S8E23GoJFQZXkBVJ9zYYMPGz919MSX1KuvAcycIuS0ci150HCoPf4XQVhQ84Qf8xRPWxFaQ==",
"peer": true,
"dependencies": {
"debug": "^3.1.0",
"koa-send": "^5.0.0"
},
"engines": {
"node": ">= 7.6.0"
}
},
"node_modules/koa-static/node_modules/debug": {
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
"peer": true,
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/koa/node_modules/http-errors": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
"integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.4",
"setprototypeof": "1.2.0",
"statuses": ">= 1.5.0 < 2",
"toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa/node_modules/http-errors/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/koa/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/lazystream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz",
"integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==",
"dependencies": {
"readable-stream": "^2.0.5"
},
"engines": {
"node": ">= 0.6.3"
}
},
"node_modules/levn": {
"version": "0.4.1",
"resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
"integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
"dev": true,
"dependencies": {
"prelude-ls": "^1.2.1",
"type-check": "~0.4.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/locate-path": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
"integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
"dependencies": {
"p-locate": "^5.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/locreq": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/locreq/-/locreq-3.0.0.tgz",
"integrity": "sha512-5j8CNJl9uF7drtA7CInWbKzoFnC9KuDu1jX2KldaKL5MY+9nfP/8veyWtc5ep5156vMybNt3ACxK643IVcgKUQ==",
"dependencies": {
"@types/node": "^16"
},
"engines": {
"node": ">=17.0.0"
}
},
"node_modules/locreq/node_modules/@types/node": {
"version": "16.18.126",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.126.tgz",
"integrity": "sha512-OTcgaiwfGFBKacvfwuHzzn1KLxH/er8mluiy8/uM3sGXHaRe73RrSIj01jow9t4kJEW633Ov+cOexXeiApTyAw=="
},
"node_modules/lodash": {
"version": "4.17.21",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
"peer": true
},
"node_modules/lodash._basecopy": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash._basecopy/-/lodash._basecopy-3.0.1.tgz",
"integrity": "sha512-rFR6Vpm4HeCK1WPGvjZSJ+7yik8d8PVUdCJx5rT2pogG4Ve/2ZS7kfmO5l5T2o5V2mqlNIfSF5MZlr1+xOoYQQ=="
},
"node_modules/lodash._basetostring": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash._basetostring/-/lodash._basetostring-3.0.1.tgz",
"integrity": "sha512-mTzAr1aNAv/i7W43vOR/uD/aJ4ngbtsRaCubp2BfZhlGU/eORUjg/7F6X0orNMdv33JOrdgGybtvMN/po3EWrA=="
},
"node_modules/lodash._basevalues": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._basevalues/-/lodash._basevalues-3.0.0.tgz",
"integrity": "sha512-H94wl5P13uEqlCg7OcNNhMQ8KvWSIyqXzOPusRgHC9DK3o54P6P3xtbXlVbRABG4q5gSmp7EDdJ0MSuW9HX6Mg=="
},
"node_modules/lodash._getnative": {
"version": "3.9.1",
"resolved": "https://registry.npmjs.org/lodash._getnative/-/lodash._getnative-3.9.1.tgz",
"integrity": "sha512-RrL9VxMEPyDMHOd9uFbvMe8X55X16/cGM5IgOKgRElQZutpX89iS6vwl64duTV1/16w5JY7tuFNXqoekmh1EmA=="
},
"node_modules/lodash._isiterateecall": {
"version": "3.0.9",
"resolved": "https://registry.npmjs.org/lodash._isiterateecall/-/lodash._isiterateecall-3.0.9.tgz",
"integrity": "sha512-De+ZbrMu6eThFti/CSzhRvTKMgQToLxbij58LMfM8JnYDNSOjkjTCIaa8ixglOeGh2nyPlakbt5bJWJ7gvpYlQ=="
},
"node_modules/lodash._reescape": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reescape/-/lodash._reescape-3.0.0.tgz",
"integrity": "sha512-Sjlavm5y+FUVIF3vF3B75GyXrzsfYV8Dlv3L4mEpuB9leg8N6yf/7rU06iLPx9fY0Mv3khVp9p7Dx0mGV6V5OQ=="
},
"node_modules/lodash._reevaluate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reevaluate/-/lodash._reevaluate-3.0.0.tgz",
"integrity": "sha512-OrPwdDc65iJiBeUe5n/LIjd7Viy99bKwDdk7Z5ljfZg0uFRFlfQaCy9tZ4YMAag9WAZmlVpe1iZrkIMMSMHD3w=="
},
"node_modules/lodash._reinterpolate": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz",
"integrity": "sha512-xYHt68QRoYGjeeM/XOE1uJtvXQAgvszfBhjV4yvsQH0u2i9I6cI6c6/eG4Hh3UAOVn0y/xAXwmTzEay49Q//HA=="
},
"node_modules/lodash._root": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/lodash._root/-/lodash._root-3.0.1.tgz",
"integrity": "sha512-O0pWuFSK6x4EXhM1dhZ8gchNtG7JMqBtrHdoUFUWXD7dJnNSUze1GuyQr5sOs0aCvgGeI3o/OJW8f4ca7FDxmQ=="
},
"node_modules/lodash.escape": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-3.2.0.tgz",
"integrity": "sha512-n1PZMXgaaDWZDSvuNZ/8XOcYO2hOKDqZel5adtR30VKQAtoWs/5AOeFA0vPV8moiPzlqe7F4cP2tzpFewQyelQ==",
"dependencies": {
"lodash._root": "^3.0.0"
}
},
"node_modules/lodash.flattendeep": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
"integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
"dev": true
},
"node_modules/lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
},
"node_modules/lodash.isarray": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/lodash.isarray/-/lodash.isarray-3.0.4.tgz",
"integrity": "sha512-JwObCrNJuT0Nnbuecmqr5DgtuBppuCvGD9lxjFpAzwnVtdGoDQ1zig+5W8k5/6Gcn0gZ3936HDAlGd28i7sOGQ=="
},
"node_modules/lodash.isequal": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
"integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
"deprecated": "This package is deprecated. Use require('node:util').isDeepStrictEqual instead."
},
"node_modules/lodash.keys": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/lodash.keys/-/lodash.keys-3.1.2.tgz",
"integrity": "sha512-CuBsapFjcubOGMn3VD+24HOAPxM79tH+V6ivJL3CHYjtrawauDJHUk//Yew9Hvc6e9rbCrURGk8z6PC+8WJBfQ==",
"dependencies": {
"lodash._getnative": "^3.0.0",
"lodash.isarguments": "^3.0.0",
"lodash.isarray": "^3.0.0"
}
},
"node_modules/lodash.merge": {
"version": "4.6.2",
"resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
"integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
"dev": true
},
"node_modules/lodash.restparam": {
"version": "3.6.1",
"resolved": "https://registry.npmjs.org/lodash.restparam/-/lodash.restparam-3.6.1.tgz",
"integrity": "sha512-L4/arjjuq4noiUJpt3yS6KIKDtJwNe2fIYgMqyYYKoeIfV1iEqvPwhCx23o+R9dzouGihDAPN1dTIRWa7zk8tw=="
},
"node_modules/lodash.template": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/lodash.template/-/lodash.template-3.6.2.tgz",
"integrity": "sha512-0B4Y53I0OgHUJkt+7RmlDFWKjVAI/YUpWNiL9GQz5ORDr4ttgfQGo+phBWKFLJbBdtOwgMuUkdOHOnPg45jKmQ==",
"deprecated": "This package is deprecated. Use https://socket.dev/npm/package/eta instead.",
"dependencies": {
"lodash._basecopy": "^3.0.0",
"lodash._basetostring": "^3.0.0",
"lodash._basevalues": "^3.0.0",
"lodash._isiterateecall": "^3.0.0",
"lodash._reinterpolate": "^3.0.0",
"lodash.escape": "^3.0.0",
"lodash.keys": "^3.0.0",
"lodash.restparam": "^3.0.0",
"lodash.templatesettings": "^3.0.0"
}
},
"node_modules/lodash.templatesettings": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/lodash.templatesettings/-/lodash.templatesettings-3.1.1.tgz",
"integrity": "sha512-TcrlEr31tDYnWkHFWDCV3dHYroKEXpJZ2YJYvJdhN+y4AkWMDZ5I4I8XDtUKqSAyG81N7w+I1mFEJtcED+tGqQ==",
"dependencies": {
"lodash._reinterpolate": "^3.0.0",
"lodash.escape": "^3.0.0"
}
},
- "node_modules/lodash.truncate": {
- "version": "4.4.2",
- "resolved": "https://registry.npmjs.org/lodash.truncate/-/lodash.truncate-4.4.2.tgz",
- "integrity": "sha512-jttmRe7bRse52OsWIMDLaXxWqRAmtIUccAQ3garviCqJjafXOfNMO0yMfNpdD6zbGaTU0P5Nz7e7gAT6cKmJRw==",
- "dev": true
- },
"node_modules/log-symbols": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
"integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
"dependencies": {
"chalk": "^4.1.0",
"is-unicode-supported": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/log-symbols/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/log-symbols/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/lower-case": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
"integrity": "sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
"peer": true
},
"node_modules/lowercase-keys": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz",
"integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/lru-cache": {
"version": "10.4.3",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
"integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
"peer": true
},
"node_modules/lunr": {
"version": "2.3.9",
"resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz",
"integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==",
"peer": true
},
"node_modules/luxon": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/luxon/-/luxon-3.3.0.tgz",
"integrity": "sha512-An0UCfG/rSiqtAIiBPO0Y9/zAnHUZxAMiCpTd5h2smgsj7GGmcenvrvww2cqNA8/4A5ZrD1gJpHN2mIHZQF+Mg==",
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
"dependencies": {
"semver": "^6.0.0"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/make-dir/node_modules/semver": {
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
"dev": true,
"bin": {
"semver": "bin/semver.js"
}
},
"node_modules/make-error": {
"version": "1.3.6",
"resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
"integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
"dev": true
},
"node_modules/marked": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/marked/-/marked-1.0.0.tgz",
"integrity": "sha512-Wo+L1pWTVibfrSr+TTtMuiMfNzmZWiOPeO7rZsQUY5bgsxpHesBEcIWJloWVTFnrMXnf/TL30eTFSGJddmQAng==",
"peer": true,
"bin": {
"marked": "bin/marked"
},
"engines": {
"node": ">= 8.16.2"
}
},
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
"integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/math-random": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
},
"node_modules/md5": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
"integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
"dependencies": {
"charenc": "0.0.2",
"crypt": "0.0.2",
"is-buffer": "~1.1.6"
}
},
"node_modules/mdurl": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/mdurl/-/mdurl-1.0.1.tgz",
"integrity": "sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==",
"peer": true
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"peer": true
},
"node_modules/mensch": {
"version": "0.3.4",
"resolved": "https://registry.npmjs.org/mensch/-/mensch-0.3.4.tgz",
"integrity": "sha512-IAeFvcOnV9V0Yk+bFhYR07O3yNina9ANIN5MoXBKYJ/RLYPurd2d0yw14MDhpr9/momp0WofT1bPUh3hkzdi/g==",
"peer": true
},
"node_modules/merge": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/merge/-/merge-2.1.1.tgz",
"integrity": "sha512-jz+Cfrg9GWOZbQAnDQ4hlVnQky+341Yk5ru8bZSe6sIDTCIg8n9i/u7hSQGSVOF3C7lH6mGtqjkiT9G4wFLL0w=="
},
"node_modules/merge-descriptors": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
"integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
"peer": true,
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/merge-stream": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-1.0.1.tgz",
"integrity": "sha512-e6RM36aegd4f+r8BZCcYXlO2P3H6xbUM6ktL2Xmf45GAOit9bI4z6/3VU7JwllVO1L7u0UDSg/EhzQ5lmMLolA==",
"dependencies": {
"readable-stream": "^2.0.1"
}
},
"node_modules/merge2": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
"integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
"dev": true,
"engines": {
"node": ">= 8"
}
},
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/micromatch": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
"integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
"dev": true,
"dependencies": {
"braces": "^3.0.3",
"picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
"node_modules/mime": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
"integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
"peer": true,
"bin": {
"mime": "cli.js"
},
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/mime-db": {
"version": "1.52.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
"version": "2.1.35",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
"dependencies": {
"mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mimic-response": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
"integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
"peer": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/minimatch": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
"dependencies": {
"brace-expansion": "^1.1.7"
},
"engines": {
"node": "*"
}
},
"node_modules/minimist": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
"version": "7.1.2",
"resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
"integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
"peer": true,
"engines": {
"node": ">=16 || 14 >=14.17"
}
},
"node_modules/mjml": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml/-/mjml-4.15.3.tgz",
"integrity": "sha512-bW2WpJxm6HS+S3Yu6tq1DUPFoTxU9sPviUSmnL7Ua+oVO3WA5ILFWqvujUlz+oeuM+HCwEyMiP5xvKNPENVjYA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"mjml-cli": "4.15.3",
"mjml-core": "4.15.3",
"mjml-migrate": "4.15.3",
"mjml-preset-core": "4.15.3",
"mjml-validator": "4.15.3"
},
"bin": {
"mjml": "bin/mjml"
}
},
"node_modules/mjml-accordion": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-accordion/-/mjml-accordion-4.15.3.tgz",
"integrity": "sha512-LPNVSj1LyUVYT9G1gWwSw3GSuDzDsQCu0tPB2uDsq4VesYNnU6v3iLCQidMiR6azmIt13OEozG700ygAUuA6Ng==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-body": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-body/-/mjml-body-4.15.3.tgz",
"integrity": "sha512-7pfUOVPtmb0wC+oUOn4xBsAw4eT5DyD6xqaxj/kssu6RrFXOXgJaVnDPAI9AzIvXJ/5as9QrqRGYAddehwWpHQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-button": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-button/-/mjml-button-4.15.3.tgz",
"integrity": "sha512-79qwn9AgdGjJR1vLnrcm2rq2AsAZkKC5JPwffTMG+Nja6zGYpTDZFZ56ekHWr/r1b5WxkukcPj2PdevUug8c+Q==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-carousel": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-carousel/-/mjml-carousel-4.15.3.tgz",
"integrity": "sha512-3ju6I4l7uUhPRrJfN3yK9AMsfHvrYbRkcJ1GRphFHzUj37B2J6qJOQUpzA547Y4aeh69TSb7HFVf1t12ejQxVw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-cli": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-cli/-/mjml-cli-4.15.3.tgz",
"integrity": "sha512-+V2TDw3tXUVEptFvLSerz125C2ogYl8klIBRY1m5BHd4JvGVf3yhx8N3PngByCzA6PGcv/eydGQN+wy34SHf0Q==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"chokidar": "^3.0.0",
"glob": "^10.3.10",
"html-minifier": "^4.0.0",
"js-beautify": "^1.6.14",
"lodash": "^4.17.21",
"minimatch": "^9.0.3",
"mjml-core": "4.15.3",
"mjml-migrate": "4.15.3",
"mjml-parser-xml": "4.15.3",
"mjml-validator": "4.15.3",
"yargs": "^17.7.2"
},
"bin": {
"mjml-cli": "bin/mjml"
}
},
"node_modules/mjml-cli/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"peer": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/mjml-cli/node_modules/foreground-child": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.1.tgz",
"integrity": "sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw==",
"peer": true,
"dependencies": {
"cross-spawn": "^7.0.6",
"signal-exit": "^4.0.1"
},
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mjml-cli/node_modules/glob": {
"version": "10.4.5",
"resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
"integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
"peer": true,
"dependencies": {
"foreground-child": "^3.1.0",
"jackspeak": "^3.1.2",
"minimatch": "^9.0.4",
"minipass": "^7.1.2",
"package-json-from-dist": "^1.0.0",
"path-scurry": "^1.11.1"
},
"bin": {
"glob": "dist/esm/bin.mjs"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mjml-cli/node_modules/minimatch": {
"version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"peer": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=16 || 14 >=14.17"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mjml-cli/node_modules/signal-exit": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
"integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
"peer": true,
"engines": {
"node": ">=14"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/mjml-column": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-column/-/mjml-column-4.15.3.tgz",
"integrity": "sha512-hYdEFdJGHPbZJSEysykrevEbB07yhJGSwfDZEYDSbhQQFjV2tXrEgYcFD5EneMaowjb55e3divSJxU4c5q4Qgw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-core": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-core/-/mjml-core-4.15.3.tgz",
"integrity": "sha512-Dmwk+2cgSD9L9GmTbEUNd8QxkTZtW9P7FN/ROZW/fGZD6Hq6/4TB0zEspg2Ow9eYjZXO2ofOJ3PaQEEShKV0kQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"cheerio": "1.0.0-rc.12",
"detect-node": "^2.0.4",
"html-minifier": "^4.0.0",
"js-beautify": "^1.6.14",
"juice": "^10.0.0",
"lodash": "^4.17.21",
"mjml-migrate": "4.15.3",
"mjml-parser-xml": "4.15.3",
"mjml-validator": "4.15.3"
}
},
"node_modules/mjml-divider": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-divider/-/mjml-divider-4.15.3.tgz",
"integrity": "sha512-vh27LQ9FG/01y0b9ntfqm+GT5AjJnDSDY9hilss2ixIUh0FemvfGRfsGVeV5UBVPBKK7Ffhvfqc7Rciob9Spzw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-group": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-group/-/mjml-group-4.15.3.tgz",
"integrity": "sha512-HSu/rKnGZVKFq3ciT46vi1EOy+9mkB0HewO4+P6dP/Y0UerWkN6S3UK11Cxsj0cAp0vFwkPDCdOeEzRdpFEkzA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head/-/mjml-head-4.15.3.tgz",
"integrity": "sha512-o3mRuuP/MB5fZycjD3KH/uXsnaPl7Oo8GtdbJTKtH1+O/3pz8GzGMkscTKa97l03DAG2EhGrzzLcU2A6eshwFw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-attributes": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-attributes/-/mjml-head-attributes-4.15.3.tgz",
"integrity": "sha512-2ISo0r5ZKwkrvJgDou9xVPxxtXMaETe2AsAA02L89LnbB2KC0N5myNsHV0sEysTw9+CfCmgjAb0GAI5QGpxKkQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-breakpoint": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-breakpoint/-/mjml-head-breakpoint-4.15.3.tgz",
"integrity": "sha512-Eo56FA5C2v6ucmWQL/JBJ2z641pLOom4k0wP6CMZI2utfyiJ+e2Uuinj1KTrgDcEvW4EtU9HrfAqLK9UosLZlg==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-font": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-font/-/mjml-head-font-4.15.3.tgz",
"integrity": "sha512-CzV2aDPpiNIIgGPHNcBhgyedKY4SX3BJoTwOobSwZVIlEA6TAWB4Z9WwFUmQqZOgo1AkkiTHPZQvGcEhFFXH6g==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-html-attributes": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-html-attributes/-/mjml-head-html-attributes-4.15.3.tgz",
"integrity": "sha512-MDNDPMBOgXUZYdxhosyrA2kudiGO8aogT0/cODyi2Ed9o/1S7W+je11JUYskQbncqhWKGxNyaP4VWa+6+vUC/g==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-preview": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-preview/-/mjml-head-preview-4.15.3.tgz",
"integrity": "sha512-J2PxCefUVeFwsAExhrKo4lwxDevc5aKj888HBl/wN4EuWOoOg06iOGCxz4Omd8dqyFsrqvbBuPqRzQ+VycGmaA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-style": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-style/-/mjml-head-style-4.15.3.tgz",
"integrity": "sha512-9J+JuH+mKrQU65CaJ4KZegACUgNIlYmWQYx3VOBR/tyz+8kDYX7xBhKJCjQ1I4wj2Tvga3bykd89Oc2kFZ5WOw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-head-title": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-head-title/-/mjml-head-title-4.15.3.tgz",
"integrity": "sha512-IM59xRtsxID4DubQ0iLmoCGXguEe+9BFG4z6y2xQDrscIa4QY3KlfqgKGT69ojW+AVbXXJPEVqrAi4/eCsLItQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-hero": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-hero/-/mjml-hero-4.15.3.tgz",
"integrity": "sha512-9cLAPuc69yiuzNrMZIN58j+HMK1UWPaq2i3/Fg2ZpimfcGFKRcPGCbEVh0v+Pb6/J0+kf8yIO0leH20opu3AyQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-image": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-image/-/mjml-image-4.15.3.tgz",
"integrity": "sha512-g1OhSdofIytE9qaOGdTPmRIp7JsCtgO0zbsn1Fk6wQh2gEL55Z40j/VoghslWAWTgT2OHFdBKnMvWtN6U5+d2Q==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-migrate": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-migrate/-/mjml-migrate-4.15.3.tgz",
"integrity": "sha512-sr/+35RdxZroNQVegjpfRHJ5hda9XCgaS4mK2FGO+Mb1IUevKfeEPII3F/cHDpNwFeYH3kAgyqQ22ClhGLWNBA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"js-beautify": "^1.6.14",
"lodash": "^4.17.21",
"mjml-core": "4.15.3",
"mjml-parser-xml": "4.15.3",
"yargs": "^17.7.2"
},
"bin": {
"migrate": "lib/cli.js"
}
},
"node_modules/mjml-navbar": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-navbar/-/mjml-navbar-4.15.3.tgz",
"integrity": "sha512-VsKH/Jdlf8Yu3y7GpzQV5n7JMdpqvZvTSpF6UQXL0PWOm7k6+LX+sCZimOfpHJ+wCaaybpxokjWZ71mxOoCWoA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-parser-xml": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-parser-xml/-/mjml-parser-xml-4.15.3.tgz",
"integrity": "sha512-Tz0UX8/JVYICLjT+U8J1f/TFxIYVYjzZHeh4/Oyta0pLpRLeZlxEd71f3u3kdnulCKMP4i37pFRDmyLXAlEuLw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"detect-node": "2.1.0",
"htmlparser2": "^9.1.0",
"lodash": "^4.17.15"
}
},
"node_modules/mjml-parser-xml/node_modules/entities": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/mjml-parser-xml/node_modules/htmlparser2": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
"integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
"funding": [
"https://github.com/fb55/htmlparser2?sponsor=1",
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
],
"peer": true,
"dependencies": {
"domelementtype": "^2.3.0",
"domhandler": "^5.0.3",
"domutils": "^3.1.0",
"entities": "^4.5.0"
}
},
"node_modules/mjml-preset-core": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-preset-core/-/mjml-preset-core-4.15.3.tgz",
"integrity": "sha512-1zZS8P4O0KweWUqNS655+oNnVMPQ1Rq1GaZq5S9JfwT1Vh/m516lSmiTW9oko6gGHytt5s6Yj6oOeu5Zm8FoLw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"mjml-accordion": "4.15.3",
"mjml-body": "4.15.3",
"mjml-button": "4.15.3",
"mjml-carousel": "4.15.3",
"mjml-column": "4.15.3",
"mjml-divider": "4.15.3",
"mjml-group": "4.15.3",
"mjml-head": "4.15.3",
"mjml-head-attributes": "4.15.3",
"mjml-head-breakpoint": "4.15.3",
"mjml-head-font": "4.15.3",
"mjml-head-html-attributes": "4.15.3",
"mjml-head-preview": "4.15.3",
"mjml-head-style": "4.15.3",
"mjml-head-title": "4.15.3",
"mjml-hero": "4.15.3",
"mjml-image": "4.15.3",
"mjml-navbar": "4.15.3",
"mjml-raw": "4.15.3",
"mjml-section": "4.15.3",
"mjml-social": "4.15.3",
"mjml-spacer": "4.15.3",
"mjml-table": "4.15.3",
"mjml-text": "4.15.3",
"mjml-wrapper": "4.15.3"
}
},
"node_modules/mjml-raw": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-raw/-/mjml-raw-4.15.3.tgz",
"integrity": "sha512-IGyHheOYyRchBLiAEgw3UM11kFNmBSMupu2BDdejC6ZiDhEAdG+tyERlsCwDPYtXanvFpGWULIu3XlsUPc+RZw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-section": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-section/-/mjml-section-4.15.3.tgz",
"integrity": "sha512-JfVPRXH++Hd933gmQfG8JXXCBCR6fIzC3DwiYycvanL/aW1cEQ2EnebUfQkt5QzlYjOkJEH+JpccAsq3ln6FZQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-social": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-social/-/mjml-social-4.15.3.tgz",
"integrity": "sha512-7sD5FXrESOxpT9Z4Oh36bS6u/geuUrMP1aCg2sjyAwbPcF1aWa2k9OcatQfpRf6pJEhUZ18y6/WBBXmMVmSzXg==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-spacer": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-spacer/-/mjml-spacer-4.15.3.tgz",
"integrity": "sha512-3B7Qj+17EgDdAtZ3NAdMyOwLTX1jfmJuY7gjyhS2HtcZAmppW+cxqHUBwCKfvSRgTQiccmEvtNxaQK+tfyrZqA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-table": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-table/-/mjml-table-4.15.3.tgz",
"integrity": "sha512-FLx7DcRKTdKdcOCbMyBaeudeHaHpwPveRrBm6WyQe3LXx6FfdmOh59i71/16LFQMgBOD3N4/UJkzxLzlTJzMqQ==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-text": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-text/-/mjml-text-4.15.3.tgz",
"integrity": "sha512-+C0hxCmw9kg0XzT6vhE5mFkK6y225nC8UEQcN94K0fBCjPKkM+HqZMwGX205fzdGRi+Bxa55b/VhrIVwdv+8vw==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3"
}
},
"node_modules/mjml-validator": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-validator/-/mjml-validator-4.15.3.tgz",
"integrity": "sha512-Xb72KdqRwjv/qM2rJpV22syyP2N3cRQ9VVDrN6u2FSzLq02buFNxmSPJ7CKhat3PrUNdVHU75KZwOf/tz4UEhA==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9"
}
},
"node_modules/mjml-wrapper": {
"version": "4.15.3",
"resolved": "https://registry.npmjs.org/mjml-wrapper/-/mjml-wrapper-4.15.3.tgz",
"integrity": "sha512-ditsCijeHJrmBmObtJmQ18ddLxv5oPyMTdPU8Di8APOnD2zPk7Z4UAuJSl7HXB45oFiivr3MJf4koFzMUSZ6Gg==",
"peer": true,
"dependencies": {
"@babel/runtime": "^7.23.9",
"lodash": "^4.17.21",
"mjml-core": "4.15.3",
"mjml-section": "4.15.3"
}
},
"node_modules/mkdirp": {
"version": "0.5.6",
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
"integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
"dependencies": {
"minimist": "^1.2.6"
},
"bin": {
"mkdirp": "bin/cmd.js"
}
},
"node_modules/mkdirp-classic": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
"integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
"peer": true
},
"node_modules/mocha": {
"version": "10.8.2",
"resolved": "https://registry.npmjs.org/mocha/-/mocha-10.8.2.tgz",
"integrity": "sha512-VZlYo/WE8t1tstuRmqgeyBgCbJc/lEdopaa+axcKzTBJ+UIdlAB9XnmvTCAH4pwR4ElNInaedhEBmZD8iCSVEg==",
"dev": true,
"dependencies": {
"ansi-colors": "^4.1.3",
"browser-stdout": "^1.3.1",
"chokidar": "^3.5.3",
"debug": "^4.3.5",
"diff": "^5.2.0",
"escape-string-regexp": "^4.0.0",
"find-up": "^5.0.0",
"glob": "^8.1.0",
"he": "^1.2.0",
"js-yaml": "^4.1.0",
"log-symbols": "^4.1.0",
"minimatch": "^5.1.6",
"ms": "^2.1.3",
"serialize-javascript": "^6.0.2",
"strip-json-comments": "^3.1.1",
"supports-color": "^8.1.1",
"workerpool": "^6.5.1",
"yargs": "^16.2.0",
"yargs-parser": "^20.2.9",
"yargs-unparser": "^2.0.0"
},
"bin": {
"_mocha": "bin/_mocha",
"mocha": "bin/mocha.js"
},
"engines": {
"node": ">= 14.0.0"
}
},
"node_modules/mocha/node_modules/argparse": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
"integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true
},
"node_modules/mocha/node_modules/brace-expansion": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"dev": true,
"dependencies": {
"balanced-match": "^1.0.0"
}
},
"node_modules/mocha/node_modules/cliui": {
"version": "7.0.4",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
"integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^7.0.0"
}
},
"node_modules/mocha/node_modules/js-yaml": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
"integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
"dev": true,
"dependencies": {
"argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
"node_modules/mocha/node_modules/minimatch": {
"version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"dev": true,
"dependencies": {
"brace-expansion": "^2.0.1"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mocha/node_modules/yargs": {
"version": "16.2.0",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.0",
"y18n": "^5.0.5",
"yargs-parser": "^20.2.2"
},
"engines": {
"node": ">=10"
}
},
"node_modules/mongodb": {
"version": "6.18.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-6.18.0.tgz",
"integrity": "sha512-fO5ttN9VC8P0F5fqtQmclAkgXZxbIkYRTUi1j8JO6IYwvamkhtYDilJr35jOPELR49zqCJgXZWwCtW7B+TM8vQ==",
"peer": true,
"dependencies": {
"@mongodb-js/saslprep": "^1.1.9",
"bson": "^6.10.4",
"mongodb-connection-string-url": "^3.0.0"
},
"engines": {
"node": ">=16.20.1"
},
"peerDependencies": {
"@aws-sdk/credential-providers": "^3.188.0",
"@mongodb-js/zstd": "^1.1.0 || ^2.0.0",
"gcp-metadata": "^5.2.0",
"kerberos": "^2.0.1",
"mongodb-client-encryption": ">=6.0.0 <7",
"snappy": "^7.2.2",
"socks": "^2.7.1"
},
"peerDependenciesMeta": {
"@aws-sdk/credential-providers": {
"optional": true
},
"@mongodb-js/zstd": {
"optional": true
},
"gcp-metadata": {
"optional": true
},
"kerberos": {
"optional": true
},
"mongodb-client-encryption": {
"optional": true
},
"snappy": {
"optional": true
},
"socks": {
"optional": true
}
}
},
"node_modules/mongodb-connection-string-url": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-3.0.2.tgz",
"integrity": "sha512-rMO7CGo/9BFwyZABcKAWL8UJwH/Kc2x0g72uhDWzG48URRax5TCIcJ7Rc3RZqffZzO/Gwff/jyKwCU9TN8gehA==",
"peer": true,
"dependencies": {
"@types/whatwg-url": "^11.0.2",
"whatwg-url": "^14.1.0 || ^13.0.0"
}
},
"node_modules/mri": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
"integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
"dev": true,
"engines": {
"node": ">=4"
}
},
"node_modules/ms": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
},
"node_modules/multipipe": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/multipipe/-/multipipe-0.1.2.tgz",
"integrity": "sha512-7ZxrUybYv9NonoXgwoOqtStIu18D1c3eFZj27hqgf5kBrBF8Q+tE8V0MW8dKM5QLkQPh1JhhbKgHLY9kifov4Q==",
"dependencies": {
"duplexer2": "0.0.2"
}
},
"node_modules/multipipe/node_modules/duplexer2": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz",
"integrity": "sha512-+AWBwjGadtksxjOQSFDhPNQbed7icNXApT4+2BNpsXzcCBiInq2H9XW0O8sfHFaPmnQRs7cg/P0fAr2IWQSW0g==",
"dependencies": {
"readable-stream": "~1.1.9"
}
},
"node_modules/multipipe/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"node_modules/multipipe/node_modules/readable-stream": {
"version": "1.1.14",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz",
"integrity": "sha512-+MeVjFf4L44XUkhM1eYbD8fyEsxcV81pqMSR5gblfcLCHfZvbrqy4/qYHE+/R5HoBUT11WV5O08Cr1n3YXkWVQ==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/multipipe/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"node_modules/multiple-scripts-tmux": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/multiple-scripts-tmux/-/multiple-scripts-tmux-1.1.3.tgz",
"integrity": "sha512-H40o7GColpIFqDVWLhpYP5j7jhTQOMls+22z5hdBx1RIPHHkQpiRtWc3X8LhUHKyMB2Pu84SjQYSEpnhBElkjw==",
"peer": true,
"dependencies": {
"@sealcode/ts-predicates": "^0.5.3",
"locreq": "^2.0.2",
"yargs": "^17.7.2"
},
"bin": {
"multiple-scripts-tmux": "lib/index.js"
}
},
"node_modules/multiple-scripts-tmux/node_modules/@sealcode/ts-predicates": {
"version": "0.5.3",
"resolved": "https://registry.npmjs.org/@sealcode/ts-predicates/-/ts-predicates-0.5.3.tgz",
"integrity": "sha512-EZI7e8EY8gI1pw2bKdevjl+fBJbcSlpNkCZ8XoEOV3cHakPujiT6M4l775RDkfxJSbLX7jhOBkhgPNDfmCpZbg==",
"peer": true
},
"node_modules/multiple-scripts-tmux/node_modules/@types/node": {
"version": "14.18.63",
"resolved": "https://registry.npmjs.org/@types/node/-/node-14.18.63.tgz",
"integrity": "sha512-fAtCfv4jJg+ExtXhvCkCqUKZ+4ok/JQk01qDKhL5BDDoS3AxKXhV5/MAVUZyQnSEd2GT92fkgZl0pz0Q0AzcIQ==",
"peer": true
},
"node_modules/multiple-scripts-tmux/node_modules/locreq": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/locreq/-/locreq-2.4.1.tgz",
"integrity": "sha512-Itfhlus87Q9GcQKEK5LXZngD5YpUbANC9mr5UFghLSBIg6gVVG21AWX45+JVyaqBxILQkB+dBW0i2KlSVzGfeQ==",
"peer": true,
"dependencies": {
"@types/node": "^14.14.16"
}
},
"node_modules/nanoid": {
"version": "5.1.5",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-5.1.5.tgz",
"integrity": "sha512-Ir/+ZpE9fDsNH0hQ3C68uyThDXzYcim2EqcZ8zn8Chtt1iylPT9xXJB0kPCnqzgcEGikO9RxSrh63MsmVCU7Fw==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"peer": true,
"bin": {
"nanoid": "bin/nanoid.js"
},
"engines": {
"node": "^18 || >=20"
}
},
"node_modules/napi-build-utils": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
"integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
"peer": true
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
"integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
"dev": true
},
- "node_modules/natural-compare-lite": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz",
- "integrity": "sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==",
- "dev": true
- },
"node_modules/negotiator": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"peer": true
},
"node_modules/no-case": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
"integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
"peer": true,
"dependencies": {
"lower-case": "^1.1.1"
}
},
"node_modules/node-abi": {
"version": "3.75.0",
"resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.75.0.tgz",
"integrity": "sha512-OhYaY5sDsIka7H7AtijtI9jwGYLyl29eQn/W623DiN/MIv5sUqc4g7BIDThX+gb7di9f6xK02nkp8sdfFWZLTg==",
"peer": true,
"dependencies": {
"semver": "^7.3.5"
},
"engines": {
"node": ">=10"
}
},
"node_modules/node-addon-api": {
"version": "6.1.0",
"resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-6.1.0.tgz",
"integrity": "sha512-+eawOlIgy680F0kBzPUNFhMZGtJ1YmqM6l4+Crf4IkImjYrO/mqPwRMh352g23uIaQKFItcQ64I7KMaJxHgAVA==",
"peer": true
},
"node_modules/node-cache": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/node-cache/-/node-cache-5.1.2.tgz",
"integrity": "sha512-t1QzWwnk4sjLWaQAS8CHgOJ+RAfmHpxFWmc36IWTiWHQfs0w5JDMBS1b1ZxQteo0vVVuWJvIUKHDkkeK7vIGCg==",
"peer": true,
"dependencies": {
"clone": "2.x"
},
"engines": {
"node": ">= 8.0.0"
}
},
"node_modules/node-eta": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/node-eta/-/node-eta-0.9.0.tgz",
"integrity": "sha512-mTCTZk29tmX1OGfVkPt63H3c3VqXrI2Kvua98S7iUIB/Gbp0MNw05YtUomxQIxnnKMyRIIuY9izPcFixzhSBrA==",
"peer": true
},
"node_modules/node-fetch": {
"version": "2.7.0",
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
"integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
"peer": true,
"dependencies": {
"whatwg-url": "^5.0.0"
},
"engines": {
"node": "4.x || >=6.0.0"
},
"peerDependencies": {
"encoding": "^0.1.0"
},
"peerDependenciesMeta": {
"encoding": {
"optional": true
}
}
},
"node_modules/node-fetch-native": {
"version": "1.6.7",
"resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz",
"integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q=="
},
"node_modules/node-fetch/node_modules/tr46": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
"integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"peer": true
},
"node_modules/node-fetch/node_modules/webidl-conversions": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
"integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"peer": true
},
"node_modules/node-fetch/node_modules/whatwg-url": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
"integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
"peer": true,
"dependencies": {
"tr46": "~0.0.3",
"webidl-conversions": "^3.0.0"
}
},
"node_modules/node-font-face-generator": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/node-font-face-generator/-/node-font-face-generator-0.1.5.tgz",
"integrity": "sha512-g5UiEOP4yRElW17dQu6uGaI7PKnrsAsS2JkGwU3/VrFrcGRO8yNDfLDph57/6iFwUec8jd35/OjILTGMYHRTeg==",
"dependencies": {
"ejs": "1.0.0",
"useragent": "2.0.9"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/node-preload": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/node-preload/-/node-preload-0.2.1.tgz",
"integrity": "sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ==",
"dev": true,
"dependencies": {
"process-on-spawn": "^1.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/node-releases": {
"version": "2.0.19",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz",
"integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==",
"dev": true
},
"node_modules/node-status-codes": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz",
"integrity": "sha512-1cBMgRxdMWE8KeWCqk2RIOrvUb0XCwYfEsY5/y2NlXyq4Y/RumnOZvTj4Nbr77+Vb2C+kyBoRTdkNOS8L3d/aQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/nodemailer": {
"version": "6.10.1",
"resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.10.1.tgz",
"integrity": "sha512-Z+iLaBGVaSjbIzQ4pX6XV41HrooLsQ10ZWPUehGmuantvzWoDVBnmsdUcOIDM1t+yPor5pDhVlDESgOMEGxhHA==",
"peer": true,
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/nopt": {
"version": "7.2.1",
"resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.1.tgz",
"integrity": "sha512-taM24ViiimT/XntxbPyJQzCG+p4EKOpgD3mxFwW38mGjVUrfERQOeY4EDHjdnptttfHuHQXFx+lTP08Q+mLa/w==",
"peer": true,
"dependencies": {
"abbrev": "^2.0.0"
},
"bin": {
"nopt": "bin/nopt.js"
},
"engines": {
"node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/nth-check": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
"integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"peer": true,
"dependencies": {
"boolbase": "^1.0.0"
},
"funding": {
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
"node_modules/nyc": {
"version": "15.1.0",
"resolved": "https://registry.npmjs.org/nyc/-/nyc-15.1.0.tgz",
"integrity": "sha512-jMW04n9SxKdKi1ZMGhvUTHBN0EICCRkHemEoE5jm6mTYcqcdas0ATzgUgejlQUHMvpnOZqGB5Xxsv9KxJW1j8A==",
"dev": true,
"dependencies": {
"@istanbuljs/load-nyc-config": "^1.0.0",
"@istanbuljs/schema": "^0.1.2",
"caching-transform": "^4.0.0",
"convert-source-map": "^1.7.0",
"decamelize": "^1.2.0",
"find-cache-dir": "^3.2.0",
"find-up": "^4.1.0",
"foreground-child": "^2.0.0",
"get-package-type": "^0.1.0",
"glob": "^7.1.6",
"istanbul-lib-coverage": "^3.0.0",
"istanbul-lib-hook": "^3.0.0",
"istanbul-lib-instrument": "^4.0.0",
"istanbul-lib-processinfo": "^2.0.2",
"istanbul-lib-report": "^3.0.0",
"istanbul-lib-source-maps": "^4.0.0",
"istanbul-reports": "^3.0.2",
"make-dir": "^3.0.0",
"node-preload": "^0.2.1",
"p-map": "^3.0.0",
"process-on-spawn": "^1.0.0",
"resolve-from": "^5.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.2",
"spawn-wrap": "^2.0.0",
"test-exclude": "^6.0.0",
"yargs": "^15.0.2"
},
"bin": {
"nyc": "bin/nyc.js"
},
"engines": {
"node": ">=8.9"
}
},
"node_modules/nyc/node_modules/cliui": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
"integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
"dev": true,
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
"wrap-ansi": "^6.2.0"
}
},
"node_modules/nyc/node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/nyc/node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nyc/node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"dependencies": {
"p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/resolve-from": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
"integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/wrap-ansi": {
"version": "6.2.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
"integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/y18n": {
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
"dev": true
},
"node_modules/nyc/node_modules/yargs": {
"version": "15.4.1",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-15.4.1.tgz",
"integrity": "sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A==",
"dev": true,
"dependencies": {
"cliui": "^6.0.0",
"decamelize": "^1.2.0",
"find-up": "^4.1.0",
"get-caller-file": "^2.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^2.0.0",
"set-blocking": "^2.0.0",
"string-width": "^4.2.0",
"which-module": "^2.0.0",
"y18n": "^4.0.0",
"yargs-parser": "^18.1.2"
},
"engines": {
"node": ">=8"
}
},
"node_modules/nyc/node_modules/yargs-parser": {
"version": "18.1.3",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-18.1.3.tgz",
"integrity": "sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ==",
"dev": true,
"dependencies": {
"camelcase": "^5.0.0",
"decamelize": "^1.2.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/oauth-sign": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
"integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
"engines": {
"node": "*"
}
},
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-fit-math": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/object-fit-math/-/object-fit-math-1.0.0.tgz",
"integrity": "sha512-SqsfEKO6OoHR1K3r5E7JpJoloN6Wd5zPZr0QAo0DAI/zjpadPNcajoUhNvrGUcDHDaF8LEQKCgiiz0+p7lVGeg==",
"peer": true
},
"node_modules/object-hash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
"integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
"peer": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/object-inspect": {
"version": "1.13.4",
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
"integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/object.omit": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/object.omit/-/object.omit-2.0.1.tgz",
"integrity": "sha512-UiAM5mhmIuKLsOvrL+B0U2d1hXHF3bFYWIuH1LMpuV2EJEHG1Ntz06PgLEHjm6VFd87NpH8rastvPoyv6UW2fA==",
"dependencies": {
"for-own": "^0.1.4",
"is-extendable": "^0.1.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/ofetch": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/ofetch/-/ofetch-1.4.1.tgz",
"integrity": "sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw==",
"dependencies": {
"destr": "^2.0.3",
"node-fetch-native": "^1.6.4",
"ufo": "^1.5.4"
}
},
"node_modules/on-finished": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"peer": true,
"dependencies": {
"ee-first": "1.1.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/onetime": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz",
"integrity": "sha512-GZ+g4jayMqzCRMgB2sol7GiCLjKfS1PINkjmx8spcKce1LiVqcbQreXwqs2YAFXC6R03VIG28ZS31t8M866v6A==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/only": {
"version": "0.0.2",
"resolved": "https://registry.npmjs.org/only/-/only-0.0.2.tgz",
"integrity": "sha512-Fvw+Jemq5fjjyWz6CpKx6w9s7xxqo3+JCyM0WXWeCSOboZ8ABkyvP8ID4CZuChA/wxSx+XSJmdOm8rGVyJ1hdQ==",
"peer": true
},
"node_modules/optionator": {
"version": "0.9.4",
"resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
"integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
"dependencies": {
"deep-is": "^0.1.3",
"fast-levenshtein": "^2.0.6",
"levn": "^0.4.1",
"prelude-ls": "^1.2.1",
"type-check": "^0.4.0",
"word-wrap": "^1.2.5"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/ordered-read-streams": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz",
"integrity": "sha512-xQvd8qvx9U1iYY9aVqPpoF5V9uaWJKV6ZGljkh/jkiNX0DiQsjbWvRumbh10QTMDE8DheaOEU8xi0szbrgjzcw==",
"dependencies": {
"is-stream": "^1.0.1",
"readable-stream": "^2.0.1"
}
},
"node_modules/p-limit": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
"integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
"dependencies": {
"yocto-queue": "^0.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
"integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
"dependencies": {
"p-limit": "^3.0.2"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-map": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz",
"integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==",
"dev": true,
"dependencies": {
"aggregate-error": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/p-try": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/package-hash": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/package-hash/-/package-hash-4.0.0.tgz",
"integrity": "sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ==",
"dev": true,
"dependencies": {
"graceful-fs": "^4.1.15",
"hasha": "^5.0.0",
"lodash.flattendeep": "^4.4.0",
"release-zalgo": "^1.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/package-json-from-dist": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"peer": true
},
"node_modules/param-case": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
"integrity": "sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
"peer": true,
"dependencies": {
"no-case": "^2.2.0"
}
},
"node_modules/parent-module": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
"engines": {
"node": ">=6"
}
},
"node_modules/parse-glob": {
"version": "3.0.4",
"resolved": "https://registry.npmjs.org/parse-glob/-/parse-glob-3.0.4.tgz",
"integrity": "sha512-FC5TeK0AwXzq3tUBFtH74naWkPQCEWs4K+xMxWZBlKDWu0bVHXGZa+KKqxKidd7xwhdZ19ZNuF2uO1M/r196HA==",
"dependencies": {
"glob-base": "^0.3.0",
"is-dotfile": "^1.0.0",
"is-extglob": "^1.0.0",
"is-glob": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/parse-glob/node_modules/is-extglob": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz",
"integrity": "sha512-7Q+VbVafe6x2T+Tu6NcOf6sRklazEPmBoB3IWk3WdGZM2iGUwU/Oe3Wtq5lSEkDTTlpp8yx+5t4pzO/i9Ty1ww==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/parse-glob/node_modules/is-glob": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz",
"integrity": "sha512-a1dBeB19NXsf/E0+FHqkagizel/LQw2DjSQpvQrj3zT+jYPpaUCryPnrQajXKFLCMuf4I6FhRpaGtw4lPrG6Eg==",
"dependencies": {
"is-extglob": "^1.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/parse-json": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
"integrity": "sha512-QR/GGaKCkhwk1ePQNYDRKYZ3mwU9ypsKhB0XyFnLQdomyEqk3e8wpW3V5Jp88zbxK4n5ST1nqo+g9juTpownhQ==",
"dependencies": {
"error-ex": "^1.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/parse-ms": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-2.1.0.tgz",
"integrity": "sha512-kHt7kzLoS9VBZfUsiKjv43mr91ea+U05EyKkEtqp7vNbHxmaVuEqN7XxeEVnGrMtYOAxGrDElSi96K7EgO1zCA==",
"peer": true,
"engines": {
"node": ">=6"
}
},
"node_modules/parse-node-version": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-node-version/-/parse-node-version-1.0.1.tgz",
"integrity": "sha512-3YHlOa/JgH6Mnpr05jP9eDG254US9ek25LyIxZlDItp2iJtwyaXQb57lBYLdT3MowkUFYEV2XXNAYIPlESvJlA==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/parse-srcset": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/parse-srcset/-/parse-srcset-1.0.2.tgz",
"integrity": "sha512-/2qh0lav6CmI15FzA3i/2Bzk2zCgQhGMkvhOhKNcBVQ1ldgpbfiNTVslmooUmWJcADi1f1kIeynbDRVzNlfR6Q==",
"peer": true
},
"node_modules/parse5": {
"version": "7.3.0",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
"integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
"peer": true,
"dependencies": {
"entities": "^6.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
"integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
"peer": true,
"dependencies": {
"domhandler": "^5.0.3",
"parse5": "^7.0.0"
},
"funding": {
"url": "https://github.com/inikulin/parse5?sponsor=1"
}
},
"node_modules/parse5/node_modules/entities": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
"integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
"peer": true,
"engines": {
"node": ">=0.12"
},
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"peer": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/path-dirname": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
"integrity": "sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q=="
},
"node_modules/path-exists": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/path-key": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
"integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"engines": {
"node": ">=8"
}
},
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"peer": true
},
"node_modules/path-scurry": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
"integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
"peer": true,
"dependencies": {
"lru-cache": "^10.2.0",
"minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
},
"engines": {
"node": ">=16 || 14 >=14.18"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/path-to-regexp": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-6.3.0.tgz",
"integrity": "sha512-Yhpw4T9C6hPpgPeA28us07OJeqZ5EzQTkbfwuhsUg0c237RomFoETJgmp2sa3F/41gfLE6G5cqcYwznmeEeOlQ=="
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/pend": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
"integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg=="
},
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
"integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
},
"node_modules/pg": {
"version": "8.16.3",
"resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
"integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
"peer": true,
"dependencies": {
"pg-connection-string": "^2.9.1",
"pg-pool": "^3.10.1",
"pg-protocol": "^1.10.3",
"pg-types": "2.2.0",
"pgpass": "1.0.5"
},
"engines": {
"node": ">= 16.0.0"
},
"optionalDependencies": {
"pg-cloudflare": "^1.2.7"
},
"peerDependencies": {
"pg-native": ">=3.0.1"
},
"peerDependenciesMeta": {
"pg-native": {
"optional": true
}
}
},
"node_modules/pg-connection-string": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
"integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
"peer": true
},
"node_modules/pg-int8": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
"integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
"peer": true,
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/pg-pool": {
"version": "3.10.1",
"resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
"integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
"peer": true,
"peerDependencies": {
"pg": ">=8.0"
}
},
"node_modules/pg-protocol": {
"version": "1.10.3",
"resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
"integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==",
"peer": true
},
"node_modules/pg-types": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
"integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
"peer": true,
"dependencies": {
"pg-int8": "1.0.1",
"postgres-array": "~2.0.0",
"postgres-bytea": "~1.0.0",
"postgres-date": "~1.0.4",
"postgres-interval": "^1.1.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/pgpass": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
"integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
"peer": true,
"dependencies": {
"split2": "^4.1.0"
}
},
"node_modules/pick-port": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/pick-port/-/pick-port-2.1.1.tgz",
"integrity": "sha512-2rBA4etQOrb7EBamFWC4no8lECAj4IFLPIjvw951isoDKvNTS0sUDf0lirjqFlMwmaahjI8652LEJ0AYtUYl8g==",
"peer": true,
"dependencies": {
"debug": "^4.4.1"
},
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/mediasoup"
}
},
"node_modules/picocolors": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true
},
"node_modules/picomatch": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
"engines": {
"node": ">=8.6"
},
"funding": {
"url": "https://github.com/sponsors/jonschlinkert"
}
},
"node_modules/pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"integrity": "sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pinkie-promise": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
"integrity": "sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
"dependencies": {
"pinkie": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/pkg-dir": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
"integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
"dependencies": {
"find-up": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-dir/node_modules/find-up": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
"integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
"dependencies": {
"locate-path": "^5.0.0",
"path-exists": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-dir/node_modules/locate-path": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
"integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
"dependencies": {
"p-locate": "^4.1.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/pkg-dir/node_modules/p-limit": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
"integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
"dependencies": {
"p-try": "^2.0.0"
},
"engines": {
"node": ">=6"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/pkg-dir/node_modules/p-locate": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
"integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
"dependencies": {
"p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/playwright": {
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright/-/playwright-1.54.2.tgz",
"integrity": "sha512-Hu/BMoA1NAdRUuulyvQC0pEqZ4vQbGfn8f7wPXcnqQmM+zct9UliKxsIkLNmz/ku7LElUNqmaiv1TG/aL5ACsw==",
"dev": true,
"dependencies": {
"playwright-core": "1.54.2"
},
"bin": {
"playwright": "cli.js"
},
"engines": {
"node": ">=18"
},
"optionalDependencies": {
"fsevents": "2.3.2"
}
},
"node_modules/playwright-core": {
"version": "1.54.2",
"resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.54.2.tgz",
"integrity": "sha512-n5r4HFbMmWsB4twG7tJLDN9gmBUeSPcsBZiWSE4DnYz9mJMAFqr2ID7+eGC9kpEnxExJ1epttwR59LEWCk8mtA==",
"dev": true,
"bin": {
"playwright-core": "cli.js"
},
"engines": {
"node": ">=18"
}
},
"node_modules/playwright/node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
"dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": "^8.16.0 || ^10.6.0 || >=11.0.0"
}
},
"node_modules/possible-typed-array-names": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
"integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/postcss": {
"version": "7.0.39",
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
"peer": true,
"dependencies": {
"picocolors": "^0.2.1",
"source-map": "^0.6.1"
},
"engines": {
"node": ">=6.0.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/postcss/"
}
},
"node_modules/postcss/node_modules/picocolors": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
"peer": true
},
"node_modules/postgres-array": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
"integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
"peer": true,
"engines": {
"node": ">=4"
}
},
"node_modules/postgres-bytea": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
"integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-date": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
"integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
"peer": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/postgres-interval": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
"integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
"peer": true,
"dependencies": {
"xtend": "^4.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/prebuild-install": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
"integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
"peer": true,
"dependencies": {
"detect-libc": "^2.0.0",
"expand-template": "^2.0.3",
"github-from-package": "0.0.0",
"minimist": "^1.2.3",
"mkdirp-classic": "^0.5.3",
"napi-build-utils": "^2.0.0",
"node-abi": "^3.3.0",
"pump": "^3.0.0",
"rc": "^1.2.7",
"simple-get": "^4.0.0",
"tar-fs": "^2.0.0",
"tunnel-agent": "^0.6.0"
},
"bin": {
"prebuild-install": "bin.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/prebuild-install/node_modules/bl": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
"integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
"peer": true,
"dependencies": {
"buffer": "^5.5.0",
"inherits": "^2.0.4",
"readable-stream": "^3.4.0"
}
},
"node_modules/prebuild-install/node_modules/readable-stream": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"peer": true,
"dependencies": {
"inherits": "^2.0.3",
"string_decoder": "^1.1.1",
"util-deprecate": "^1.0.1"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/prebuild-install/node_modules/tar-fs": {
"version": "2.1.3",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.3.tgz",
"integrity": "sha512-090nwYJDmlhwFwEW3QQl+vaNnxsO2yVsd45eTKRBzSzu+hlb1w2K9inVq5b0ngXuLVqQ4ApvsUHHnu/zQNkWAg==",
"peer": true,
"dependencies": {
"chownr": "^1.1.1",
"mkdirp-classic": "^0.5.2",
"pump": "^3.0.0",
"tar-stream": "^2.1.4"
}
},
"node_modules/prebuild-install/node_modules/tar-stream": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
"integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
"peer": true,
"dependencies": {
"bl": "^4.0.3",
"end-of-stream": "^1.4.1",
"fs-constants": "^1.0.0",
"inherits": "^2.0.3",
"readable-stream": "^3.1.1"
},
"engines": {
"node": ">=6"
}
},
"node_modules/prebuild-install/node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"peer": true,
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/prelude-ls": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
"integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
"dev": true,
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/prepend-http": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
"integrity": "sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/preserve": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/preserve/-/preserve-0.2.0.tgz",
"integrity": "sha512-s/46sYeylUfHNjI+sA/78FAHlmIuKqI9wNnzEOGehAlUUYeObv5C2mOinXBjyUyWmJ2SfcS2/ydApH4hTF4WXQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/prettier": {
- "version": "2.8.8",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
- "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.6.2.tgz",
+ "integrity": "sha512-I7AIg5boAr5R0FFtJ6rCfD+LFsWHp81dolrFD8S79U9tb8Az2nGrJncnMSnys+bpQJfRUzqs9hnA81OAA3hCuQ==",
+ "license": "MIT",
"bin": {
- "prettier": "bin-prettier.js"
+ "prettier": "bin/prettier.cjs"
},
"engines": {
- "node": ">=10.13.0"
+ "node": ">=14"
},
"funding": {
"url": "https://github.com/prettier/prettier?sponsor=1"
}
},
"node_modules/prettier-linter-helpers": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
"integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
"dev": true,
"dependencies": {
"fast-diff": "^1.1.2"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/pretty-ms": {
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/pretty-ms/-/pretty-ms-7.0.1.tgz",
"integrity": "sha512-973driJZvxiGOQ5ONsFhOF/DtzPMOMtgC11kCpUrPGMTgqp2q/1gwzCquocrN33is0VZ5GFHXZYMM9l6h67v2Q==",
"peer": true,
"dependencies": {
"parse-ms": "^2.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/process-nextick-args": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
},
"node_modules/process-on-spawn": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/process-on-spawn/-/process-on-spawn-1.1.0.tgz",
"integrity": "sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q==",
"dev": true,
"dependencies": {
"fromentries": "^1.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/progress": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
"integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
+ "peer": true,
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/prompts": {
"version": "2.4.2",
"resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
"integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
"dependencies": {
"kleur": "^3.0.3",
"sisteransi": "^1.0.5"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/proto-list": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz",
"integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==",
"peer": true
},
"node_modules/proxy-from-env": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
"integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
"dev": true
},
"node_modules/psl": {
"version": "1.15.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.15.0.tgz",
"integrity": "sha512-JZd3gMVBAVQkSs6HdNZo9Sdo0LNcQeMNP3CozBJb3JYC/QUYZTnKxP+f8oWRX4rHP5EurWxqAHTSwUCjlNKa1w==",
"dependencies": {
"punycode": "^2.3.1"
},
"funding": {
"url": "https://github.com/sponsors/lupomontero"
}
},
"node_modules/pump": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
"integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
"peer": true,
"dependencies": {
"end-of-stream": "^1.1.0",
"once": "^1.3.1"
}
},
"node_modules/punycode": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
"integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
"engines": {
"node": ">=6"
}
},
"node_modules/qs": {
"version": "6.14.0",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
"integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
"dependencies": {
"side-channel": "^1.1.0"
},
"engines": {
"node": ">=0.6"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
"integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/randomatic": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/randomatic/-/randomatic-3.1.1.tgz",
"integrity": "sha512-TuDE5KxZ0J461RVjrJZCJc+J+zCkTb1MbH9AQUq68sMhOMcy9jLcb3BrZKgp9q9Ncltdg4QVqWrH02W2EFFVYw==",
"dependencies": {
"is-number": "^4.0.0",
"kind-of": "^6.0.0",
"math-random": "^1.0.1"
},
"engines": {
"node": ">= 0.10.0"
}
},
"node_modules/randomatic/node_modules/is-number": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-4.0.0.tgz",
"integrity": "sha512-rSklcAIlf1OmFdyAqbnWTLVelsQ58uvZ66S/ZyawjWqIviTWCjg2PzVGw8WUA+nNuPTqb4wgA+NszrJ+08LlgQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/randomatic/node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/randombytes": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
"node_modules/raw-body": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/rc": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
"integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
"dependencies": {
"deep-extend": "^0.6.0",
"ini": "~1.3.0",
"minimist": "^1.2.0",
"strip-json-comments": "~2.0.1"
},
"bin": {
"rc": "cli.js"
}
},
"node_modules/rc/node_modules/strip-json-comments": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
"integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/read-all-stream": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz",
"integrity": "sha512-DI1drPHbmBcUDWrJ7ull/F2Qb8HkwBncVx8/RpKYFSIACYaVRQReISYPdZz/mt1y1+qMCOrfReTopERmaxtP6w==",
"dependencies": {
"pinkie-promise": "^2.0.0",
"readable-stream": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/readable-stream": {
"version": "2.3.8",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
"integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.3",
"isarray": "~1.0.0",
"process-nextick-args": "~2.0.0",
"safe-buffer": "~5.1.1",
"string_decoder": "~1.1.1",
"util-deprecate": "~1.0.1"
}
},
"node_modules/readable-stream/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/readdirp": {
"version": "3.6.0",
"resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
"integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
"dependencies": {
"picomatch": "^2.2.1"
},
"engines": {
"node": ">=8.10.0"
}
},
"node_modules/rechoir": {
"version": "0.6.2",
"resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz",
"integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==",
"peer": true,
"dependencies": {
"resolve": "^1.1.6"
},
"engines": {
"node": ">= 0.10"
}
},
"node_modules/recursive-readdir": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
"integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
"dependencies": {
"minimatch": "^3.0.5"
},
"engines": {
"node": ">=6.0.0"
}
},
"node_modules/regex-cache": {
"version": "0.4.4",
"resolved": "https://registry.npmjs.org/regex-cache/-/regex-cache-0.4.4.tgz",
"integrity": "sha512-nVIZwtCjkC9YgvWkpM55B5rBhBYRZhAaJbgcFYXXsHnbZ9UZI9nnVWYZpBlCqv9ho2eZryPnWrZGsOdPwVWXWQ==",
"dependencies": {
"is-equal-shallow": "^0.1.3"
},
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/regexpp": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-3.2.0.tgz",
- "integrity": "sha512-pq2bWo9mVD43nbts2wGv17XLiNLya+GklZ8kaDLV2Z08gDCsGpnKn9BFMepvWuHCbyVvY7J5o5+BVvoQbmlJLg==",
- "dev": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- }
- },
"node_modules/relateurl": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
"integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
"peer": true,
"engines": {
"node": ">= 0.10"
}
},
"node_modules/relative-luminance": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/relative-luminance/-/relative-luminance-2.0.1.tgz",
"integrity": "sha512-wFuITNthJilFPwkK7gNJcULxXBcfFZvZORsvdvxeOdO44wCeZnuQkf3nFFzOR/dpJNxYsdRZJLsepWbyKhnMww==",
"dependencies": {
"esm": "^3.0.84"
}
},
"node_modules/release-zalgo": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/release-zalgo/-/release-zalgo-1.0.0.tgz",
"integrity": "sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA==",
"dev": true,
"dependencies": {
"es6-error": "^4.0.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/remove-trailing-separator": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
"integrity": "sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw=="
},
"node_modules/repeat-element": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
"integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/repeat-string": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
"integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/replace-ext": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-0.0.1.tgz",
"integrity": "sha512-AFBWBy9EVRTa/LhEcG8QDP3FvpwZqmvN2QFDuJswFeaVhWnZMp8q3E6Zd90SR04PlIwfGdyVjNyLPyen/ek5CQ==",
"engines": {
"node": ">= 0.4"
}
},
"node_modules/request": {
"version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
"dependencies": {
"aws-sign2": "~0.7.0",
"aws4": "^1.8.0",
"caseless": "~0.12.0",
"combined-stream": "~1.0.6",
"extend": "~3.0.2",
"forever-agent": "~0.6.1",
"form-data": "~2.3.2",
"har-validator": "~5.1.3",
"http-signature": "~1.2.0",
"is-typedarray": "~1.0.0",
"isstream": "~0.1.2",
"json-stringify-safe": "~5.0.1",
"mime-types": "~2.1.19",
"oauth-sign": "~0.9.0",
"performance-now": "^2.1.0",
"qs": "~6.5.2",
"safe-buffer": "^5.1.2",
"tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0",
"uuid": "^3.3.2"
},
"engines": {
"node": ">= 6"
}
},
"node_modules/request/node_modules/form-data": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
"integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
"dependencies": {
"asynckit": "^0.4.0",
"combined-stream": "^1.0.6",
"mime-types": "^2.1.12"
},
"engines": {
"node": ">= 0.12"
}
},
"node_modules/request/node_modules/qs": {
"version": "6.5.3",
"resolved": "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz",
"integrity": "sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/request/node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/request/node_modules/uuid": {
"version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
"deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
"bin": {
"uuid": "bin/uuid"
}
},
"node_modules/require-directory": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/require-from-string": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
- "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/require-main-filename": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
"integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
"dev": true
},
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"peer": true,
"dependencies": {
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/resolve-path": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/resolve-path/-/resolve-path-1.4.0.tgz",
"integrity": "sha512-i1xevIst/Qa+nA9olDxLWnLk8YZbi8R/7JPbCMcgyWaFR6bKWaexgJgEB5oc2PKMjYdrHynyz0NY+if+H98t1w==",
"peer": true,
"dependencies": {
"http-errors": "~1.6.2",
"path-is-absolute": "1.0.1"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/resolve-path/node_modules/depd": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
"integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/resolve-path/node_modules/http-errors": {
"version": "1.6.3",
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
"integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
"peer": true,
"dependencies": {
"depd": "~1.1.2",
"inherits": "2.0.3",
"setprototypeof": "1.1.0",
"statuses": ">= 1.4.0 < 2"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/resolve-path/node_modules/inherits": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
"integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
"peer": true
},
"node_modules/resolve-path/node_modules/setprototypeof": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
"integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
"peer": true
},
"node_modules/resolve-path/node_modules/statuses": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
"integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
"peer": true,
"engines": {
"node": ">= 0.6"
}
},
"node_modules/reusify": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
"integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
"dev": true,
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
"node_modules/rimraf": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
"integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/rimraf/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/run-parallel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
"integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
"node_modules/safe-buffer": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/safe-regex-test": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
"integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
"peer": true,
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"is-regex": "^1.2.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
},
"node_modules/sanitize-html": {
"version": "1.27.5",
"resolved": "https://registry.npmjs.org/sanitize-html/-/sanitize-html-1.27.5.tgz",
"integrity": "sha512-M4M5iXDAUEcZKLXkmk90zSYWEtk5NH3JmojQxKxV371fnMh+x9t1rqdmXaGoyEHw3z/X/8vnFhKjGL5xFGOJ3A==",
"peer": true,
"dependencies": {
"htmlparser2": "^4.1.0",
"lodash": "^4.17.15",
"parse-srcset": "^1.0.2",
"postcss": "^7.0.27"
}
},
"node_modules/sanitize-html/node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/dom-serializer/node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"peer": true,
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"peer": true,
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/domutils/node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"peer": true,
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"peer": true,
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/sanitize-html/node_modules/htmlparser2": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.1.0.tgz",
"integrity": "sha512-4zDq1a1zhE4gQso/c5LP1OtrhYTncXNSpvJYtWJBtXAETPlMfi3IFNjGuQbYLuVY4ZR0QMqRVvo4Pdy9KLyP8Q==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^3.0.0",
"domutils": "^2.0.0",
"entities": "^2.0.0"
}
},
"node_modules/sealious": {
- "version": "0.21.8",
- "resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.8.tgz",
- "integrity": "sha512-LKKTmKDewvfpLs4h61ZrfZRvD7FaK3/QlJeHDSB6m8hoAkxPynJZbyaqe7kco6G2EPDTyOrcHz58i5pSJXTwYw==",
+ "version": "0.21.20",
+ "resolved": "https://registry.npmjs.org/sealious/-/sealious-0.21.20.tgz",
+ "integrity": "sha512-O4ac6jHkL3tP8UcN/3ybmOHMSo17IRaAFt5/FDixw+6upcQw8QeXuQgf7DR8gKdmNbNCiWLjqGoksw6GeQFWgg==",
+ "license": "BSD-2-Clause",
"peer": true,
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.1",
"@sealcode/ts-predicates": "^0.4.3",
"@types/boom": "^7.3.0",
"@types/clone": "^0.1.30",
"@types/color": "^3.0.1",
"@types/color-hash": "^1.0.0",
"@types/escape-html": "^1.0.0",
"@types/koa": "^3.0.0",
"@types/koa-mount": "^4.0.0",
"@types/koa-qs": "^2.0.0",
"@types/koa-send": "^4.1.2",
"@types/koa-static": "^4.0.1",
"@types/mjml": "^4.0.4",
"@types/mongodb": "^3.5.20",
"@types/node": "^20.0",
"@types/nodemailer": "^6.4.0",
"@types/object-hash": "^1.3.3",
"@types/sanitize-html": "^2.11.0",
"@types/uuid": "^8.3.0",
"boom": "^7.3.0",
"chalk": "^4.1.0",
"clone": "^1.0.2",
"color": "latest",
"color-hash": "^1.0.3",
"commonmark": "^0.31.0",
"cron": "^2.1.0",
"csv-stringify": "^6.4.5",
"deepmerge": "^4.2.2",
"dot-prop": "^8.0.2",
"emittery": "0.8.1",
"escape-html": "^1.0.3",
"get-port": "^5.1.1",
"koa": "^2.13.0",
"koa-body": "^4.2.0",
"koa-mount": "^4.0.0",
"koa-qs": "^3.0.0",
"koa-send": "^5.0.1",
"koa-static": "^5.0.0",
"locreq": "^3.0.0",
"mjml": "^4.2.0",
"mongodb": "^6.5.0",
"nanoid": "^5.0.9",
"nodemailer": "^6.4.6",
"object-hash": "^2.0.3",
"pg": "^8.13.1",
"pretty-ms": "^7.0.0",
"qs": "^6.12.0",
"sanitize-html": "^1.13.0",
"typedoc": "^0.17.8",
"uuid": "^8.3.2"
},
"engines": {
"node": ">=21.0"
+ },
+ "peerDependencies": {
+ "koa-responsive-image-router": "^0.2.37"
}
},
"node_modules/sealious/node_modules/@types/formidable": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@types/formidable/-/formidable-1.2.8.tgz",
"integrity": "sha512-6psvrUy5VDYb+yaPJReF1WrRsz+FBwyJutK9Twz1Efa27tm07bARNIkK2B8ZPWq80dXqpKfrxTO96xrtPp+AuA==",
"peer": true,
"dependencies": {
"@types/node": "*"
}
},
"node_modules/sealious/node_modules/@types/uuid": {
"version": "8.3.4",
"resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-8.3.4.tgz",
"integrity": "sha512-c/I8ZRb51j+pYGAu5CrFMRxqZ2ke4y2grEBO5AUjgSkSk+qT2Ea+OdWElz/OiMf5MNpn2b17kuVBwZLQJXzihw==",
"peer": true
},
"node_modules/sealious/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"peer": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/sealious/node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"peer": true,
"engines": {
"node": ">=0.8"
}
},
"node_modules/sealious/node_modules/formidable": {
"version": "1.2.6",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.6.tgz",
"integrity": "sha512-KcpbcpuLNOwrEjnbpMC0gS+X8ciDoZE1kkqzat4a8vrprf+s9pKNQ/QIwWfbfs4ltgmFl3MD177SNTkve3BwGQ==",
"deprecated": "Please upgrade to latest, formidable@v2 or formidable@v3! Check these notes: https://bit.ly/2ZEqIau",
"peer": true,
"funding": {
"url": "https://ko-fi.com/tunnckoCore/commissions"
}
},
"node_modules/sealious/node_modules/koa-body": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/koa-body/-/koa-body-4.2.0.tgz",
"integrity": "sha512-wdGu7b9amk4Fnk/ytH8GuWwfs4fsB5iNkY8kZPpgQVb04QZSv85T0M8reb+cJmvLE8cjPYvBzRikD3s6qz8OoA==",
"peer": true,
"dependencies": {
"@types/formidable": "^1.0.31",
"co-body": "^5.1.1",
"formidable": "^1.1.1"
}
},
"node_modules/sealious/node_modules/object-hash": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
"integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
"peer": true,
"engines": {
"node": ">= 6"
}
},
"node_modules/sealious/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"peer": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/sealious/node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"peer": true,
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/seek-bzip": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.6.tgz",
"integrity": "sha512-e1QtP3YL5tWww8uKaOCQ18UxIT2laNBXHjV/S2WYCiK4udiv8lkG89KRIoCjUagnAmCBurjF4zEVX2ByBbnCjQ==",
"dependencies": {
"commander": "^2.8.1"
},
"bin": {
"seek-bunzip": "bin/seek-bunzip",
"seek-table": "bin/seek-bzip-table"
}
},
"node_modules/semver": {
"version": "7.7.2",
"resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
"integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
"bin": {
"semver": "bin/semver.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/serialize-javascript": {
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
"integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/set-blocking": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
"dev": true
},
"node_modules/set-function-length": {
"version": "1.2.2",
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
"dependencies": {
"define-data-property": "^1.1.4",
"es-errors": "^1.3.0",
"function-bind": "^1.1.2",
"get-intrinsic": "^1.2.4",
"gopd": "^1.0.1",
"has-property-descriptors": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/set-immediate-shim": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/set-immediate-shim/-/set-immediate-shim-1.0.1.tgz",
"integrity": "sha512-Li5AOqrZWCVA2n5kryzEmqai6bKSIvpz5oUJHPVj6+dsbD3X1ixtsY5tEnsaNpH3pFAHmG8eIHUrtEtohrg+UQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/setprototypeof": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
},
"node_modules/sharp": {
"version": "0.32.6",
"resolved": "https://registry.npmjs.org/sharp/-/sharp-0.32.6.tgz",
"integrity": "sha512-KyLTWwgcR9Oe4d9HwCwNM2l7+J0dUQwn/yf7S0EnTtb0eVS4RxO0eUSvxPtzT4F3SY+C4K6fqdv/DO27sJ/v/w==",
"hasInstallScript": true,
"peer": true,
"dependencies": {
"color": "^4.2.3",
"detect-libc": "^2.0.2",
"node-addon-api": "^6.1.0",
"prebuild-install": "^7.1.1",
"semver": "^7.5.4",
"simple-get": "^4.0.1",
"tar-fs": "^3.0.4",
"tunnel-agent": "^0.6.0"
},
"engines": {
"node": ">=14.15.0"
},
"funding": {
"url": "https://opencollective.com/libvips"
}
},
"node_modules/sharp/node_modules/color": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
"integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
"peer": true,
"dependencies": {
"color-convert": "^2.0.1",
"color-string": "^1.9.0"
},
"engines": {
"node": ">=12.5.0"
}
},
"node_modules/sharp/node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"peer": true,
"dependencies": {
"color-name": "~1.1.4"
},
"engines": {
"node": ">=7.0.0"
}
},
"node_modules/sharp/node_modules/color-name": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
"peer": true
},
"node_modules/sharp/node_modules/color-string": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
"integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
"peer": true,
"dependencies": {
"color-name": "^1.0.0",
"simple-swizzle": "^0.2.2"
}
},
"node_modules/sharp/node_modules/tunnel-agent": {
"version": "0.6.0",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
"integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
"peer": true,
"dependencies": {
"safe-buffer": "^5.0.1"
},
"engines": {
"node": "*"
}
},
"node_modules/shebang-command": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
"integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dependencies": {
"shebang-regex": "^3.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/shebang-regex": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
"integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"engines": {
"node": ">=8"
}
},
"node_modules/shelljs": {
"version": "0.8.5",
"resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz",
"integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==",
"peer": true,
"dependencies": {
"glob": "^7.0.0",
"interpret": "^1.0.0",
"rechoir": "^0.6.2"
},
"bin": {
"shjs": "bin/shjs"
},
"engines": {
"node": ">=4"
}
},
"node_modules/shelljs/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"peer": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/side-channel": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
"integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3",
"side-channel-list": "^1.0.0",
"side-channel-map": "^1.0.1",
"side-channel-weakmap": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-list": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
"integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
"dependencies": {
"es-errors": "^1.3.0",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-map": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
"integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/side-channel-weakmap": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
"integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dependencies": {
"call-bound": "^1.0.2",
"es-errors": "^1.3.0",
"get-intrinsic": "^1.2.5",
"object-inspect": "^1.13.3",
"side-channel-map": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/signal-exit": {
"version": "3.0.7",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
"integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true
},
"node_modules/simple-concat": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
"integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true
},
"node_modules/simple-get": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
"integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"peer": true,
"dependencies": {
"decompress-response": "^6.0.0",
"once": "^1.3.1",
"simple-concat": "^1.0.0"
}
},
"node_modules/simple-swizzle": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
"integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
"peer": true,
"dependencies": {
"is-arrayish": "^0.3.1"
}
},
"node_modules/simple-swizzle/node_modules/is-arrayish": {
"version": "0.3.2",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
"integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
"peer": true
},
"node_modules/sisteransi": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
"integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg=="
},
"node_modules/slash": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
"engines": {
"node": ">=8"
}
},
- "node_modules/slice-ansi": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz",
- "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "astral-regex": "^2.0.0",
- "is-fullwidth-code-point": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/slice-ansi?sponsor=1"
- }
- },
"node_modules/slick": {
"version": "1.12.2",
"resolved": "https://registry.npmjs.org/slick/-/slick-1.12.2.tgz",
"integrity": "sha512-4qdtOGcBjral6YIBCWJ0ljFSKNLz9KkhbWtuGvUyRowl1kxfuE1x/Z/aJcaiilpb3do9bl5K7/1h9XC5wWpY/A==",
"peer": true,
"engines": {
"node": "*"
}
},
"node_modules/smartcrop": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/smartcrop/-/smartcrop-2.0.5.tgz",
"integrity": "sha512-aXoHTM8XlC51g96kgZkYxZ2mx09/ibOrIVLiUNOFozV/MHmFSgEr1/5CKVBoFD5vd+re2wSy0xra21CyjRITzA==",
"peer": true
},
"node_modules/smartcrop-sharp": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/smartcrop-sharp/-/smartcrop-sharp-2.0.8.tgz",
"integrity": "sha512-0rpK/ddGAx7ou6YqqvJRkw/xyR4qgqmJeUQ2EWDnN3hSuJUk4InPGE6Sa45+TYOfGEEQJrchjF1ujBPMhoe9iA==",
"peer": true,
"dependencies": {
"smartcrop": "^2.0.5"
},
"peerDependencies": {
"sharp": "^0.32.5"
}
},
"node_modules/source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
"dev": true,
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
"node_modules/sparkles": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/sparkles/-/sparkles-1.0.1.tgz",
"integrity": "sha512-dSO0DDYUahUt/0/pD/Is3VIm5TGJjludZ0HVymmhYF6eNA53PVLhnUk0znSYbH8IYBuJdCE+1luR22jNLMaQdw==",
"engines": {
"node": ">= 0.10"
}
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"peer": true,
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/spawn-wrap": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/spawn-wrap/-/spawn-wrap-2.0.0.tgz",
"integrity": "sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg==",
"dev": true,
"dependencies": {
"foreground-child": "^2.0.0",
"is-windows": "^1.0.2",
"make-dir": "^3.0.0",
"rimraf": "^3.0.0",
"signal-exit": "^3.0.2",
"which": "^2.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/split2": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
"integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
"peer": true,
"engines": {
"node": ">= 10.x"
}
},
"node_modules/sprintf-js": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
"dev": true
},
"node_modules/sshpk": {
"version": "1.18.0",
"resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.18.0.tgz",
"integrity": "sha512-2p2KJZTSqQ/I3+HX42EpYOa2l3f8Erv8MWKsy2I9uf4wA7yFIkXRffYdsx86y6z4vHtV8u7g+pPlr8/4ouAxsQ==",
"dependencies": {
"asn1": "~0.2.3",
"assert-plus": "^1.0.0",
"bcrypt-pbkdf": "^1.0.0",
"dashdash": "^1.12.0",
"ecc-jsbn": "~0.1.1",
"getpass": "^0.1.1",
"jsbn": "~0.1.0",
"safer-buffer": "^2.0.2",
"tweetnacl": "~0.14.0"
},
"bin": {
"sshpk-conv": "bin/sshpk-conv",
"sshpk-sign": "bin/sshpk-sign",
"sshpk-verify": "bin/sshpk-verify"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/stat-mode": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz",
"integrity": "sha512-o+7DC0OM5Jt3+gratXXqfXf62V/CBoqQbT7Kp7jCxTYW2PLOB2/ZSGIfm9T5/QZe1Vw1MCbu6DoB6JnhVtxcJw=="
},
"node_modules/statuses": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/stimulus": {
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/stimulus/-/stimulus-3.2.2.tgz",
"integrity": "sha512-sEGK0ofeMuW+B2oPLTigCqxl47P9vRfZxeqzY5Hk1u0QPWS8DZhW+VOEEyngtzdHM+MutXKGBT8BkUKoA0060Q==",
"license": "MIT",
"peer": true,
"dependencies": {
"@hotwired/stimulus": "^3.2.2",
"@hotwired/stimulus-webpack-helpers": "^1.0.0"
}
},
"node_modules/stream-combiner2": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz",
"integrity": "sha512-3PnJbYgS56AeWgtKF5jtJRT6uFJe56Z0Hc5Ngg/6sI6rIt8iiMBTa9cvdyFfpMQjaVHr8dusbNeFGIIonxOvKw==",
"dependencies": {
"duplexer2": "~0.1.0",
"readable-stream": "^2.0.2"
}
},
"node_modules/stream-shift": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
"integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ=="
},
"node_modules/streamx": {
"version": "2.22.1",
"resolved": "https://registry.npmjs.org/streamx/-/streamx-2.22.1.tgz",
"integrity": "sha512-znKXEBxfatz2GBNK02kRnCXjV+AA4kjZIUxeWSr3UGirZMJfTE9uiwKHobnbgxWyL/JWro8tTq+vOqAK1/qbSA==",
"peer": true,
"dependencies": {
"fast-fifo": "^1.3.2",
"text-decoder": "^1.1.0"
},
"optionalDependencies": {
"bare-events": "^2.2.0"
}
},
"node_modules/string_decoder": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
"dependencies": {
"safe-buffer": "~5.1.0"
}
},
"node_modules/string_decoder/node_modules/safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"node_modules/string-width": {
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/string-width-cjs": {
"name": "string-width",
"version": "4.2.3",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"peer": true,
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
"strip-ansi": "^6.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-ansi-cjs": {
"name": "strip-ansi",
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"peer": true,
"dependencies": {
"ansi-regex": "^5.0.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
"integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/strip-bom-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz",
"integrity": "sha512-7jfJB9YpI2Z0aH3wu10ZqitvYJaE0s5IzFuWE+0pbb4Q/armTloEUShymkDO47YSLnjAW52mlXT//hs9wXNNJQ==",
"dependencies": {
"first-chunk-stream": "^1.0.0",
"strip-bom": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-bom-stream/node_modules/strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
"dependencies": {
"is-utf8": "^0.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-dirs": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz",
"integrity": "sha512-+0QvOUTIs3xMridKraQAUSIp/kq7FRt/QjevB40+U6qJfeuPpTDQENFVfAbfZp59GpJkxY+yMdjR5cgKZyR2vg==",
"dependencies": {
"chalk": "^1.0.0",
"get-stdin": "^4.0.1",
"is-absolute": "^0.1.5",
"is-natural-number": "^2.0.0",
"minimist": "^1.1.0",
"sum-up": "^1.0.1"
},
"bin": {
"strip-dirs": "cli.js"
}
},
"node_modules/strip-dirs/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-dirs/node_modules/ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-dirs/node_modules/chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"dependencies": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-dirs/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/strip-dirs/node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-dirs/node_modules/supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/strip-json-comments": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/strip-outer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz",
"integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==",
"dependencies": {
"escape-string-regexp": "^1.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/strip-outer/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/sum-up": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz",
"integrity": "sha512-zw5P8gnhiqokJUWRdR6F4kIIIke0+ubQSGyYUY506GCbJWtV7F6Xuy0j6S125eSX2oF+a8KdivsZ8PlVEH0Mcw==",
"dependencies": {
"chalk": "^1.0.0"
}
},
"node_modules/sum-up/node_modules/ansi-regex": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
"integrity": "sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sum-up/node_modules/ansi-styles": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.1.tgz",
"integrity": "sha512-kmCevFghRiWM7HB5zTPULl4r9bVFSWjz62MhqizDGUrq2NWuNMQyuv4tHHoKJHs69M/MF64lEcHdYIocrdWQYA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sum-up/node_modules/chalk": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-1.1.3.tgz",
"integrity": "sha512-U3lRVLMSlsCfjqYPbLyVv11M9CPW4I728d6TCKMAOJueEeB9/8o+eSsMnxPJD+Q+K909sdESg7C+tIkoH6on1A==",
"dependencies": {
"ansi-styles": "^2.2.1",
"escape-string-regexp": "^1.0.2",
"has-ansi": "^2.0.0",
"strip-ansi": "^3.0.0",
"supports-color": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sum-up/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/sum-up/node_modules/strip-ansi": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
"integrity": "sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
"dependencies": {
"ansi-regex": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/sum-up/node_modules/supports-color": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-2.0.0.tgz",
"integrity": "sha512-KKNVtd6pCYgPIKU4cp2733HWYCpplQhddZLBUryaAHou723x+FRzQ5Df824Fj+IyyuiQTRoub4SnIFfIcrp70g==",
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/supports-color": {
"version": "8.1.1",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
"integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"peer": true,
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/table": {
- "version": "6.9.0",
- "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz",
- "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==",
+ "node_modules/synckit": {
+ "version": "0.11.11",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.11.tgz",
+ "integrity": "sha512-MeQTA1r0litLUf0Rp/iisCaL8761lKAZHaimlbGK4j0HysC4PLfqygQj9srcs0m2RdtDYnF8UuYyKpbjHYp7Jw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^8.0.1",
- "lodash.truncate": "^4.4.2",
- "slice-ansi": "^4.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1"
+ "@pkgr/core": "^0.2.9"
},
"engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/table/node_modules/ajv": {
- "version": "8.17.1",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
- "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
- "dev": true,
- "dependencies": {
- "fast-deep-equal": "^3.1.3",
- "fast-uri": "^3.0.1",
- "json-schema-traverse": "^1.0.0",
- "require-from-string": "^2.0.2"
+ "node": "^14.18.0 || >=16.0.0"
},
"funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
+ "url": "https://opencollective.com/synckit"
}
},
- "node_modules/table/node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "dev": true
- },
"node_modules/tar-fs": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.1.0.tgz",
"integrity": "sha512-5Mty5y/sOF1YWj1J6GiBodjlDc05CUR8PKXrsnFAiSG0xA+GHeWLovaZPYUDXkH/1iKRf2+M5+OrRgzC7O9b7w==",
"peer": true,
"dependencies": {
"pump": "^3.0.0",
"tar-stream": "^3.1.5"
},
"optionalDependencies": {
"bare-fs": "^4.0.1",
"bare-path": "^3.0.0"
}
},
"node_modules/tar-fs/node_modules/tar-stream": {
"version": "3.1.7",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz",
"integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==",
"peer": true,
"dependencies": {
"b4a": "^1.6.4",
"fast-fifo": "^1.2.0",
"streamx": "^2.15.0"
}
},
"node_modules/tar-stream": {
"version": "1.6.2",
"resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.2.tgz",
"integrity": "sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A==",
"dependencies": {
"bl": "^1.0.0",
"buffer-alloc": "^1.2.0",
"end-of-stream": "^1.0.0",
"fs-constants": "^1.0.0",
"readable-stream": "^2.3.0",
"to-buffer": "^1.1.1",
"xtend": "^4.0.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/temp-dir": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-3.0.0.tgz",
"integrity": "sha512-nHc6S/bwIilKHNRgK/3jlhDoIHcp45YgyiwcAk46Tr0LfEqGBVpmiAyuiuxeVE44m3mXnEeVhaipLOEWmH+Njw==",
"engines": {
"node": ">=14.16"
}
},
"node_modules/tempfile": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/tempfile/-/tempfile-5.0.0.tgz",
"integrity": "sha512-bX655WZI/F7EoTDw9JvQURqAXiPHi8o8+yFxPF2lWYyz1aHnmMRuXWqL6YB6GmeO0o4DIYWHLgGNi/X64T+X4Q==",
"dependencies": {
"temp-dir": "^3.0.0"
},
"engines": {
"node": ">=14.18"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/tempstream": {
"version": "0.4.6",
"resolved": "https://registry.npmjs.org/tempstream/-/tempstream-0.4.6.tgz",
"integrity": "sha512-UpRUWkgm6CdbwrBHRCiKmYwTSXvLsoROOZFwNmn+o2OXYd67yLe0/oK05ezgtD6YjkKy9Hrel36VSyaRlgsQUQ==",
"dependencies": {
"classnames": "^2.5.1",
"escape-goat": "^4.0.0"
}
},
"node_modules/test-exclude": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
"integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
"dev": true,
"dependencies": {
"@istanbuljs/schema": "^0.1.2",
"glob": "^7.1.4",
"minimatch": "^3.0.4"
},
"engines": {
"node": ">=8"
}
},
"node_modules/test-exclude/node_modules/glob": {
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
"deprecated": "Glob versions prior to v9 are no longer supported",
"dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
"minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
"engines": {
"node": "*"
},
"funding": {
"url": "https://github.com/sponsors/isaacs"
}
},
"node_modules/text-decoder": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.3.tgz",
"integrity": "sha512-3/o9z3X0X0fTupwsYvR03pJ/DjWuqqrfwBgTQzdWDiQSm9KitAyz/9WqsT2JQW7KV2m+bC2ol/zqpW37NHxLaA==",
"peer": true,
"dependencies": {
"b4a": "^1.6.4"
}
},
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
- },
"node_modules/through2": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
"integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
"dependencies": {
"readable-stream": ">=1.0.33-1 <1.1.0-0",
"xtend": ">=4.0.0 <4.1.0-0"
}
},
"node_modules/through2-filter": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz",
"integrity": "sha512-miwWajb1B80NvIVKXFPN/o7+vJc4jYUvnZCwvhicRAoTxdD9wbcjri70j+BenCrN/JXEPKDjhpw4iY7yiNsCGg==",
"dependencies": {
"through2": "~2.0.0",
"xtend": "~4.0.0"
}
},
"node_modules/through2-filter/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/through2/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
"integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
},
"node_modules/through2/node_modules/readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
"isarray": "0.0.1",
"string_decoder": "~0.10.x"
}
},
"node_modules/through2/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
"integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
},
"node_modules/time-stamp": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/time-stamp/-/time-stamp-1.1.0.tgz",
"integrity": "sha512-gLCeArryy2yNTRzTGKbZbloctj64jkZ57hj5zdraXue6aFgd6PmvVtEyiUU+hvU0v7q08oVv8r8ev0tRo6bvgw==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/timed-out": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/timed-out/-/timed-out-2.0.0.tgz",
"integrity": "sha512-pqqJOi1rF5zNs/ps4vmbE4SFCrM4iR7LW+GHAsHqO/EumqbIWceioevYLM5xZRgQSH6gFgL9J/uB7EcJhQ9niQ==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/tiny-glob": {
"version": "0.2.9",
"resolved": "https://registry.npmjs.org/tiny-glob/-/tiny-glob-0.2.9.tgz",
"integrity": "sha512-g/55ssRPUjShh+xkfx9UPDXqhckHEsHr4Vd9zX55oSdGZc/MD0m3sferOkwWtp98bv+kcVfEHtRJgBVJzelrzg==",
"dependencies": {
"globalyzer": "0.1.0",
"globrex": "^0.1.2"
}
},
"node_modules/to-absolute-glob": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz",
"integrity": "sha512-Vvl5x6zNf9iVG1QTWeknmWrKzZxaeKfIDRibrZCR3b2V/2NlFJuD2HV7P7AVjaKLZNqLPHqyr0jGrW0fTcxCPQ==",
"dependencies": {
"extend-shallow": "^2.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/to-buffer": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.1.tgz",
"integrity": "sha512-tB82LpAIWjhLYbqjx3X4zEeHN6M8CiuOEy2JY8SEQVdYRe3CCHOFaqrBW1doLDrfpWhplcW7BL+bO3/6S3pcDQ==",
"dependencies": {
"isarray": "^2.0.5",
"safe-buffer": "^5.2.1",
"typed-array-buffer": "^1.0.3"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/to-buffer/node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
"integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
},
"node_modules/to-regex-range": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
"dependencies": {
"is-number": "^7.0.0"
},
"engines": {
"node": ">=8.0"
}
},
"node_modules/toidentifier": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"engines": {
"node": ">=0.6"
}
},
"node_modules/tough-cookie": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"dependencies": {
"psl": "^1.1.28",
"punycode": "^2.1.1"
},
"engines": {
"node": ">=0.8"
}
},
"node_modules/tr46": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-5.1.1.tgz",
"integrity": "sha512-hdF5ZgjTqgAntKkklYw0R03MG2x/bSzTtkxmIRw/sTNV8YXsCJ1tfLAX23lhxhHJlEf3CRCOCGGWw3vI3GaSPw==",
"peer": true,
"dependencies": {
"punycode": "^2.3.1"
},
"engines": {
"node": ">=18"
}
},
"node_modules/trim-repeated": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz",
"integrity": "sha512-pkonvlKk8/ZuR0D5tLW8ljt5I8kmxp2XKymhepUeOdCEfKpZaktSArkLHZt76OB1ZvO9bssUsDty4SWhLvZpLg==",
"dependencies": {
"escape-string-regexp": "^1.0.2"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/trim-repeated/node_modules/escape-string-regexp": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
"integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"engines": {
"node": ">=0.8.0"
}
},
+ "node_modules/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
"node_modules/ts-node": {
"version": "10.9.2",
"resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
"integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
"dev": true,
"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"
},
"bin": {
"ts-node": "dist/bin.js",
"ts-node-cwd": "dist/bin-cwd.js",
"ts-node-esm": "dist/bin-esm.js",
"ts-node-script": "dist/bin-script.js",
"ts-node-transpile-only": "dist/bin-transpile.js",
"ts-script": "dist/bin-script-deprecated.js"
},
"peerDependencies": {
"@swc/core": ">=1.2.50",
"@swc/wasm": ">=1.2.50",
"@types/node": "*",
"typescript": ">=2.7"
},
"peerDependenciesMeta": {
"@swc/core": {
"optional": true
},
"@swc/wasm": {
"optional": true
}
}
},
- "node_modules/ts-node/node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
"node_modules/ts-node/node_modules/diff": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
"integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
"dev": true,
"engines": {
"node": ">=0.3.1"
}
},
"node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
"dev": true
},
"node_modules/tsscmp": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/tsscmp/-/tsscmp-1.0.6.tgz",
"integrity": "sha512-LxhtAkPDTkVCMQjt2h6eBVY28KCjikZqZfMcC15YBeNjkgUpdCfBu5HoiOTDu86v6smE8yOjyEktJ8hlbANHQA==",
"peer": true,
"engines": {
"node": ">=0.6.x"
}
},
"node_modules/tsutils": {
"version": "3.21.0",
"resolved": "https://registry.npmjs.org/tsutils/-/tsutils-3.21.0.tgz",
"integrity": "sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA==",
"dev": true,
"dependencies": {
"tslib": "^1.8.1"
},
"engines": {
"node": ">= 6"
},
"peerDependencies": {
"typescript": ">=2.8.0 || >= 3.2.0-dev || >= 3.3.0-dev || >= 3.4.0-dev || >= 3.5.0-dev || >= 3.6.0-dev || >= 3.6.0-beta || >= 3.7.0-dev || >= 3.7.0-beta"
}
},
"node_modules/tunnel-agent": {
"version": "0.4.3",
"resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz",
"integrity": "sha512-e0IoVDWx8SDHc/hwFTqJDQ7CCDTEeGhmcT9jkWJjoGQSpgBz20nAMr80E3Tpk7PatJ1b37DQDgJR3CNSzcMOZQ==",
"engines": {
"node": "*"
}
},
"node_modules/tweetnacl": {
"version": "0.14.5",
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
"integrity": "sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA=="
},
"node_modules/type-check": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
"integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
"dev": true,
"dependencies": {
"prelude-ls": "^1.2.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
- "node_modules/type-fest": {
- "version": "0.20.2",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz",
- "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
"node_modules/type-is": {
"version": "1.6.18",
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/typed-array-buffer": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
"integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
"dependencies": {
"call-bound": "^1.0.3",
"es-errors": "^1.3.0",
"is-typed-array": "^1.1.14"
},
"engines": {
"node": ">= 0.4"
}
},
"node_modules/typedarray": {
"version": "0.0.6",
"resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
"integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
},
"node_modules/typedarray-to-buffer": {
"version": "3.1.5",
"resolved": "https://registry.npmjs.org/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz",
"integrity": "sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q==",
"dev": true,
"dependencies": {
"is-typedarray": "^1.0.0"
}
},
"node_modules/typedoc": {
"version": "0.17.8",
"resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.17.8.tgz",
"integrity": "sha512-/OyrHCJ8jtzu+QZ+771YaxQ9s4g5Z3XsQE3Ma7q+BL392xxBn4UMvvCdVnqKC2T/dz03/VXSLVKOP3lHmDdc/w==",
"peer": true,
"dependencies": {
"fs-extra": "^8.1.0",
"handlebars": "^4.7.6",
"highlight.js": "^10.0.0",
"lodash": "^4.17.15",
"lunr": "^2.3.8",
"marked": "1.0.0",
"minimatch": "^3.0.0",
"progress": "^2.0.3",
"shelljs": "^0.8.4",
"typedoc-default-themes": "^0.10.2"
},
"bin": {
"typedoc": "bin/typedoc"
},
"engines": {
"node": ">= 8.0.0"
},
"peerDependencies": {
"typescript": ">=3.8.3"
}
},
"node_modules/typedoc-default-themes": {
"version": "0.10.2",
"resolved": "https://registry.npmjs.org/typedoc-default-themes/-/typedoc-default-themes-0.10.2.tgz",
"integrity": "sha512-zo09yRj+xwLFE3hyhJeVHWRSPuKEIAsFK5r2u47KL/HBKqpwdUSanoaz5L34IKiSATFrjG5ywmIu98hPVMfxZg==",
"peer": true,
"dependencies": {
"lunr": "^2.3.8"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/typedoc/node_modules/fs-extra": {
"version": "8.1.0",
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
"peer": true,
"dependencies": {
"graceful-fs": "^4.2.0",
"jsonfile": "^4.0.0",
"universalify": "^0.1.0"
},
"engines": {
"node": ">=6 <7 || >=8"
}
},
"node_modules/typedoc/node_modules/jsonfile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
"peer": true,
"optionalDependencies": {
"graceful-fs": "^4.1.6"
}
},
"node_modules/typescript": {
"version": "5.9.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.2.tgz",
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=14.17"
}
},
+ "node_modules/typescript-eslint": {
+ "version": "8.44.0",
+ "resolved": "https://registry.npmjs.org/typescript-eslint/-/typescript-eslint-8.44.0.tgz",
+ "integrity": "sha512-ib7mCkYuIzYonCq9XWF5XNw+fkj2zg629PSa9KNIQ47RXFF763S5BIX4wqz1+FLPogTZoiw8KmCiRPRa8bL3qw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/eslint-plugin": "8.44.0",
+ "@typescript-eslint/parser": "8.44.0",
+ "@typescript-eslint/typescript-estree": "8.44.0",
+ "@typescript-eslint/utils": "8.44.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
"node_modules/ufo": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/ufo/-/ufo-1.6.1.tgz",
"integrity": "sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA=="
},
"node_modules/uglify-js": {
"version": "3.19.3",
"resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
"integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
"peer": true,
"bin": {
"uglifyjs": "bin/uglifyjs"
},
"engines": {
"node": ">=0.8.0"
}
},
"node_modules/undici-types": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.21.0.tgz",
"integrity": "sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ=="
},
"node_modules/unique-stream": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.3.1.tgz",
"integrity": "sha512-2nY4TnBE70yoxHkDli7DMazpWiP7xMdCYqU2nBRO0UB+ZpEkGsSija7MvmvnZFUeC+mrgiUfcHSr3LmRFIg4+A==",
"dependencies": {
"json-stable-stringify-without-jsonify": "^1.0.1",
"through2-filter": "^3.0.0"
}
},
"node_modules/unique-stream/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/unique-stream/node_modules/through2-filter": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-3.0.0.tgz",
"integrity": "sha512-jaRjI2WxN3W1V8/FMZ9HKIBXixtiqs3SQSX4/YGIiP3gL6djW48VoZq9tDqeCWs3MT8YY5wb/zli8VW8snY1CA==",
"dependencies": {
"through2": "~2.0.0",
"xtend": "~4.0.0"
}
},
"node_modules/universalify": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
"peer": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/unpipe": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/unzip-response": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz",
"integrity": "sha512-pwCcjjhEcpW45JZIySExBHYv5Y9EeL2OIGEfrSKp2dMUFGFv4CpvZkwJbVge8OvGH2BNNtJBx67DuKuJhf+N5Q==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/update-browserslist-db": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz",
"integrity": "sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw==",
"dev": true,
"funding": [
{
"type": "opencollective",
"url": "https://opencollective.com/browserslist"
},
{
"type": "tidelift",
"url": "https://tidelift.com/funding/github/npm/browserslist"
},
{
"type": "github",
"url": "https://github.com/sponsors/ai"
}
],
"dependencies": {
"escalade": "^3.2.0",
"picocolors": "^1.1.1"
},
"bin": {
"update-browserslist-db": "cli.js"
},
"peerDependencies": {
"browserslist": ">= 4.21.0"
}
},
"node_modules/upper-case": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
"integrity": "sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
"peer": true
},
"node_modules/uri-js": {
"version": "4.4.1",
"resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
"integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
"dependencies": {
"punycode": "^2.1.0"
}
},
"node_modules/url-parse-lax": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz",
"integrity": "sha512-BVA4lR5PIviy2PMseNd2jbFQ+jwSwQGdJejf5ctd1rEXt0Ypd7yanUK9+lYechVlN5VaTJGsu2U/3MDDu6KgBA==",
"dependencies": {
"prepend-http": "^1.0.1"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/useragent": {
"version": "2.0.9",
"resolved": "https://registry.npmjs.org/useragent/-/useragent-2.0.9.tgz",
"integrity": "sha512-VxzjR7qj3CJdFLuodfsC2M1E26uAxcoN2j/LK/NawLvq8K1EC5u3M5PHmhMEOd5kfaA3OcsM63CF9dgtSaWF6Q==",
"dependencies": {
"lru-cache": "2.2.x"
}
},
"node_modules/useragent/node_modules/lru-cache": {
"version": "2.2.4",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-2.2.4.tgz",
"integrity": "sha512-Q5pAgXs+WEAfoEdw2qKQhNFFhMoFMTYqRVKKUMnzuiR7oKFHS7fWo848cPcTKw+4j/IdN17NyzdhVKgabFV0EA=="
},
"node_modules/util-deprecate": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
},
"node_modules/uuid": {
"version": "9.0.1",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
"integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
"funding": [
"https://github.com/sponsors/broofa",
"https://github.com/sponsors/ctavan"
],
"bin": {
"uuid": "dist/bin/uuid"
}
},
- "node_modules/v8-compile-cache": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.4.0.tgz",
- "integrity": "sha512-ocyWc3bAHBB/guyqJQVI5o4BZkPhznPYUG2ea80Gond/BgNWpap8TOmLSeeQG7bnh2KMISxskdADG59j7zruhw==",
- "dev": true
- },
"node_modules/v8-compile-cache-lib": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
"integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
"dev": true
},
"node_modules/vali-date": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz",
"integrity": "sha512-sgECfZthyaCKW10N0fm27cg8HYTFK5qMWgypqkXMQ4Wbl/zZKx7xZICgcoxIIE+WFAP/MBL2EFwC/YvLxw3Zeg==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/valid-data-url": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/valid-data-url/-/valid-data-url-3.0.1.tgz",
"integrity": "sha512-jOWVmzVceKlVVdwjNSenT4PbGghU0SBIizAev8ofZVgivk/TVHXSbNL8LP6M3spZvkR9/QolkyJavGSX5Cs0UA==",
"peer": true,
"engines": {
"node": ">=10"
}
},
"node_modules/vary": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"peer": true,
"engines": {
"node": ">= 0.8"
}
},
"node_modules/verror": {
"version": "1.10.0",
"resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
"integrity": "sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
"engines": [
"node >=0.6.0"
],
"dependencies": {
"assert-plus": "^1.0.0",
"core-util-is": "1.0.2",
"extsprintf": "^1.2.0"
}
},
"node_modules/verror/node_modules/core-util-is": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
"integrity": "sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ=="
},
"node_modules/vinyl": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz",
"integrity": "sha512-Ci3wnR2uuSAWFMSglZuB8Z2apBdtOyz8CV7dC6/U1XbltXBC+IuutUkXQISz01P+US2ouBuesSbV6zILZ6BuzQ==",
"dependencies": {
"clone": "^1.0.0",
"clone-stats": "^0.0.1",
"replace-ext": "0.0.1"
},
"engines": {
"node": ">= 0.9"
}
},
"node_modules/vinyl-assign": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz",
"integrity": "sha512-jUVK1MkXgsZDdyUAy0rnrcmPeuR/ZLwsaS377zaaciz9SoDRVPIjHlUcYVcUAzLD+AolsLxMMwSe/VP77lAvow==",
"dependencies": {
"object-assign": "^4.0.1",
"readable-stream": "^2.0.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/vinyl-fs": {
"version": "2.4.4",
"resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz",
"integrity": "sha512-lxMlQW/Wxk/pwhooY3Ut0Q11OH5ZvZfV0Gg1c306fBNWznQ6ZeQaCdE7XX0O/PpGSqgAsHMBxwFgcGxiYW3hZg==",
"dependencies": {
"duplexify": "^3.2.0",
"glob-stream": "^5.3.2",
"graceful-fs": "^4.0.0",
"gulp-sourcemaps": "1.6.0",
"is-valid-glob": "^0.3.0",
"lazystream": "^1.0.0",
"lodash.isequal": "^4.0.0",
"merge-stream": "^1.0.0",
"mkdirp": "^0.5.0",
"object-assign": "^4.0.0",
"readable-stream": "^2.0.4",
"strip-bom": "^2.0.0",
"strip-bom-stream": "^1.0.0",
"through2": "^2.0.0",
"through2-filter": "^2.0.0",
"vali-date": "^1.0.0",
"vinyl": "^1.0.0"
},
"engines": {
"node": ">=0.10"
}
},
"node_modules/vinyl-fs/node_modules/strip-bom": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz",
"integrity": "sha512-kwrX1y7czp1E69n2ajbG65mIo9dqvJ+8aBQXOGVxqwvNbsXdFM6Lq37dLAY3mknUwru8CfcCbfOLL/gMo+fi3g==",
"dependencies": {
"is-utf8": "^0.2.0"
},
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/vinyl-fs/node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
"node_modules/vinyl/node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"engines": {
"node": ">=0.8"
}
},
"node_modules/wait-port": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/wait-port/-/wait-port-1.1.0.tgz",
"integrity": "sha512-3e04qkoN3LxTMLakdqeWth8nih8usyg+sf1Bgdf9wwUkp05iuK1eSY/QpLvscT/+F/gA89+LpUmmgBtesbqI2Q==",
"dev": true,
"dependencies": {
"chalk": "^4.1.2",
"commander": "^9.3.0",
"debug": "^4.3.4"
},
"bin": {
"wait-port": "bin/wait-port.js"
},
"engines": {
"node": ">=10"
}
},
"node_modules/wait-port/node_modules/chalk": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
"integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/wait-port/node_modules/commander": {
"version": "9.5.0",
"resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz",
"integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==",
"dev": true,
"engines": {
"node": "^12.20.0 || >=14"
}
},
"node_modules/wait-port/node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
"dependencies": {
"has-flag": "^4.0.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/ware": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz",
"integrity": "sha512-Y2HUDMktriUm+SR2gZWxlrszcgtXExlhQYZ8QJNYbl22jum00KIUcHJ/h/sdAXhWTJcbSkiMYN9Z2tWbWYSrrw==",
"dependencies": {
"wrap-fn": "^0.1.0"
}
},
"node_modules/wcag-contrast": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/wcag-contrast/-/wcag-contrast-3.0.0.tgz",
"integrity": "sha512-RWbpg/S7FOXDCwqC2oFhN/vh8dHzj0OS6dpyOSDHyQFSmqmR+lAUStV/ziTT1GzDqL9wol+nZQB4vCi5yEak+w==",
"dependencies": {
"relative-luminance": "^2.0.0"
}
},
"node_modules/web-resource-inliner": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/web-resource-inliner/-/web-resource-inliner-6.0.1.tgz",
"integrity": "sha512-kfqDxt5dTB1JhqsCUQVFDj0rmY+4HLwGQIsLPbyrsN9y9WV/1oFDSx3BQ4GfCv9X+jVeQ7rouTqwK53rA/7t8A==",
"peer": true,
"dependencies": {
"ansi-colors": "^4.1.1",
"escape-goat": "^3.0.0",
"htmlparser2": "^5.0.0",
"mime": "^2.4.6",
"node-fetch": "^2.6.0",
"valid-data-url": "^3.0.0"
},
"engines": {
"node": ">=10.0.0"
}
},
"node_modules/web-resource-inliner/node_modules/dom-serializer": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
"integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/dom-serializer/node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"peer": true,
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/domhandler": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.3.0.tgz",
"integrity": "sha512-J1C5rIANUbuYK+FuFL98650rihynUOEzRLxW+90bKZRWB6A1X1Tf82GxR1qAWLyfNPRvjqfip3Q5tdYlmAa9lA==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"peer": true,
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
"domhandler": "^4.2.0"
},
"funding": {
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/domutils/node_modules/domhandler": {
"version": "4.3.1",
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
"integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"peer": true,
"dependencies": {
"domelementtype": "^2.2.0"
},
"engines": {
"node": ">= 4"
},
"funding": {
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/entities": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
"integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"peer": true,
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/web-resource-inliner/node_modules/escape-goat": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/escape-goat/-/escape-goat-3.0.0.tgz",
"integrity": "sha512-w3PwNZJwRxlp47QGzhuEBldEqVHHhh8/tIPcl6ecf2Bou99cdAt0knihBV0Ecc7CGxYduXVBDheH1K2oADRlvw==",
"peer": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/web-resource-inliner/node_modules/htmlparser2": {
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-5.0.1.tgz",
"integrity": "sha512-vKZZra6CSe9qsJzh0BjBGXo8dvzNsq/oGvsjfRdOrrryfeD9UOBEEQdeoqCRmKZchF5h2zOBMQ6YuQ0uRUmdbQ==",
"peer": true,
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^3.3.0",
"domutils": "^2.4.2",
"entities": "^2.0.0"
},
"funding": {
"url": "https://github.com/fb55/htmlparser2?sponsor=1"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"peer": true,
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-url": {
"version": "14.2.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-14.2.0.tgz",
"integrity": "sha512-De72GdQZzNTUBBChsXueQUnPKDkg/5A5zp7pFDuQAj5UFoENpiACU0wlCvzpAGnTkj++ihpKwKyYewn/XNUbKw==",
"peer": true,
"dependencies": {
"tr46": "^5.1.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=18"
}
},
"node_modules/which": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
"integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dependencies": {
"isexe": "^2.0.0"
},
"bin": {
"node-which": "bin/node-which"
},
"engines": {
"node": ">= 8"
}
},
"node_modules/which-module": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.1.tgz",
"integrity": "sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ==",
"dev": true
},
"node_modules/which-typed-array": {
"version": "1.1.19",
"resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
"integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
"dependencies": {
"available-typed-arrays": "^1.0.7",
"call-bind": "^1.0.8",
"call-bound": "^1.0.4",
"for-each": "^0.3.5",
"get-proto": "^1.0.1",
"gopd": "^1.2.0",
"has-tostringtag": "^1.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
"integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
"dev": true,
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/wordwrap": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
"peer": true
},
"node_modules/workerpool": {
"version": "6.5.1",
"resolved": "https://registry.npmjs.org/workerpool/-/workerpool-6.5.1.tgz",
"integrity": "sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA==",
"dev": true
},
"node_modules/wrap-ansi": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-ansi-cjs": {
"name": "wrap-ansi",
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
"integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
"peer": true,
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrap-fn": {
"version": "0.1.5",
"resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz",
"integrity": "sha512-xDLdGx0M8JQw9QDAC9s5NUxtg9MI09F6Vbxa2LYoSoCvzJnx2n81YMIfykmXEGsUvuLaxnblJTzhSOjUOX37ag==",
"dependencies": {
"co": "3.1.0"
}
},
"node_modules/wrap-fn/node_modules/co": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz",
"integrity": "sha512-CQsjCRiNObI8AtTsNIBDRMQ4oMR83CzEswHYahClvul7gKk+lDQiOKv+5qh7LQWf5sh6jkZNispz/QlsZxyNgA=="
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
"node_modules/write-file-atomic": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-3.0.3.tgz",
"integrity": "sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==",
"dev": true,
"dependencies": {
"imurmurhash": "^0.1.4",
"is-typedarray": "^1.0.0",
"signal-exit": "^3.0.2",
"typedarray-to-buffer": "^3.1.5"
}
},
"node_modules/ws": {
"version": "8.18.3",
"resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
"integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
"engines": {
"node": ">=10.0.0"
},
"peerDependencies": {
"bufferutil": "^4.0.1",
"utf-8-validate": ">=5.0.2"
},
"peerDependenciesMeta": {
"bufferutil": {
"optional": true
},
"utf-8-validate": {
"optional": true
}
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
"engines": {
"node": ">=0.4"
}
},
"node_modules/xxhashjs": {
"version": "0.2.2",
"resolved": "https://registry.npmjs.org/xxhashjs/-/xxhashjs-0.2.2.tgz",
"integrity": "sha512-AkTuIuVTET12tpsVIQo+ZU6f/qDmKuRUcjaqR+OIvm+aCBsZ95i7UVY5WJ9TMsSaZ0DA2WxoZ4acu0sPH+OKAw==",
"peer": true,
"dependencies": {
"cuint": "^0.2.2"
}
},
"node_modules/y18n": {
"version": "5.0.8",
"resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
"integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
"engines": {
"node": ">=10"
}
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
"dev": true
},
"node_modules/yargs": {
"version": "17.7.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
"integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
"dependencies": {
"cliui": "^8.0.1",
"escalade": "^3.1.1",
"get-caller-file": "^2.0.5",
"require-directory": "^2.1.1",
"string-width": "^4.2.3",
"y18n": "^5.0.5",
"yargs-parser": "^21.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/yargs-parser": {
"version": "20.2.9",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-unparser": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/yargs-unparser/-/yargs-unparser-2.0.0.tgz",
"integrity": "sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA==",
"dev": true,
"dependencies": {
"camelcase": "^6.0.0",
"decamelize": "^4.0.0",
"flat": "^5.0.2",
"is-plain-obj": "^2.1.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/yargs-unparser/node_modules/camelcase": {
"version": "6.3.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yargs-unparser/node_modules/decamelize": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-4.0.0.tgz",
"integrity": "sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yargs-unparser/node_modules/is-plain-obj": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-2.1.0.tgz",
"integrity": "sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA==",
"dev": true,
"engines": {
"node": ">=8"
}
},
"node_modules/yargs/node_modules/yargs-parser": {
"version": "21.1.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
"integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
"engines": {
"node": ">=12"
}
},
"node_modules/yauzl": {
"version": "2.10.0",
"resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz",
"integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==",
"dependencies": {
"buffer-crc32": "~0.2.3",
"fd-slicer": "~1.1.0"
}
},
"node_modules/ylru": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/ylru/-/ylru-1.4.0.tgz",
"integrity": "sha512-2OQsPNEmBCvXuFlIni/a+Rn+R2pHW9INm0BxXJ4hVDA8TirqMj+J/Rp9ItLatT/5pZqWwefVrTQcHpixsxnVlA==",
"peer": true,
"engines": {
"node": ">= 4.0.0"
}
},
"node_modules/yn": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
"integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
"dev": true,
"engines": {
"node": ">=6"
}
},
"node_modules/yocto-queue": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
"integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
"dev": true,
"engines": {
"node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
}
}
}
diff --git a/package.json b/package.json
index 297073b..6ddc291 100644
--- a/package.json
+++ b/package.json
@@ -1,96 +1,97 @@
{
"name": "@sealcode/sealgen",
"version": "0.19.0",
"description": "Module to automate adding routes and collections to a sealious application",
"main": "lib/index.js",
"type": "module",
"scripts": {
"prebuild": "npm run lint && rm -rf lib",
"build": "node ./build.js",
"watch": "npm run build -- --watch",
"postbuild": "npm run build-types",
"pretest": "npm run build",
"test": "node test.cjs",
"typecheck": "tsc --noemit",
"build-types": "tsc --emitDeclarationOnly",
"prepare": "husky",
"lint": "eslint src",
"preinstrument": "npm run build && rm -fr .xunit coverage lib-instrumented",
"instrument": "npx nyc instrument --exclude \"\" lib lib-instrumented",
"pretest-reports": "npm run instrument",
"test-reports": "npx nyc --exclude \"\" ./node_modules/.bin/mocha --recursive --timeout=10000 --require source-map-support/register --reporter xunit --reporter-option output=.xunit 'lib-instrumented/**/*.test.js' --exit && nyc report --reporter clover --exclude \"\"",
"precover-html": "rm -rf coverate/lcov-report",
"cover-html": "npm run test-reports && nyc report --reporter lcov --exclude \"\" && xdg-open coverage/lcov-report/index.html"
},
"bin": {
"sealgen": "./lib/cli.js"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@playwright/test": "^1.30.0",
"@types/koa__router": "^12.0.4",
"@types/md5": "^2.3.5",
"@types/mocha": "^10.0.6",
"@types/node": "^20.8.4",
"@types/prettier": "^2.7.0",
"@types/prompts": "^2.0.14",
"@types/recursive-readdir": "^2.2.4",
"@types/wcag-contrast": "^3.0.3",
"@types/ws": "^8.5.10",
"@types/yargs": "^17.0.32",
- "@typescript-eslint/eslint-plugin": "^5.58.0",
- "@typescript-eslint/parser": "^5.58.0",
+ "@typescript-eslint/eslint-plugin": "^8.44.0",
+ "@typescript-eslint/parser": "^8.44.0",
"axios": "^1.6.7",
"chalk": "^5.3.0",
- "eslint": "^7.32.0",
- "eslint-config-prettier": "^8.3.0",
- "eslint-plugin-prettier": "^3.4.1",
+ "eslint": "^9.36.0",
+ "eslint-config-prettier": "^8.10.2",
+ "eslint-plugin-prettier": "^5.5.4",
"eslint-plugin-with-tsc-error": "^0.0.7",
"get-port": "^5.1.1",
"koa-body": "^5.0.0",
"mocha": "^10.4.0",
"mri": "^1.2.0",
"nyc": "^15.1.0",
"playwright": "^1.29.2",
"source-map-support": "^0.5.21",
"ts-node": "^10.9.1",
"typescript": "5.9",
+ "typescript-eslint": "^8.44.0",
"wait-port": "^1.0.4"
},
"types": "./@types/index.d.ts",
"dependencies": {
"@koa/router": "^12.0.1",
"@sealcode/file-manager": "^1.0.2",
"@sealcode/ts-predicates": "^0.4.3",
"chokidar": "^3.6.0",
"colord": "^2.9.3",
"deepmerge": "^4.3.1",
"esbuild": "^0.20.0",
"escape-goat": "^4.0.0",
"fonsta": "^1.1.1",
"google-fonts-helper": "^3.4.1",
"husky": "^9.1.7",
"is-what": "^4.1.16",
"js-convert-case": "^4.2.0",
"json5": "^2.2.3",
"locreq": "^3.0.0",
"md5": "^2.3.0",
"merge": "^2.1.1",
- "prettier": "^2.7.1",
+ "prettier": "^3.6.2",
"prompts": "^2.4.2",
"recursive-readdir": "^2.2.3",
"tempfile": "^5.0.0",
"tempstream": "^0.4.6",
"tiny-glob": "^0.2.9",
"wcag-contrast": "^3.0.0",
"ws": "^8.16.0",
"yargs": "^17.6.2"
},
"peerDependencies": {
"koa": "^2.13.0",
"koa-responsive-image-router": "^0.2.24",
- "sealious": "^0.21",
+ "sealious": "^0.21.20",
"stimulus": "^3.2.2"
}
}
diff --git a/src/add-collection.ts b/src/add-collection.ts
index 5c0c364..3d8fc32 100644
--- a/src/add-collection.ts
+++ b/src/add-collection.ts
@@ -1,51 +1,49 @@
import { resolve } from "path";
import _locreq from "locreq";
import { promises as fs, existsSync } from "fs";
import { collectionTemplate } from "./templates/collection.js";
import { generateCollections } from "./generate-collections.js";
import { toKebabCase, toPascalCase } from "js-convert-case";
const target_locreq = _locreq(process.cwd());
import prompts from "prompts";
import { formatWithPrettier } from "./utils/prettier.js";
export async function addCollection(
params: Record<string, string | boolean> = {}
): Promise<void> {
prompts.override(params);
const response = await prompts([
{
type: "text",
name: "collection_name",
message: "What's the name of the collection class: ",
validate: (s: string) =>
s.length > 3 ? true : "Should be at least 3 characters long",
format: function (action: string) {
return toPascalCase(action);
},
},
]);
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
- const collection_name: string = response.collection_name;
+ const collection_name: string = response.collection_name as string;
if (!collection_name) {
throw new Error("Empty collection name, please try again");
}
const file_path = target_locreq.resolve(
`src/back/collections/${toKebabCase(collection_name)}.ts`
);
if (existsSync(file_path)) {
- // eslint-disable-next-line no-console
console.error(`ERROR: File ${file_path} already exists.`);
return;
}
await fs.mkdir(resolve(file_path, "../"), { recursive: true });
await fs.writeFile(
file_path,
await formatWithPrettier(collectionTemplate(collection_name))
);
// eslint-disable-next-line no-console
console.log(`${file_path} created`);
await generateCollections();
}
diff --git a/src/add-crud.ts b/src/add-crud.ts
index 8b21310..788d8c2 100644
--- a/src/add-crud.ts
+++ b/src/add-crud.ts
@@ -1,137 +1,132 @@
import _locreq from "locreq";
import { escape_url_params } from "./utils/escape-url-params.js";
import prompts from "prompts";
import { toKebabCase, toPascalCase } from "js-convert-case";
import { listCollections } from "./utils/list-collections.js";
import { collectionListTemplate } from "./templates/shared/collection-list.js";
import { writeFile } from "./utils/write-file.js";
import { curryImportPath, importPath } from "./utils/import-path.js";
import { sharedCrudFormFields } from "./templates/shared/shared-crud-form-fields.js";
import { generateRoutes } from "./generate-routes.js";
import { createItemFormTemplate } from "./templates/shared/collection-create-form.js";
import { editItemFormTemplate } from "./templates/shared/collection-edit-form.js";
import { itemDeleteTemplate } from "./templates/shared/item-delete.js";
export async function addCRUD(
params: Partial<{ [key in "collection" | "url"]: string }>,
app_directory: string = process.cwd()
) {
const target_locreq = _locreq(app_directory);
prompts.override(params);
const response = await prompts([
{
type: "autocomplete",
name: "collection",
message:
"Which sealious collection do you like to add CRUD forms for?",
- choices: (
- await listCollections()
- ).map((collection) => ({
+ choices: (await listCollections()).map((collection) => ({
title: collection,
value: collection,
})),
},
{
type: "text",
name: "url",
message:
"Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
validate: (s: string) =>
s.trim()[0] == "/" ? true : "Should start with a '/'",
initial: function (_, { collection }: { collection: string }) {
return "/" + toKebabCase(collection);
},
},
]);
const collection_name = response.collection as string;
const url = response.url as string;
const list_action_name = toPascalCase(collection_name) + "CRUDList";
const create_action_name = toPascalCase(collection_name) + "CRUDCreate";
const edit_action_name = toPascalCase(collection_name) + "CRUDEdit";
const delete_action_name = toPascalCase(collection_name) + "CRUDDelete";
/* create the list endpoint */
const list_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/index.list.tsx`
);
const list_content = await collectionListTemplate(
collection_name,
list_action_name,
list_path,
{
post_import_js: `import { ${create_action_name}URL, ${edit_action_name}URL, ${delete_action_name}URL } from "${importPath(
list_path,
"src/back/routes/urls.ts"
)}";`,
post_header_html: `<a href={${create_action_name}URL}> Create </a>`,
render_item: (
collection_name: string
) => ` async renderItem(ctx: Context, item: CollectionItem<typeof ${toPascalCase(
collection_name
)}>) {
return <tr>
{displayFields.map(({ field, format }) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
const value = item.get(field as any);
return <td>{format ? format(value, item) : value}</td>;
})}
<td><div class="sealious-list__actions">
<a href={${edit_action_name}URL(item.id)}>Edit</a>
<a data-turbo-method="POST" data-turbo-confirm="Delete item?" href={${delete_action_name}URL(item.id)}>Delete</a>
</div>
</td>
</tr>;
}`,
}
);
await writeFile(list_path, list_content);
/* create the shared fields file */
const fields_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/shared.ts`
);
- const fields_content = await sharedCrudFormFields(
- collection_name,
- fields_path
- );
+ const fields_content = await sharedCrudFormFields(collection_name);
await writeFile(fields_path, fields_content);
/* create the create endpoint */
const create_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/create.form.ts`
);
const create_content = await createItemFormTemplate(
create_action_name,
create_path,
collection_name,
list_action_name
);
await writeFile(create_path, create_content);
/* create the edit endpoint */
const edit_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/[id]/edit.form.ts`
);
const edit_content = await editItemFormTemplate(
edit_action_name,
edit_path,
collection_name,
list_action_name
);
await writeFile(edit_path, edit_content);
/* create the actual delete endpoint */
const delete_path = target_locreq.resolve(
`src/back/routes/${escape_url_params(url)}/[id]/delete.page.tsx`
);
const base_import_path = curryImportPath(delete_path);
const delete_content = await itemDeleteTemplate(
delete_action_name,
collection_name,
list_action_name,
base_import_path
);
await writeFile(delete_path, delete_content);
await generateRoutes();
}
diff --git a/src/add-jdd-component.ts b/src/add-jdd-component.ts
index 624d3a6..bde3876 100644
--- a/src/add-jdd-component.ts
+++ b/src/add-jdd-component.ts
@@ -1,43 +1,42 @@
import { resolve } from "path";
import _locreq from "locreq";
import { promises as fs, existsSync } from "fs";
import { question } from "./utils/question.js";
const target_locreq = _locreq(process.cwd());
import { jddComponentTemplate } from "./templates/jdd-component.js";
import { generateComponents } from "./generate-components.js";
import { toKebabCase } from "js-convert-case";
export async function addJDDComponent(): Promise<void> {
const component_name = await question(
"What's the name of the component? > ",
(s: string) => s.length > 3
);
const file_path = target_locreq.resolve(
`src/back/jdd-components/${toKebabCase(component_name)}/${toKebabCase(
component_name
)}.jdd.tsx`
);
if (existsSync(file_path)) {
- // eslint-disable-next-line no-console
console.error(`ERROR: File ${file_path} already exists.`);
return;
}
await fs.mkdir(resolve(file_path, "../"), { recursive: true });
- await fs.writeFile(file_path, jddComponentTemplate(component_name));
+ await fs.writeFile(file_path, await jddComponentTemplate(component_name));
const css_file_path = target_locreq.resolve(
`src/back/jdd-components/${toKebabCase(component_name)}/${toKebabCase(
component_name
)}.css`
);
await fs.writeFile(
css_file_path,
`.${toKebabCase(component_name)} {
}`
);
- // eslint-disable-next-line no-console
- console.log(`Created ${file_path}`);
- console.log(`Created ${css_file_path}`);
+
+ console.info(`Created ${file_path}`);
+ console.info(`Created ${css_file_path}`);
await generateComponents();
}
diff --git a/src/add-route.ts b/src/add-route.ts
index c07db4e..2894fdc 100644
--- a/src/add-route.ts
+++ b/src/add-route.ts
@@ -1,88 +1,85 @@
import { existsSync, promises as fs } from "fs";
import _locreq from "locreq";
import { resolve } from "path";
import { generateRoutes } from "./generate-routes.js";
import { escape_url_params } from "./utils/escape-url-params.js";
import prompts from "prompts";
import { Templates } from "./templates/templates.js";
import { toKebabCase, toPascalCase } from "js-convert-case";
export async function addRoute(
params: Partial<{ [key in "action" | "url" | "mode"]: string }>,
app_directory: string = process.cwd()
): Promise<void> {
const target_locreq = _locreq(app_directory);
prompts.override(params);
const response = await prompts([
{
type: "text",
name: "action",
message: 'What\'s the name of the action (e.g. "AddUser"): ',
validate: (s: string) =>
s.length > 3 ? true : "Should be at least 3 characters long",
format: function (action: string) {
return toPascalCase(action);
},
},
{
type: "text",
name: "url",
message:
"Enter a full absolute path for the new route (for example: /admin/users/:id/edit): ",
validate: (s: string) =>
s.trim()[0] == "/" ? true : "Should start with a '/'",
initial: function (_, { action }: { action: string }) {
return "/" + toKebabCase(action);
},
},
{
type: "select",
name: "mode",
message: "What kind of route is it?",
choices: [
{ title: "page", value: "page" },
{ title: "stateful page", value: "sreact" },
{ title: "form", value: "form" },
{ title: "list", value: "list" },
{ title: "multiform", value: "multiform" },
{ title: "redirect", value: "redirect" },
{ title: "raw POST", value: "post" },
{ title: "Long Running Process status page", value: "lpr" },
{ title: "JDD content editor", value: "jdd-editor" },
],
},
]);
const { action, url, mode } = response as Record<string, string>;
const extension = ["list", "lpr", "page", "sreact", "jdd-editor"].includes(
mode
)
? "tsx"
: "ts";
const base_file_name = escape_url_params(url) || "index";
const file_path = target_locreq.resolve(
`src/back/routes/${base_file_name}.${mode}.${extension}`
);
const test_file_path = target_locreq.resolve(
`src/back/routes/${base_file_name}.test.ts`
);
- const template = Templates[mode as keyof typeof Templates];
+ const template = Templates[mode];
if (!template) {
throw new Error(`Could not get template ${mode}`);
}
if (existsSync(file_path)) {
- // eslint-disable-next-line no-console
console.error(`ERROR: File ${file_path} already exists.`);
return;
}
await fs.mkdir(resolve(file_path, "../"), { recursive: true });
await fs.writeFile(file_path, await template(action, file_path));
- // eslint-disable-next-line no-console
- console.log(`${file_path} created`);
- // eslint-disable-next-line no-console
- console.log(`${test_file_path} created`);
+ console.info(`${file_path} created`);
+ console.info(`${test_file_path} created`);
await generateRoutes();
}
diff --git a/src/build.ts b/src/build.ts
index 4831f52..fc20f11 100644
--- a/src/build.ts
+++ b/src/build.ts
@@ -1,135 +1,135 @@
import { promises as fs } from "fs";
import * as chokidar from "chokidar";
import { make_notifier } from "./notifier.js";
import getPort from "get-port";
import { resolve } from "node:path";
import _locreq from "locreq";
import { hasShape, predicates } from "@sealcode/ts-predicates";
import { FontsBuilder } from "./builders/fonts-builder.js";
import { BackendTSBuilder } from "./builders/backend-ts-builder.js";
import { FrontendTSBuilder } from "./builders/frontend-ts-builder.js";
import { CSSBuilder } from "./builders/css-builder.js";
import { ColorsBuilder } from "./builders/colors-builder.js";
const target_locreq = _locreq(process.cwd());
async function get_notifier_port() {
return getPort({ port: 4000 });
}
async function write_notifier_config(watch: boolean, port?: number) {
const config = { watch } as Record<string, boolean | number>;
if (port) {
config.port = port;
}
await fs.writeFile(
target_locreq.resolve("public/dist/notifier.json"),
JSON.stringify(config)
);
}
const package_json_shape = {
sealgen: predicates.maybe(
predicates.shape({
styleDirs: predicates.maybe(predicates.array(predicates.string)),
controllerDirs: predicates.maybe(
predicates.array(predicates.string)
),
copyToPublic: predicates.maybe(
predicates.array(
predicates.shape({
from: predicates.string,
to: predicates.string,
})
)
),
})
),
};
async function build(watch: boolean): Promise<void> {
const project_dir = target_locreq.resolve("");
const package_json = JSON.parse(
await fs.readFile(resolve(project_dir, "package.json"), "utf-8")
) as Record<string, unknown>;
if (!hasShape(package_json_shape, package_json)) {
throw new Error("Misshaped package.json props");
}
const style_dirs = package_json.sealgen?.styleDirs || [];
const controller_dirs = package_json.sealgen?.controllerDirs || [];
const copy_to_public = package_json.sealgen?.copyToPublic || [];
await Promise.all(
copy_to_public.map(async ({ from, to }) => {
try {
await fs.stat(resolve(project_dir, "public", to));
- } catch (e) {
+ } catch (_e) {
await fs.mkdir(resolve(project_dir, "public", to, "../"), {
recursive: true,
});
await fs.symlink(
resolve(project_dir, from),
resolve(project_dir, "public", to)
);
}
})
);
const fonts_builder = new FontsBuilder(project_dir, style_dirs);
const backend_ts_builder = new BackendTSBuilder(project_dir, style_dirs);
const frontend_ts_builder = new FrontendTSBuilder(
project_dir,
style_dirs,
controller_dirs
);
const css_builder = new CSSBuilder(project_dir, style_dirs);
const colors_builder = new ColorsBuilder(project_dir, style_dirs);
const builders = [
fonts_builder,
backend_ts_builder,
colors_builder,
css_builder,
frontend_ts_builder,
];
await Promise.all(builders.map((b) => b.build()));
if (watch) {
const watcher = chokidar.watch(["src", ...controller_dirs], {
ignoreInitial: true,
});
const port = await get_notifier_port();
const notifier = make_notifier(port, 8080); // TODO: parse the app config to get the actual port
await write_notifier_config(watch, port);
watcher.on("all", (_, file_path) => {
- console.log("Detected a change!", file_path);
+ console.info("Detected a change!", file_path);
builders.forEach((builder) => {
const owns_a_file = builder.ownsFile(file_path);
if (owns_a_file) {
void builder.build(notifier);
}
});
});
} else {
await write_notifier_config(watch);
builders.forEach((builder) => {
void builder.dispose();
});
}
}
export async function buildProject({
watch,
}: {
watch: boolean;
}): Promise<void> {
try {
await build(watch);
} catch (e) {
- console.log("CAUGHT!");
+ console.error("CAUGHT!");
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
console.error(e.message);
if (!watch) {
process.exit(1);
}
}
}
diff --git a/src/builders/backend-ts-builder.ts b/src/builders/backend-ts-builder.ts
index 09523be..e257eee 100644
--- a/src/builders/backend-ts-builder.ts
+++ b/src/builders/backend-ts-builder.ts
@@ -1,73 +1,72 @@
import glob from "tiny-glob";
import { build } from "esbuild";
import { promises as fs } from "fs";
import { relative } from "node:path";
import { embeddable_file_extensions } from "../embeddable-file-extensions.js";
import { generateCollections } from "../generate-collections.js";
import { generateComponents } from "../generate-components.js";
import { generateRoutes } from "../generate-routes.js";
import { Builder } from "./builder.js";
import { rewrite_asset_imports_plugin } from "../esbuild-plugins/rewrite-asset-imports.js";
import { load_assets_plugin } from "../esbuild-plugins/load-assets.js";
export class BackendTSBuilder extends Builder {
getName(): string {
return "backend-ts";
}
ownsFile(file_path: string) {
return (
(file_path.endsWith(".ts") || file_path.endsWith(".tsx")) &&
!file_path.endsWith("src/back/collections/collections.ts") &&
!file_path.endsWith("src/back/routes/routes.ts") &&
!file_path.endsWith("src/back/routes/urls.ts") &&
!file_path.endsWith("stimulus.ts") &&
!file_path.startsWith("src/front")
);
}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
async dispose(): Promise<void> {}
async _build(): Promise<void> {
await Promise.all([
generateCollections(),
generateRoutes(),
generateComponents(),
]);
const entryPoints = (
await glob(
`./src/back/**/*.{ts,tsx,${embeddable_file_extensions.join(
","
)}}`
)
).filter((path) => !path.includes(".#"));
const { metafile } = await build({
entryPoints,
sourcemap: true,
bundle: false,
jsxFactory: "TempstreamJSX.createElement",
jsxFragment: "TempstreamJSX.Fragment",
outdir: "./dist/back",
logLevel: "info",
platform: "node",
target: "es2022",
format: "esm",
loader: Object.fromEntries(
embeddable_file_extensions.map((ext) => ["." + ext, "js"])
),
plugins: [
rewrite_asset_imports_plugin(this.project_dir),
load_assets_plugin,
],
metafile: true,
});
await fs.writeFile(
relative(this.project_dir, "dist") + "/" + "back" + ".meta.json",
JSON.stringify(metafile)
);
}
}
diff --git a/src/builders/builder.ts b/src/builders/builder.ts
index 8028944..7e2538a 100644
--- a/src/builders/builder.ts
+++ b/src/builders/builder.ts
@@ -1,25 +1,28 @@
export abstract class Builder {
abstract ownsFile(file_path: string): boolean;
abstract getName(): string;
abstract _build(): Promise<void>;
abstract dispose(): Promise<void>;
- constructor(public project_dir: string, public style_dirs: string[]) {}
+ constructor(
+ public project_dir: string,
+ public style_dirs: string[]
+ ) {}
public ongoing_build: Promise<void> | null = null;
public build(notifier?: (message: string) => void) {
if (!this.ongoing_build) {
const build = this._build()
.catch((err) => {
console.error(err);
})
.then(() => {
notifier?.(this.getName());
this.ongoing_build = null;
});
this.ongoing_build = build;
}
return this.ongoing_build;
}
}
diff --git a/src/builders/colors-builder.ts b/src/builders/colors-builder.ts
index 51b907f..60dd349 100644
--- a/src/builders/colors-builder.ts
+++ b/src/builders/colors-builder.ts
@@ -1,490 +1,492 @@
-/* eslint-disable @typescript-eslint/no-non-null-assertion */
import { build } from "esbuild";
import tempfile from "tempfile";
import { promises as fs } from "fs";
import { resolve } from "path";
import { colord } from "colord";
import { hex } from "wcag-contrast";
import { formatWithPrettier } from "../utils/prettier.js";
import { Builder } from "./builder.js";
import { exec } from "../utils/exec.js";
import { APP_BACK_ALIVE_SIGNAL } from "../notifier.js";
export const COLORS_TS_PATH = "src/back/colors.ts"; // keeping it in src/back instead of just src to make typescript hints work there
export const COLORS_CSS_PATH = "src/colors.css";
export const COLORS_HTML_PATH = "public/dist/colors.html";
export class ColorsBuilder extends Builder {
getName(): string {
return "colors";
}
ownsFile(file_path: string) {
return file_path == COLORS_TS_PATH;
}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
async dispose(): Promise<void> {}
async _build() {
const outfile = tempfile({ extension: "mjs" });
await build({
entryPoints: [COLORS_TS_PATH],
bundle: true,
format: "esm",
outfile,
});
await fs.appendFile(
outfile,
/* HTML */ `<script>
console.log(
JSON.stringify(
Object.fromEntries(
Object.entries(colors).map(
([group_name, group]) => [
group_name,
Object.fromEntries(
Object.entries(group).map(
([color_name, color]) => {
const shades = [];
for (let i = 0; i <= 9; i++) {
shades.push(
shade(color, i)
);
}
return [
color_name,
{ color, shades },
];
}
)
),
]
)
)
)
);
</script>`.replaceAll(/<\/?script>/g, "") // <script> helps Prettier format this snippet
);
const output = await exec("node", [outfile]);
const color_groups = JSON.parse(output.stdout) as Record<
string,
Record<string, { color: string; shades: string[] }>
>;
let css_colors = "";
let html_colors = "";
function html_color_box({
color,
shade_no,
name,
group_name,
is_main = false,
}: {
color: string;
shade_no: string;
name: string;
group_name: string;
is_main?: boolean;
}) {
const c = colord(color);
return /* HTML */ `<div
class="color-box ${c.isDark() ? "is-dark" : ""} ${is_main
? "is-main"
: ""} ${c.toHsl().l > 90 ? "is-almost-white" : ""}"
style="background-color: ${color}; order: ${parseInt(shade_no)}"
data-color-name="${name}"
data-color-group-name="${group_name}"
data-color-shade-number="${shade_no}"
>
<span class="hex">${c.toHex()}</span>
</div>`;
}
for (const group_name of Object.keys(color_groups).sort((key) =>
key == "brand" ? -1 : 11
)) {
html_colors += `<h2>${group_name}</h2><div class="group">`;
const colors = color_groups[group_name];
for (const [color_name, color_info] of Object.entries(colors)) {
html_colors += `<h3>${color_name}</h3><div class="shades">`;
const main_color = color_info.color;
css_colors += `--color-${group_name}-${color_name}: ${main_color};`;
const main_l = colord(main_color).toHsl().l;
html_colors += html_color_box({
color: main_color,
name: color_name,
shade_no: Math.round((main_l - (main_l % 10)) / 10)
.toString()
.padStart(2, "0"),
is_main: true,
group_name,
});
color_info.shades.forEach((shaded_color, index) => {
const shade_no = index.toString().padStart(2, "0");
css_colors += `--color-${group_name}-${color_name}-${shade_no}: ${shaded_color};`;
if (
Math.abs(
colord(shaded_color).toHsl().l -
colord(main_color).toHsl().l
) < 10
) {
// this color is already in HTML as the main color, skipping adding it to html to avoid duplication
return;
}
html_colors += html_color_box({
color: shaded_color,
shade_no,
name: color_name,
group_name,
});
});
html_colors += `</div>`;
}
html_colors += "</div>";
}
const css = await formatWithPrettier(
`/* DO NOT EDIT! This file is automatically generated by sealgen */
:root {
${css_colors}
}`,
"css"
);
function colorCodeFind(color_varibale_name: string) {
const parts = color_varibale_name.split("-").slice(2);
const colorGroup = parts[1];
const colorName = parts.slice(2).join("-").replace(/\)$/, "");
const colorCode = color_groups[colorGroup]?.[colorName]?.color;
return colorCode;
}
function makeDemoPair(
fg: string,
bg: string,
text: string,
classname = ""
) {
let roundedContrast = "";
if (fg !== "") {
const fg_code = colorCodeFind(fg);
const bg_code = colorCodeFind(bg);
const contrast = hex(fg_code, bg_code);
roundedContrast = Math.round(contrast).toString();
}
return /* HTML */ ` <div
class="pair ${classname}"
data-fg="${fg}"
data-bg="${bg}"
style="background-color: ${bg}; color: ${fg}; display: flex; justify-content: space-between;"
>
<span>${text}</span>
<span>${roundedContrast}</span>
</div>`;
}
const html = await formatWithPrettier(
/* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Color palettes</title>
<style>
${css}
</style>
<style>
* {
font-family: sans-serif;
}
.shades {
display: flex;
}
.color-box {
width: 100px;
height: 100px;
transition: transform 50ms;
transition-timing-function: ease-in-out;
transform: scale(1);
cursor: pointer;
&:hover {
transform: scale(1.1);
z-index: 2;
.hex {
visibility: visible;
}
}
&.is-main {
height: 116px;
width: 116px;
margin-top: -8px;
box-shadow: 0px 0px 6px 2px white;
z-index: 1;
&:before {
font-weight: bold;
}
}
&.is-almost-white.is-main {
box-shadow: 0px 0px 6px 1px #00000078;
}
.hex {
padding: 8px;
- font-family: Menlo, Consolas, Monaco,
- Liberation Mono, Lucida Console,
+ font-family:
+ Menlo,
+ Consolas,
+ Monaco,
+ Liberation Mono,
+ Lucida Console,
monospace;
opacity: 0.5;
visibility: hidden;
}
&.is-dark .hex {
color: white;
}
}
.color-box:before {
content: attr(data-color-shade-number);
box-sizing: border-box;
display: block;
color: black;
font-size: 14px;
width: 100%;
padding: 10px;
opacity: 0.3;
}
.color-box.is-dark:before {
color: white;
}
@keyframes float-up {
from {
transform: translateY(0);
opacity: 1;
}
to {
transform: translateY(-20px);
opacity: 0;
}
}
.toast {
background-color: black;
position: absolute;
color: white;
border-radius: 8px;
padding: 8px;
animation: float-up 800ms;
animation-timing-function: ease-out;
z-index: 3;
}
.container {
width: 100vw;
display: flex;
flex-flow: row wrap;
gap: 16px;
@media (max-width: 1400px) {
.demo {
order: 1;
}
.pallete {
order: 2;
}
}
.canvas {
background-color: var(--color-brand-canvas);
display: flex;
flex-flow: column;
border: 1px dashed gray;
color: gray;
gap: 8px;
padding: 8px;
& > * {
padding: 8px;
color: black;
}
.pair.single span {
opacity: 0.5;
}
.pair.link span {
text-decoration: underline;
}
}
}
</style>
</head>
<body>
<div class="container">
<div class="pallete">${html_colors}</div>
<div class="demo">
<div class="canvas">
<span>canvas</span>
${makeDemoPair(
"var(--color-brand-text-fg)",
"var(--color-brand-canvas)",
"text-fg on canvas"
)}
${makeDemoPair(
"var(--color-brand-text-fg)",
"var(--color-brand-text-bg)",
"text-fg on text-bg"
)}
${makeDemoPair(
"var(--color-brand-text-accent)",
"var(--color-brand-text-bg)",
"text-accent on text-bg"
)}
${makeDemoPair(
"var(--color-brand-text-accent2)",
"var(--color-brand-text-bg)",
"text-accent2 on text-bg"
)}
${makeDemoPair(
"var(--color-brand-link-fg)",
"var(--color-brand-text-bg)",
"link-fg on text-bg",
"link"
)}
${makeDemoPair(
"",
"var(--color-brand-accent)",
"accent",
"single"
)}
${makeDemoPair(
"",
"var(--color-brand-accent2)",
"accent2",
"single"
)}
${makeDemoPair(
"var(--color-brand-text-on-accent)",
"var(--color-brand-accent)",
"text-on-accent on accent"
)}
${makeDemoPair(
"var(--color-brand-text-on-accent2)",
"var(--color-brand-accent2)",
"text-on-accent2 on accent2"
)}
${makeDemoPair(
"var(--color-brand-link-on-accent)",
"var(--color-brand-accent)",
"link-on-accent on accent",
"link"
)}
${makeDemoPair(
"var(--color-brand-link-on-accent2)",
"var(--color-brand-accent2)",
"link-on-accent2 on accent2",
"link"
)}
</div>
</div>
</div>
</body>
<script>
function pop_toast() {
const toast = document.createElement("div");
document.body.appendChild(toast);
toast.classList.add("toast");
toast.textContent = "Copied!";
toast.style.setProperty(
"top",
event.clientY +
document.scrollingElement.scrollTop -
40 +
"px"
);
toast.style.setProperty(
"left",
event.clientX + "px"
);
toast.addEventListener("animationend", () => {
toast.remove();
});
}
document.addEventListener("click", (event) => {
const box = event.target.closest(".color-box");
if (box) {
const css_var = box.classList.contains(
"is-main"
)
? \`var(--color-\${box.getAttribute(
"data-color-group-name"
- )}-\${box.getAttribute(
+ )}-\${box.getAttribute(
"data-color-name"
- )})\`
+ )})\`
: \`var(--color-\${box.getAttribute(
"data-color-group-name"
- )}-\${box.getAttribute(
+ )}-\${box.getAttribute(
"data-color-name"
- )}-\${box.getAttribute(
+ )}-\${box.getAttribute(
"data-color-shade-number"
- )})\`;
+ )})\`;
navigator.clipboard.writeText(css_var);
pop_toast();
}
const pair = event.target.closest(".pair");
if (pair) {
let to_copy = "";
if (pair.classList.contains("single")) {
to_copy = pair.getAttribute("data-bg");
} else {
to_copy = \`background-color: \${pair.getAttribute(
"data-bg"
)};\\ncolor: \${pair.getAttribute(
"data-fg"
)};\`;
}
navigator.clipboard.writeText(to_copy);
pop_toast();
}
});
</script>
<script>
(async function () {
const response = await (
await fetch("/dist/notifier.json")
).json();
const ws = new WebSocket(
\`http://localhost:\${response.port}\`
);
ws.addEventListener("message", (event) => {
console.log(event);
if (event.data == "${APP_BACK_ALIVE_SIGNAL}") {
document.location = document.location; // refresh
}
});
})();
</script>
</html>`,
"html"
);
await Promise.all([
fs.writeFile(resolve(this.project_dir, COLORS_CSS_PATH), css),
fs.writeFile(resolve(this.project_dir, COLORS_HTML_PATH), html),
]);
}
}
diff --git a/src/builders/css-builder.ts b/src/builders/css-builder.ts
index 2920670..87b78d2 100644
--- a/src/builders/css-builder.ts
+++ b/src/builders/css-builder.ts
@@ -1,157 +1,160 @@
import { build } from "esbuild";
import { resolve, relative, basename, dirname } from "node:path";
import glob from "tiny-glob";
import { promises as fs } from "fs";
import { walkDir } from "../utils/walk.js";
import { Builder } from "./builder.js";
export class CSSClump {
public files: string[] = [];
- constructor(public project_dir: string, public name: string) {}
+ constructor(
+ public project_dir: string,
+ public name: string
+ ) {}
addFile(full_path: string) {
this.files.push(full_path);
}
async build() {
await this.makeEntrypoint();
const loader = Object.fromEntries(
(<const>[
"png",
"svg",
"jpg",
"gif",
"jpeg",
"otf",
"ttf",
"woff",
"woff2",
]).map((ext) => <const>["." + ext, "file"])
);
const result = await build({
entryPoints: [relative(this.project_dir, this.getEntrypointPath())],
sourcemap: true,
bundle: true,
outdir: "./public/dist",
logLevel: "info",
loader,
minify: true,
target: ["safari16.5"], // to make css nesting work without manually adding `&`
metafile: true,
});
await fs.writeFile(
relative(this.project_dir, "public/dist") +
"/" +
this.name +
".meta.json",
JSON.stringify(result.metafile)
);
}
getEntrypointPath(): string {
return resolve(
this.project_dir,
`src/style-entrypoints/${this.name}.entrypoint.css`
);
}
async makeEntrypoint() {
const entrypoint_path = this.getEntrypointPath();
await fs.mkdir(dirname(entrypoint_path), { recursive: true });
await fs.writeFile(
entrypoint_path,
[
`/* DO NOT EDIT! Automatically generated by sealgen */`,
...this.files
.sort()
.map(
(fullpath) =>
`@import "${relative(
dirname(entrypoint_path),
fullpath
)}";`
),
].join("\n")
);
}
static assignFileToClumps(file_path: string): string[] {
const segments = basename(file_path).split(".");
segments.shift(); // filename
segments.pop(); // extension
if (!segments.length) {
if (file_path.includes("/jdd-components/")) {
const component_name = file_path.match(
/jdd-components\/([^/]+)\//
)?.[1];
if (!component_name) {
return [];
}
return ["jdd-components", "jdd-component__" + component_name];
} else {
// no segments, default clump
return ["default"];
}
}
if (segments.length == 1 && segments[0] == "entrypoint") {
return [];
}
return segments;
}
static async findCSSClumps(
project_dir: string,
style_dirs: string[]
): Promise<CSSClump[]> {
const clumps: Record<string, CSSClump> = {};
const dirs_to_scan = [resolve(project_dir, "src"), ...style_dirs];
const all_files = (await Promise.all(dirs_to_scan.map(walkDir))).flat();
for (const file of all_files) {
if (!file.endsWith(".css")) continue;
const clump_names = CSSClump.assignFileToClumps(file);
for (const clump_name of clump_names) {
if (!clump_name) continue;
if (!clumps[clump_name]) {
clumps[clump_name] = new CSSClump(project_dir, clump_name);
}
clumps[clump_name]?.addFile(file);
}
}
return Object.values(clumps);
}
}
export class CSSBuilder extends Builder {
getName(): string {
return "css";
}
ownsFile(file_path: string) {
return (
file_path.endsWith(".css") && !file_path.endsWith("/includes.css")
);
}
async dispose(): Promise<void> {
//noop
}
async _build() {
try {
const entrypoints = await glob(`./src/*.entrypoint.css`);
await Promise.allSettled(
entrypoints.map((rel_path) =>
fs.unlink(resolve(this.project_dir, rel_path))
)
);
const clumps = await CSSClump.findCSSClumps(
this.project_dir,
this.style_dirs
);
await Promise.all(clumps.map((clump) => clump.build()));
} catch (e) {
console.error(e);
}
}
}
diff --git a/src/builders/fonts-builder.ts b/src/builders/fonts-builder.ts
index 6e29ee0..ced8f1f 100644
--- a/src/builders/fonts-builder.ts
+++ b/src/builders/fonts-builder.ts
@@ -1,19 +1,18 @@
import { Builder } from "./builder.js";
import { FONTS_CONFIG_PATH, getFonts } from "../get-fonts.js";
export class FontsBuilder extends Builder {
getName(): string {
return "fonts";
}
ownsFile(file_path: string) {
return file_path == FONTS_CONFIG_PATH;
}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
async dispose(): Promise<void> {}
async _build() {
return getFonts();
}
}
diff --git a/src/builders/frontend-ts-builder.ts b/src/builders/frontend-ts-builder.ts
index 96645f1..6bfb866 100644
--- a/src/builders/frontend-ts-builder.ts
+++ b/src/builders/frontend-ts-builder.ts
@@ -1,47 +1,46 @@
import { generateStimulusControllers } from "../generate-stimulus.js";
import { promises as fs } from "fs";
import { build } from "esbuild";
import { Builder } from "./builder.js";
import { relative } from "node:path";
export class FrontendTSBuilder extends Builder {
constructor(
public project_dir: string,
public style_dirs: string[],
public controller_dirs: string[]
) {
super(project_dir, style_dirs);
}
getName(): string {
return "frontend-ts";
}
ownsFile(file_path: string) {
return (
file_path.startsWith("src/front") ||
file_path.endsWith(".stimulus.ts")
);
}
- // eslint-disable-next-line @typescript-eslint/no-empty-function
async dispose(): Promise<void> {}
async _build(): Promise<void> {
await generateStimulusControllers(this.controller_dirs);
const { metafile } = await build({
entryPoints: ["./src/front/index.ts"],
sourcemap: true,
outfile: "./public/dist/bundle.js",
logLevel: "info",
bundle: true,
minify: true,
metafile: true,
treeShaking: true,
});
await fs.writeFile(
relative(this.project_dir, "dist") + "/" + "front" + ".meta.json",
JSON.stringify(metafile)
);
}
}
diff --git a/src/cli.ts b/src/cli.ts
index 5e6c95c..5995d71 100644
--- a/src/cli.ts
+++ b/src/cli.ts
@@ -1,51 +1,51 @@
#!/usr/bin/env node
import yargs from "yargs/yargs";
import { addCollection } from "./add-collection.js";
import { addJDDComponent } from "./add-jdd-component.js";
import { addRoute } from "./add-route.js";
import { addCRUD } from "./add-crud.js";
import { buildProject } from "./build.js";
import { generateCollections } from "./generate-collections.js";
import { generateComponents } from "./generate-components.js";
import { generateRoutes } from "./generate-routes.js";
import { getFonts } from "./get-fonts.js";
import { makeEnv } from "./make-env.js";
import {
registerExternalControllers,
registerExternalStyles,
} from "./register-external.js";
const actions: Record<
string,
(args: Record<string, string | boolean>) => Promise<void> | undefined
> = {
"add-collection": addCollection,
"add-route": addRoute,
"add-crud": addCRUD,
"generate-collections": generateCollections,
"generate-components": generateComponents,
"generate-routes": generateRoutes,
build: buildProject,
default: async function () {
- console.log("Usage: `npx sealgen <action>`");
- console.log(
+ console.info("Usage: `npx sealgen <action>`");
+ console.info(
`Available actions: ${Object.keys(actions)
.filter((e) => e != "default")
.join(", ")}`
);
},
"make-env": makeEnv,
"add-component": addJDDComponent,
"get-fonts": getFonts,
// "crud-field-snippets": crudFieldSnippets,
"register-external-controllers": registerExternalControllers,
"register-external-styles": registerExternalStyles,
};
void (async function () {
const action = process.argv.at(2);
const fn = actions[action || "default"] || actions.default;
const args = yargs(process.argv).argv as Record<string, string | boolean>;
await fn(args);
})();
diff --git a/src/components/tabs.ts b/src/components/tabs.ts
index 3c4e90b..8f07900 100644
--- a/src/components/tabs.ts
+++ b/src/components/tabs.ts
@@ -1,95 +1,96 @@
import { FlatTemplatable, tempstream } from "tempstream";
function name_to_id(str: string) {
return str.replace(/\W/g, "-");
}
-const style = (hide_tabs_width: number) => /* HTML */ `<style>
- .tab-label {
- height: 45px;
- line-height: 45px;
- padding: 0 45px;
- display: block;
- float: left;
- box-sizing: border-box;
- border-bottom: 3px solid transparent;
- cursor: pointer;
- font-size: 18px;
- -webkit-user-select: none;
- user-select: none;
- }
-
- @media screen and (max-width: ${hide_tabs_width}px) {
+const style = (hide_tabs_width: number) =>
+ /* HTML */ `<style>
.tab-label {
- display: none;
+ height: 45px;
+ line-height: 45px;
+ padding: 0 45px;
+ display: block;
+ float: left;
+ box-sizing: border-box;
+ border-bottom: 3px solid transparent;
+ cursor: pointer;
+ font-size: 18px;
+ -webkit-user-select: none;
+ user-select: none;
}
- }
- .tab-label--mobile {
- line-height: unset;
- padding-top: 30px;
- padding-left: 0;
- pointer-events: none;
- padding-bottom: 30px;
- color: $font-graphite;
- border-bottom: 2px solid $font-primary;
- display: none;
@media screen and (max-width: ${hide_tabs_width}px) {
- display: block;
+ .tab-label {
+ display: none;
+ }
}
- }
- .tab-content {
- padding-top: 30px;
- clear: both;
- }
+ .tab-label--mobile {
+ line-height: unset;
+ padding-top: 30px;
+ padding-left: 0;
+ pointer-events: none;
+ padding-bottom: 30px;
+ color: $font-graphite;
+ border-bottom: 2px solid $font-primary;
+ display: none;
+ @media screen and (max-width: ${hide_tabs_width}px) {
+ display: block;
+ }
+ }
- @media screen and (max-width: ${hide_tabs_width}px) {
.tab-content {
- display: block !important;
+ padding-top: 30px;
+ clear: both;
+ }
+
+ @media screen and (max-width: ${hide_tabs_width}px) {
+ .tab-content {
+ display: block !important;
+ }
}
- }
-</style>`;
+ </style>`;
export function tabs(
tabs: Record<string, FlatTemplatable>,
selected_tab_style = "font-weight: bold;",
selected_index = 0,
hide_tabs_width = 0
): FlatTemplatable {
return /* HTML */ tempstream`${style(hide_tabs_width)}
${Object.keys(tabs)
.map((tab_title, index) => {
const id = name_to_id(tab_title);
return /* HTML */ `<input
type="radio"
name="tabs"
id="${id}"
class="tab-radio--${id}"
style="display: none"
${selected_index == index ? "checked" : ""}
/>
<label class="tab-label tab-label--${id}" for="${id}">
${tab_title}
</label>`;
})
.join("\n")}
${Object.entries(tabs).map(([title, content]) => {
const id = name_to_id(title);
return /* HTML */ tempstream`<div class="tab-label tab-label--mobile">
${title}
</div>
<div class="tab-content tab-content--${id}">${content}</div>
<style>
.tab-radio--${id} ~ .tab-content--${id} {
display:none;
}
.tab-radio--${id}:checked ~ .tab-content--${id} {
display:block;
}
.tab-radio--${id}:checked ~ label.tab-label--${id} {
${selected_tab_style}
}
</style>`;
})}`;
}
diff --git a/src/components/toggle-modal.ts b/src/components/toggle-modal.ts
index ba8ea30..d9b468f 100644
--- a/src/components/toggle-modal.ts
+++ b/src/components/toggle-modal.ts
@@ -1,52 +1,52 @@
import { FlatTemplatable, tempstream } from "tempstream";
import { makeSlug } from "../utils/utils.js";
export function toggleModal(options: {
name: string;
contentWrapped: (id: string) => FlatTemplatable | Promise<FlatTemplatable>;
contentUnwrapped: (
id: string
) => FlatTemplatable | Promise<FlatTemplatable>;
}) {
const { contentWrapped, contentUnwrapped, name } = options;
const id = makeSlug(name);
- return tempstream/* HTML */ `<style>
+ return tempstream /* HTML */ `<style>
.toggle-modal__wrapped {
display: none;
}
@media (max-width: 960px) {
.toggle-modal__wrapped {
display: block;
}
.toggle-modal__unwrapped {
display: none;
}
#${id} {
display: none;
}
#${id}:checked ~ .toggle-modal__wrapped {
display: none;
}
#${id}:checked ~ .toggle-modal__unwrapped {
display: block;
position: fixed;
height: 100vh;
width: 100vw;
top: 0;
left: 0;
background-color: white;
z-index: 99;
overflow-y: scroll;
}
}
</style>
<div class="toggle-modal toggle-modal--${id}">
<input id="${id}" name="${id}" type="checkbox" autocomplete="off" />
<div class="toggle-modal__wrapped">${contentWrapped(id)}</div>
<div class="toggle-modal__unwrapped">${contentUnwrapped(id)}</div>
</div>`;
}
diff --git a/src/controllers/table-add-button.stimulus.ts b/src/controllers/table-add-button.stimulus.ts
index b084cf3..5c7ff78 100644
--- a/src/controllers/table-add-button.stimulus.ts
+++ b/src/controllers/table-add-button.stimulus.ts
@@ -1,35 +1,35 @@
/// <reference lib="dom" />
import { Controller } from "stimulus";
export default class extends Controller {
static targets = ["textarea"];
defaultRowsNumber = 20;
addRow() {
const template = this.element
.closest("turbo-frame")
?.querySelector("template");
if (!template) {
throw new Error("Couldn't find template");
}
const tbody = this.element
.closest("turbo-frame")
?.querySelector("tbody");
if (!tbody) {
throw new Error("tbody not found");
}
const orig_template = template.innerHTML;
const placeholder = this.element.getAttribute("data-table-placeholder");
if (!placeholder) {
throw new Error("Could find placeholder attribute");
}
template.innerHTML = orig_template.replaceAll(
placeholder,
String(tbody.querySelectorAll("tr").length)
);
- // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
+ // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-explicit-any
tbody.appendChild((template.cloneNode(true) as any).content);
template.innerHTML = orig_template;
}
}
diff --git a/src/esbuild-plugins/rewrite-asset-imports.ts b/src/esbuild-plugins/rewrite-asset-imports.ts
index c96eb9e..c4ae1d3 100644
--- a/src/esbuild-plugins/rewrite-asset-imports.ts
+++ b/src/esbuild-plugins/rewrite-asset-imports.ts
@@ -1,42 +1,39 @@
import { promises as fs } from "fs";
import { extname, resolve } from "node:path";
import { embeddable_file_extensions } from "../embeddable-file-extensions.js";
import { PluginBuild } from "esbuild";
export const rewrite_asset_imports_plugin = (project_dir: string) => ({
name: "sealgen-rewrite-asset-imports",
setup(build: PluginBuild) {
build.onLoad({ filter: /\.tsx?$/ }, async (args) => {
let contents = await fs.readFile(args.path, "utf8");
for (const ext of embeddable_file_extensions) {
const regex_assets = new RegExp(
`^import (\\w+|{[^}]+}) from "([^"]+.${ext})";`,
"gm"
);
contents = contents.replaceAll(regex_assets, (line) => {
line = line.replace(`.${ext}"`, '.js"');
return line;
});
}
const regex_import = new RegExp(
`^import ([^ ]+, )?(\\w+|{[^}]+}) from "([^"]+)";`,
"gm"
);
- contents = contents.replaceAll(
- regex_import,
- (line, _: string, original_path: string) => {
- const replaced = line.replace(
- `"src/`,
- `"` + resolve(project_dir, "./dist") + "/"
- );
- return replaced;
- }
- );
+ contents = contents.replaceAll(regex_import, (line) => {
+ const replaced = line.replace(
+ `"src/`,
+ `"` + resolve(project_dir, "./dist") + "/"
+ );
+ return replaced;
+ });
return {
contents,
loader: extname(args.path) === ".tsx" ? "tsx" : "ts",
};
});
},
});
diff --git a/src/forms/controls/array.ts b/src/forms/controls/array.ts
index 5ff7437..9a78c9a 100644
--- a/src/forms/controls/array.ts
+++ b/src/forms/controls/array.ts
@@ -1,237 +1,233 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Router from "@koa/router";
import { hasShape, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import qs from "qs";
import { Field, FieldsetOutput } from "sealious";
import { tempstream } from "tempstream";
import { FormField } from "../fields/field.js";
import { TextBasedSimpleField } from "../fields/simple-form-field.js";
import { StructuredArray as StructuredArrayField } from "../fields/structured-array.js";
import { FormDataValue } from "../form-types.js";
import { Derived } from "./derived.js";
import { FormControl, FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export type UnboundControlStorage<
F extends { new (...args: any): FormFieldControl } = {
new (...args: any): FormFieldControl;
- }
+ },
> = [F, string, ConstructorParameters<F>];
export function UnboundControl<
- F extends { new (...args: any): FormFieldControl }
+ F extends { new (...args: any): FormFieldControl },
>(
controlClass: F,
arbitrary_field_name: string,
params: ConstructorParameters<F>["1"]
): UnboundControlStorage {
return [controlClass, arbitrary_field_name, params];
}
export class StructuredArray<
- Subfields extends Record<string, Field<any>>
+ Subfields extends Record<string, Field<any>>,
> extends FormFieldControl {
constructor(
public field: StructuredArrayField<Subfields>,
public item_controls: Array<FormControl | UnboundControlStorage>
) {
super([field]);
}
getFrameID() {
return `array-frame-${this.field.name}`;
}
getInnerFormID() {
return this.getFrameID() + "-form";
}
getActionURL(form_id?: string, action?: Record<string, unknown>) {
return `${this.getFrameID()}${
form_id || action ? "?" : ""
}${qs.stringify({ form_id, action })}`;
}
async getDefaultItemBody() {
return {};
}
makeSubfield(_field_name: string): FormField {
return new TextBasedSimpleField(false);
}
async renderItemControl(
ctx: Context,
form_id: string,
control: FormControl | UnboundControlStorage,
item: FieldsetOutput<Subfields>,
index: number
) {
const fctx = {
ctx,
data: { raw_values: {}, messages: [], field_messages: {} },
messages: [],
field_name_prefix: "",
form_id,
validate: false,
} as FormControlContext;
if (Array.isArray(control)) {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const [constructor, field_name, params] = control;
const field = this.makeSubfield(field_name);
if (!field) {
console.warn(
`makeSubfield returned null for field ${field_name}`
);
return "";
}
field.setName(`${this.field.name}[data][${index}][${field_name}]`);
const hidden_shadow = new Derived(
[field],
- async (
- values,
- { inner_form_id, field_name }
- ) => /* HTML */ `<input
- name="${field_name}"
- type="hidden"
- value="${values[field_name] || ""}"
- form="${inner_form_id}"
- />`,
+ async (values, { inner_form_id, field_name }) =>
+ /* HTML */ `<input
+ name="${field_name}"
+ type="hidden"
+ value="${values[field_name] || ""}"
+ form="${inner_form_id}"
+ />`,
async () => ({
inner_form_id: this.getInnerFormID(),
field_name: field.name,
})
);
return tempstream`${new constructor(field, params).render({
...fctx,
data: {
raw_values: {
[field.name]: item[field_name] as FormDataValue,
},
messages: [],
field_messages: {},
},
})}${hidden_shadow.render({
...fctx,
data: {
raw_values: {
[field.name]: item[field_name] as FormDataValue,
},
messages: [],
field_messages: {},
},
form_id: this.getInnerFormID(),
})}`;
} else {
return control.render(fctx);
}
}
async renderItem(
ctx: Context,
form_id: string,
item: FieldsetOutput<Subfields>,
index: number
) {
- return tempstream/* HTML */ `<div>
+ return tempstream /* HTML */ `<div>
${this.item_controls.map((control) =>
this.renderItemControl(ctx, form_id, control, item, index)
)}
<input
type="submit"
value="remove"
form="${this.getInnerFormID()}"
formaction="${this.getActionURL(form_id, {
remove: index,
})}"
/>
</div>`;
}
async getItems(ctx: Context, raw_values: Record<string, FormDataValue>) {
return (await this.field.getParsedValue(ctx, raw_values))
.parsed as FieldsetOutput<Subfields>[];
}
async _render(
ctx: Context,
form_id: string,
raw_values: Record<string, FormDataValue>
) {
const items = await this.getItems(ctx, raw_values);
- return tempstream/* HTML */ `<turbo-frame id="${this.getFrameID()}">
+ return tempstream /* HTML */ `<turbo-frame id="${this.getFrameID()}">
Reverse Single Reference
${items.map((item, index) =>
this.renderItem(ctx, form_id, item, index)
)}
<form id="${this.getInnerFormID()}" method="POST"></form>
<input
type="submit"
value="add"
form="${this.getInnerFormID()}"
formaction="${this.getActionURL(form_id, {
insert: { index: items.length, value: {} },
})}"
/>
</turbo-frame>`;
}
render(fctx: FormControlContext) {
return this._render(fctx.ctx, fctx.form_id, fctx.data.raw_values);
}
async getTargetItemID(ctx: Context): Promise<string> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
return ctx.params.id as string;
}
mount(router: Router) {
router.post(this.getActionURL(), async (ctx) => {
const form_id = ctx.query.form_id;
if (typeof form_id != "string") {
throw new Error("Missing form_id query param");
}
const item = await this.field.sealious_field.collection.getByID(
ctx.$context,
await this.getTargetItemID(ctx)
);
if (!hasShape({ action: predicates.object }, ctx.$body)) {
throw new Error("Missing action param");
}
const field_data = (ctx.$body as Record<string, unknown>)[
this.field.name
] || { data: [] };
if (
!hasShape(
{
data: predicates.array(
this.field.sealious_field.value_predicate
),
},
field_data
)
) {
throw new Error("missing data atribute in action description");
}
item.set(this.field.name, {
...ctx.$body.action,
data: field_data.data || [],
});
await item.save(ctx.$context);
- console.log(await item.getDecodedBody(ctx.$context, {}));
ctx.body = this._render(
ctx,
form_id,
(await item.getDecodedBody(
ctx.$context,
{}
)) as unknown as Record<string, FormDataValue>
);
});
}
}
diff --git a/src/forms/controls/autocomplete.ts b/src/forms/controls/autocomplete.ts
index 2eb114d..d69c5bc 100644
--- a/src/forms/controls/autocomplete.ts
+++ b/src/forms/controls/autocomplete.ts
@@ -1,33 +1,33 @@
import { Context } from "koa";
import { tempstream } from "tempstream";
import { PickFromListField } from "../fields/pick-from-list.js";
import { FormControlContext } from "./form-control.js";
import { SimpleInput } from "./simple-input.js";
export class Autocomplete extends SimpleInput {
constructor(
public field: PickFromListField<boolean>,
public options: { id?: string; label?: string; placeholder?: string }
) {
super(field);
}
getListID(): string {
return this.getID() + "_list";
}
async getInputAttributes(fctx: FormControlContext) {
return {
...(await super.getInputAttributes(fctx)),
list: this.getListID(),
};
}
async postInput(ctx: Context) {
- return tempstream/* HTML */ `<datalist id="${this.getListID()}">
+ return tempstream /* HTML */ `<datalist id="${this.getListID()}">
${(await this.field.generateOptions(ctx)).map(
({ value }) => /* HTML */ `<option>${value}</option>`
)}
</datalist>`;
}
}
diff --git a/src/forms/controls/big-radio-group.ts b/src/forms/controls/big-radio-group.ts
index ba9c74e..957351e 100644
--- a/src/forms/controls/big-radio-group.ts
+++ b/src/forms/controls/big-radio-group.ts
@@ -1,48 +1,48 @@
import { FlatTemplatable, tempstream } from "tempstream";
import { FormField } from "../fields/field.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export class BigRadioGroup extends FormFieldControl {
constructor(
public field: FormField,
public options: Record<
string,
{
description:
| FlatTemplatable
| ((fctx: FormControlContext) => FlatTemplatable);
}
>
) {
super([field]);
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const { raw: current_value } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
- return tempstream/* HTML */ `<div class="bigradios">
+ return tempstream /* HTML */ `<div class="bigradios">
${Object.entries(this.options).map(([key, { description }]) => {
const id = `${this.field.name}-radio-${key}`;
- return tempstream/* HTML */ `<input
+ return tempstream /* HTML */ `<input
type="radio"
name="${this.field.name}"
value="${key}"
id="${id}"
style="display: none"
${fctx.form_id ? `form=${fctx.form_id}` : ""}
${this.field.required ? "required" : ""}
${key == current_value ? "checked" : ""}
/>
<div class="bigradio">
${typeof description == "function"
? description(fctx)
: description}
<label class="bigradio__cta" for="${id}">Wybierz</label>
</div>`;
})}
</div>`;
}
}
diff --git a/src/forms/controls/checkbox-group.ts b/src/forms/controls/checkbox-group.ts
index b4dfbf6..04fd2d6 100644
--- a/src/forms/controls/checkbox-group.ts
+++ b/src/forms/controls/checkbox-group.ts
@@ -1,69 +1,69 @@
import { FlatTemplatable } from "tempstream";
import { ProxyFormField } from "../fields/proxy-field.js";
import { CheckboxWithValue } from "./checkbox.js";
import { FieldGroup } from "./field-group.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
import { CheckboxedListField } from "../fields/checkboxed-list.js";
export type DefaultCheckboxOptions = {
id?: string;
label?: string;
hide_errors?: boolean;
readonly?: boolean;
name?: string;
checkboxNameToLabel?: (name: string) => string;
classes?: string[];
};
export class CheckboxGroup<
- Options extends DefaultCheckboxOptions = DefaultCheckboxOptions
+ Options extends DefaultCheckboxOptions = DefaultCheckboxOptions,
> extends FormFieldControl {
constructor(
public field: CheckboxedListField<boolean, string>,
public options: Options = {} as Options
) {
super([field]);
}
wrapGroup(
fctx: FormControlContext,
checkboxes: CheckboxWithValue[]
): Promise<FlatTemplatable> {
return new FieldGroup(checkboxes, {
label: this.options.label,
classes: [
...(this.options.classes || []),
"field-group--checkboxes",
],
}).render(fctx);
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const { parsed: values } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
const checkboxes = (await this.field.generateOptions(fctx.ctx)).map(
(option) =>
new CheckboxWithValue(
new ProxyFormField(
false,
this.field.name,
false,
Object.keys(values || {}).includes(option.value)
),
{
id: this.field.name + "__" + option.value,
label: (
this.options.checkboxNameToLabel ||
((s: string) => s)
)(option.value),
default_value: false,
},
option.value
)
);
return this.wrapGroup(fctx, checkboxes);
}
}
diff --git a/src/forms/controls/checkboxed-list-input.test.ts b/src/forms/controls/checkboxed-list-input.test.ts
index 7e75d1e..765c239 100644
--- a/src/forms/controls/checkboxed-list-input.test.ts
+++ b/src/forms/controls/checkboxed-list-input.test.ts
@@ -1,312 +1,312 @@
import Router from "@koa/router";
import getPort from "get-port";
import { Browser, Page } from "playwright";
import type { Context } from "koa";
import Koa from "koa";
import { mount } from "../../mount.js";
import { CheckboxedListField } from "../fields/checkboxed-list.js";
import { Form } from "../form.js";
import { CheckboxedListInput } from "./checkboxed-list-input.js";
import { getBrowser } from "../../utils/browser-creator.js";
import assert from "assert";
import { sleep } from "../../utils/sleep.js";
describe("checkboxed-list", () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
let browser: Browser;
let page: Page;
afterEach(() => {
server.close();
});
it("sends the values", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(true, async () => {
return ["sa", "mple", "co", "de"].map((s) => ({
value: s,
label: s.toLocaleUpperCase(),
}));
}),
};
let received_values: unknown;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables)];
async onSubmit(ctx: Context) {
received_values = await this.getParsedValues(ctx);
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByLabel("CO").check();
await page.getByLabel("DE").check();
await page.getByRole("button", { name: "Wyślij" }).click();
assert.deepStrictEqual(received_values, { syllables: { co: "on", de: "on" } });
});
describe("behavior with (non)required", () => {
it("allows to send a form when no value is selected and fiels is not required", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(false, async () => {
await sleep(10);
return ["sa", "mple", "co", "de"].map((s) => ({
value: s,
label: s.toLocaleUpperCase(),
}));
}),
};
let submit_called = false;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables)];
async onSubmit(ctx: Context) {
submit_called = true;
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
await sleep(100);
assert(submit_called);
});
it("does not allow to send a form when no value is selected and field IS required", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(true, async () => {
await sleep(10);
return ["sa", "mple", "co", "de"].map((s) => ({
value: s,
label: s.toLocaleUpperCase(),
}));
}),
};
let submit_called = false;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables)];
async onSubmit(ctx: Context) {
submit_called = true;
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
await sleep(100);
assert(submit_called == false);
await page.getByText(/empty value/).click({ timeout: 500 }); // should display an error message for that field
});
it("allows to send a form when no value is selected and field IS required", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(true, async () => {
await sleep(10);
return ["sa", "mple", "co", "de"].map((s) => ({
value: s,
label: s.toLocaleUpperCase(),
}));
}),
};
let submit_called = false;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables)];
async onSubmit(ctx: Context) {
submit_called = true;
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByLabel("DE").check();
await page.getByRole("button", { name: "Wyślij" }).click();
await sleep(100);
assert(submit_called);
});
});
it("renders the label", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(true, async () => {
return ["sa", "mple", "co", "de"].map((s) => ({
value: s,
label: s.toLocaleUpperCase(),
}));
}),
};
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables, { label: "ABC" })];
async onSubmit(ctx: Context) {
// noop
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
await page.getByText(/ABC/).click({ timeout: 500 }); // should display an error message for that field
});
it("groups checkboxes based on the value of the 'group' attribute", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
syllables: new CheckboxedListField(true, async () => {
return [
...["e", "y", "u", "i", "o", "a"].map((s, index) => ({
value: "vowel" + index,
label: s,
group: "vowels",
})),
...["q", "w", "r", "t", "p", "s", "test_label"].map((s, index) => ({
value: "consonant" + index,
label: s,
group: "consonants",
})),
];
}),
};
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new CheckboxedListInput(fields.syllables, { label: "Letters" })];
async onSubmit(ctx: Context) {
// noop
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
await page.getByText(/vowels/).click({ timeout: 500 }); // should display an error message for that field
await page.getByText(/consonants/).click({ timeout: 500 }); // should display an error message for that field
await page.getByText("test_label").click({ timeout: 500 });
});
});
});
diff --git a/src/forms/controls/checkboxed-list-input.ts b/src/forms/controls/checkboxed-list-input.ts
index 8b14603..dd165b0 100644
--- a/src/forms/controls/checkboxed-list-input.ts
+++ b/src/forms/controls/checkboxed-list-input.ts
@@ -1,147 +1,143 @@
import { tempstream } from "tempstream";
import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
import {
CheckboxedListField,
CheckboxedListItem,
} from "../fields/checkboxed-list.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export class CheckboxedListInput<
- Values extends string
+ Values extends string,
> extends FormFieldControl {
constructor(
public field: CheckboxedListField<boolean, Values>,
public options: { label: string } = { label: field.name }
) {
super([field]);
}
generateCountBasedClasses(n: number) {
return [
"options-count--" + n.toString(),
...(n >= 5 ? ["options-count--5-or-more"] : []),
...(n >= 10 ? ["options-count--10-or-more"] : []),
...(n >= 15 ? ["options-count--15-or-more"] : []),
...(n >= 20 ? ["options-count--20-or-more"] : []),
];
}
async render(fctx: FormControlContext) {
const {
valid,
message,
parsed: currentValue,
} = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values,
true
);
const pickedValues = Object.entries(currentValue || {})
.filter(([, is_on]) => is_on)
.map(([key]) => key);
const [options, isVisible] = await Promise.all([
this.field.generateOptions(fctx.ctx),
this.field.isVisible(fctx.ctx),
]);
const ungroupped = [];
const groups: Record<string, CheckboxedListItem[] | undefined> = {};
for (const option of options) {
if (!option.group) {
ungroupped.push(option);
} else {
if (!groups[option.group]) {
groups[option.group] = [];
}
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
groups[option.group]!.push(option);
}
}
const { name, required } = this.field;
return inputWrapper(
"checkboxed-list",
[
name,
getRequiredClass(required),
...this.generateCountBasedClasses(options.length),
],
- tempstream/* HTML */ `<label
+ tempstream /* HTML */ `<label
>${this.options.label || this.field.name}</label
>
${~valid && fctx.validate
? `<div class="input__error">${message}</div>`
: ""}
<ul>
${isVisible
? Object.entries(groups).map(
([group_label, options]) =>
- tempstream/* HTML */ ` <h3>
+ tempstream /* HTML */ ` <h3>
${group_label}
</h3>
- ${
- // eslint-disable-next-line @typescript-eslint/no-non-null-assertion
- options!.map(({ value, label }) =>
- this.renderOption({
- name,
- value,
- label,
- form_id: fctx.form_id,
- checked:
- pickedValues.includes(
- value
- ),
- })
- )
- }`
- )
+ ${options!.map(({ value, label }) =>
+ this.renderOption({
+ name,
+ value,
+ label,
+ form_id: fctx.form_id,
+ checked:
+ pickedValues.includes(
+ value
+ ),
+ })
+ )}`
+ )
: ""}
${isVisible
? ungroupped.map(({ value, label }) =>
this.renderOption({
name,
value,
label,
form_id: fctx.form_id,
checked: pickedValues.includes(value),
})
- )
+ )
: ""}
</ul>`
);
}
renderOption({
name,
value,
form_id,
label,
checked,
}: {
name: string;
form_id: string;
value: string;
label?: string;
checked: boolean;
}) {
- return tempstream/* HTML */ `<li>
+ return tempstream /* HTML */ `<li>
${inputWrapper(
"checkbox",
[name],
/* HTML */ `
<input
type="checkbox"
id="${name}.${value}"
name="${name}.${value}"
${checked ? "checked" : ""}
form=${form_id}
autocomplete="off"
/>
<label for="${name}.${value}">${label || value}</label>
`
)}
</li>`;
}
}
diff --git a/src/forms/controls/derived-frame.ts b/src/forms/controls/derived-frame.ts
index cbc96f4..48e8876 100644
--- a/src/forms/controls/derived-frame.ts
+++ b/src/forms/controls/derived-frame.ts
@@ -1,95 +1,96 @@
import Router from "@koa/router";
import { hasShape, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { ParsedUrlQuery } from "querystring";
import { FlatTemplatable, tempstream } from "tempstream";
import { makeSlug } from "../../utils/make-slug.js";
import { FormField } from "../fields/field.js";
import { Derived } from "./derived.js";
import { FormControlContext } from "./form-control.js";
export class DerivedFrame extends Derived<{
frame_id: string;
form_id: string;
field_name_prefix: string;
}> {
constructor(
public frame_name: string,
fields: FormField[],
public generateFrameContent: (
ctx: FormControlContext,
args: ParsedUrlQuery
) => Promise<FlatTemplatable>,
// "a" is to make it a valid DOM id
public frame_id = "a" + makeSlug(frame_name)
) {
super(
fields,
- async (values, consts) => /* HTML */ `<turbo-frame
- id="${consts.frame_id}"
- src="./${consts.frame_id}?${Object.entries({
- ...consts,
- ...(values || {}),
- })
- .map(([key, value]) => `${key}=${value}`)
- .join("&")}"
- ></turbo-frame>`,
+ async (values, consts) =>
+ /* HTML */ `<turbo-frame
+ id="${consts.frame_id}"
+ src="./${consts.frame_id}?${Object.entries({
+ ...consts,
+ ...(values || {}),
+ })
+ .map(([key, value]) => `${key}=${value}`)
+ .join("&")}"
+ ></turbo-frame>`,
async (fctx) => ({
form_id: fctx.form_id,
field_name_prefix: fctx.field_name_prefix,
frame_id,
validate: fctx.validate,
})
);
}
renderBackendResponseFrame(_ctx: Context, content: FlatTemplatable) {
- return tempstream/* HTML */ `<turbo-frame
+ return tempstream /* HTML */ `<turbo-frame
id="${this.frame_id}"
target="_top"
>
${content || ""}
</turbo-frame>`;
}
mount(router: Router) {
router.get(this.frame_id, async (ctx) => {
const query = ctx.query;
if (
!hasShape(
{
field_name_prefix: predicates.string,
form_id: predicates.string,
validate: predicates.string,
},
query
)
) {
ctx.body = this.renderBackendResponseFrame(
ctx,
"Missing query params"
);
return;
}
ctx.body = this.renderBackendResponseFrame(
ctx,
await this.generateFrameContent(
new FormControlContext(
ctx,
{
messages: [],
field_messages: {},
raw_values: ctx.query,
},
[],
query.field_name_prefix,
query.form_id,
query.validate === "true" ? true : false
),
ctx.query
)
);
});
return;
}
}
diff --git a/src/forms/controls/derived.ts b/src/forms/controls/derived.ts
index 7f5c968..79701bd 100644
--- a/src/forms/controls/derived.ts
+++ b/src/forms/controls/derived.ts
@@ -1,108 +1,109 @@
+/* eslint @typescript-eslint/no-redundant-type-constituents: off */
import { randomUUID } from "crypto";
import { FlatTemplatable, tempstream } from "tempstream";
import { FormField } from "../fields/field.js";
import { FormDataValue } from "../form-types.js";
import { FormControl, FormControlContext } from "./form-control.js";
export class Derived<
- Consts extends Record<string, unknown | undefined>
+ Consts extends Record<string, unknown | undefined>,
> extends FormControl {
role = <const>"decoration";
constructor(
public fields: FormField[],
public _render: (
values: Record<string, string>,
consts: Consts
) => Promise<FlatTemplatable>,
public getConsts: (
fctx: FormControlContext
- ) => Promise<Consts> = async () => ({} as Consts)
+ ) => Promise<Consts> = async () => ({}) as Consts
) {
super();
}
async getBackendValues(
fctx: FormControlContext
): Promise<Record<string, FormDataValue>> {
const fieldnames = this.fields.map((f) => f.name);
const result = Object.fromEntries(
Object.entries(fctx.data.raw_values).filter(([key]) =>
fieldnames.includes(key)
)
);
return result;
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
// the A makes it always a valid id, as it cannot start with a number
const id = "A" + randomUUID();
const consts = this.getConsts(fctx);
const frontend_side_refresh_code = (values_code = "getValues()") =>
`render(${values_code}, consts)
.then(result=>document.querySelector("#${id}").innerHTML=result)`;
- return tempstream/* HTML */ `<div>
+ return tempstream /* HTML */ `<div>
<script>
(function () {
const consts = ${"{" +
Object.entries((await consts) || {})
.map(([key, value]) => {
return `"${key}": ${
typeof value === "object"
? JSON.stringify(value)
: typeof value == "string"
- ? '"' + value.toString() + '"'
- : (value as string).toString()
+ ? '"' + value.toString() + '"'
+ : (value as string).toString()
}`;
})
.join(",") +
"}"};
const form_container =
document.currentScript.closest(".form-container");
const render = ${this._render.toString()};
function getValues() {
return Object.fromEntries(
${JSON.stringify(
this.fields.map((field) => field.name)
)}.map((field_name) => {
let input = form_container.querySelector(
\`input[name="\${field_name}"]\`
);
if (!input) {
return [field_name, ""];
}
if (input.type === "radio") {
input = form_container.querySelector(
\`input[name="\${field_name}"]:checked\`
);
}
return [field_name, input.value];
})
);
}
function setupWatcher(field_name) {
form_container
.querySelectorAll(\`input[name="\${field_name}"]\`)
.forEach((input) => {
input.addEventListener("change", () => {
${frontend_side_refresh_code()};
});
});
}
${JSON.stringify(
this.fields.map((field) => field.name)
)}.forEach(setupWatcher);
setTimeout(() => {
${frontend_side_refresh_code(
JSON.stringify(await this.getBackendValues(fctx))
)};
}, 0);
})();
</script>
<div id="${id}">${this._render({}, await consts)}</div>
</div>`;
}
}
diff --git a/src/forms/controls/dropdown.ts b/src/forms/controls/dropdown.ts
index d8480f1..0a0bcea 100644
--- a/src/forms/controls/dropdown.ts
+++ b/src/forms/controls/dropdown.ts
@@ -1,91 +1,88 @@
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import { attribute } from "../../sanitize.js";
import { FormField } from "../fields/field.js";
import { PickFromListField } from "../fields/pick-from-list.js";
import { FormDataValue } from "../form-types.js";
import { FormControlContext } from "./form-control.js";
import { SimpleInput } from "./simple-input.js";
export type DropdownOptions = {
label: string;
autosubmit?: boolean;
autocomplete?: boolean;
};
export type DropdownOption = { value: string; label: string };
export class FreeformDropdown extends SimpleInput {
constructor(
public field: FormField<boolean, string | null>,
public _generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
public options: DropdownOptions = {
label: field.name,
autosubmit: false,
autocomplete: true,
}
) {
super(field, options);
}
async generateOptions(ctx: Context): Promise<DropdownOption[]> {
return this._generateOptions(ctx);
}
async getInputAttributes(
fctx: FormControlContext
): Promise<Record<string, string | boolean>> {
const original = await super.getInputAttributes(fctx);
return {
...original,
...Object.fromEntries([
...(this.options.autosubmit
? [
[
"onchange",
((original.onchange as string | undefined) ||
"") + ";this.form.submit();",
],
- ]
+ ]
: []),
]),
} as Record<string, string>;
}
async renderInput(
ctx: Context,
attributes_str: string,
data: Record<string, FormDataValue>
): Promise<FlatTemplatable> {
const { parsed: picked_value } = await this.field.getParsedValue(
ctx,
data
);
return /* HTML */ tempstream`<select ${attributes_str}>
- ${
- // eslint-disable-next-line @typescript-eslint/restrict-template-expressions
- Promise.resolve(this.generateOptions(ctx)).then((options) =>
- options.map(
- ({ value, label }) =>
- `<option value="${attribute(value)}" ${
- (value || "") == picked_value ? "selected" : ""
- }>${label}</option>`
- )
+ ${Promise.resolve(this.generateOptions(ctx)).then((options) =>
+ options.map(
+ ({ value, label }) =>
+ `<option value="${attribute(value)}" ${
+ (value || "") == picked_value ? "selected" : ""
+ }>${label}</option>`
)
- }
+ )}
</select>`;
}
}
export class Dropdown extends FreeformDropdown {
constructor(
public field: PickFromListField<boolean>,
public options: DropdownOptions = {
label: field.name,
autosubmit: false,
autocomplete: true,
}
) {
super(field, (ctx) => field.generateOptions(ctx), options);
}
}
diff --git a/src/forms/controls/editable-collection-subset.ts b/src/forms/controls/editable-collection-subset.ts
index 1f29dd3..d2d3c2c 100644
--- a/src/forms/controls/editable-collection-subset.ts
+++ b/src/forms/controls/editable-collection-subset.ts
@@ -1,103 +1,104 @@
+/* eslint @typescript-eslint/no-base-to-string: off */
import { FlatTemplatable, tempstream } from "tempstream";
import { attribute } from "../../sanitize.js";
import { PickFromListField } from "../fields/pick-from-list.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
/**
* This control has own forms in it so if you want to use it you
* probably shouldn't use `await super.render(ctx, data, path)` in
* render method of you from implementation and you should write
* your own implementation of this method. See forms that uses
* this control for reference.
*/
export class EditableCollectionSubset extends FormFieldControl {
constructor(
public field: PickFromListField<false>,
public actionname: string,
public listLabel?: string,
public selectLabel?: string
) {
super([field]);
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const { parsed: values } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
- return tempstream/* HTML */ `<div>
+ return tempstream /* HTML */ `<div>
<ul>
${Promise.resolve(this.field.generateOptions(fctx.ctx)).then(
(options) =>
Object.entries(options)
.filter(([value]) =>
(values || ([] as string[])).includes(value)
)
.map(
([value, text]) => /* HTML */ `
<li>
<form
method="POST"
action="${fctx.ctx.path}"
>
<span
>${
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
text
}</span
>
<input
type="hidden"
name="${this.field.name}"
value="${attribute(value)}"
/>
<input
type="hidden"
name="${this.actionname}"
value="list"
/>
<input
type="submit"
${this.listLabel
? `value="${this.listLabel}"`
: ""}
/>
</form>
</li>
`
)
)}
</ul>
<form method="POST" action="${fctx.ctx.path}">
<select name="${this.field.name}">
${Promise.resolve(
this.field.generateOptions(fctx.ctx)
).then((options) =>
Object.entries(options)
.filter(
([value]) =>
!(values || ([] as string[])).includes(
value
)
)
.map(
([value, text]) =>
`<option value="${attribute(value)}">${
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
text
}</option>`
)
)}
</select>
<input type="hidden" name="${this.actionname}" value="select" />
<input
type="submit"
${this.selectLabel ? `value="${this.selectLabel}"` : ""}
/>
</form>
</div>`;
}
role = <const>"input";
}
diff --git a/src/forms/controls/field-group.ts b/src/forms/controls/field-group.ts
index e287d9d..c75cc71 100644
--- a/src/forms/controls/field-group.ts
+++ b/src/forms/controls/field-group.ts
@@ -1,67 +1,67 @@
import { FlatTemplatable, tempstream } from "tempstream";
import { FormControl, FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export class FieldGroup extends FormFieldControl {
constructor(
public controls: FormControl[],
public options: {
label?: string;
classes?: string[];
containerID?: string;
} = {}
) {
super([]);
}
preLabel(): FlatTemplatable {
return "";
}
preLabelContainer(): FlatTemplatable {
return "";
}
postLabel(): FlatTemplatable {
return "";
}
preFields(): FlatTemplatable {
return "";
}
postFields(): FlatTemplatable {
return "";
}
getGroupLabelProps(): FlatTemplatable {
return `class="field-group__label"`;
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const { label, classes } = this.options;
- return tempstream/* HTML */ `
+ return tempstream /* HTML */ `
<div
class="field-group ${(classes || []).join(" ")}"
${this.options.containerID
? `id="${this.options.containerID}"`
: ""}
>
${this.preLabelContainer()}
<div class="field-group__label-container">
${this.preLabel()}
${label
? tempstream`<label ${this.getGroupLabelProps()}>${label}</label>`
: ""}
${this.postLabel()}
</div>
${this.preFields()}
<div class="field-group__fields">
${this.controls.map((control) => control.render(fctx))}
</div>
${this.postFields()}
</div>
`;
}
}
diff --git a/src/forms/controls/file.test.ts b/src/forms/controls/file.test.ts
index f1e3637..a2faf48 100644
--- a/src/forms/controls/file.test.ts
+++ b/src/forms/controls/file.test.ts
@@ -1,81 +1,81 @@
import Router from "@koa/router";
import getPort from "get-port";
import { Browser, Page } from "playwright";
import type { Context } from "koa";
import Koa from "koa";
import { mount } from "../../mount.js";
import { Form } from "../form.js";
import { getBrowser } from "../../utils/browser-creator.js";
import { Controls, Fields, sleep } from "../../index.js";
import _locreq from "locreq";
import { module_dirname } from "../../utils/module-dirname.js";
import { FileManager, PathFilePointer } from "@sealcode/file-manager";
import assert from "node:assert";
const locreq = _locreq(module_dirname(import.meta.url));
describe("file-control", () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
let browser: Browser;
let page: Page;
after(() => {
server.close();
});
it("doesn't require image input if it already has old-value", async () => {
const port = await getPort();
- console.log(`Using port ${port} for image.test.ts`);
+ console.info(`Using port ${port} for image.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
file: new Fields.File(true),
};
let submit_called = false;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new Controls.File(fields.file)];
async onSubmit(_ctx: Context) {
submit_called = true;
}
async getInitialValues(_ctx: Context) {
const file = new PathFilePointer(
new FileManager("/tmp", "/uploaded_files"),
locreq.resolve("assets/important.png")
);
return {
file: await file.save(false), // to get the token
};
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
await sleep(100);
assert(submit_called, "Submit not called - something prevented submit on click?");
});
}).timeout(10000);
});
diff --git a/src/forms/controls/file.ts b/src/forms/controls/file.ts
index 09b446f..42aa5cb 100644
--- a/src/forms/controls/file.ts
+++ b/src/forms/controls/file.ts
@@ -1,89 +1,86 @@
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
-/* eslint-disable @typescript-eslint/no-unsafe-argument */
-/* eslint-disable @typescript-eslint/no-unsafe-member-access */
-/* eslint-disable @typescript-eslint/no-unsafe-call */
+/* eslint @typescript-eslint/no-unsafe-assignment: off, @typescript-eslint/no-unsafe-argument: off, @typescript-eslint/no-unsafe-member-access: off, @typescript-eslint/no-unsafe-call: off */
import { Context } from "koa";
import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
import { FlatTemplatable, tempstream } from "tempstream";
import { FormDataValue } from "../form-types.js";
import { FormControlContext } from "./form-control.js";
import { SimpleInput } from "./simple-input.js";
import { htmlEscape } from "escape-goat";
import { extname } from "node:path";
export class File extends SimpleInput {
getType() {
return "file";
}
async renderFilePreview(
_ctx: Context,
file: FilePointer | null
): Promise<FlatTemplatable> {
const class_name = "file_preview";
const empty_container = `<div class="${class_name}"></div>`;
if (!file) {
return empty_container;
}
if (file instanceof PathFilePointer) {
const filename = await file.getOriginalFilename();
- return tempstream/* HTML */ `<div class="${class_name}">
+ return tempstream /* HTML */ `<div class="${class_name}">
<div class="${class_name}__icon">
<picture>
<img
src="/dist/sealgen/file-icon.svg"
width="80"
height="80"
alt=""
/>
<span class="${class_name}__icon__extension"
>${extname(filename)}</span
>
</picture>
<a href="${file.getURL()}" download>${filename}</a>
</div>
</div>`;
}
- return tempstream/* HTML */ `<div class="${class_name}">
+ return tempstream /* HTML */ `<div class="${class_name}">
${file.getOriginalFilename()}
</div>`;
}
async preInput(
fctx: FormControlContext,
data: Record<string, FormDataValue>
) {
let { parsed } = await this.field.getParsedValue(fctx.ctx, data);
if (parsed === null) {
parsed = { old: null, new: null };
}
- return tempstream/* HTML */ `${this.renderFilePreview(
+ return tempstream /* HTML */ `${this.renderFilePreview(
fctx.ctx,
parsed.old
)}
<input
type="hidden"
name="${this.field.name}[old]"
value="${htmlEscape(
parsed.old?.token || (await parsed.old?.save(false)) || ""
)}"
form="${fctx.form_id}"
/> `;
}
async getInputAttributes(
fctx: FormControlContext
): Promise<Record<string, string | boolean>> {
const original = await super.getInputAttributes(fctx);
const { parsed } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return {
...original,
name: this.field.name + "[new]",
required: original.required && !parsed?.old,
value: false,
};
}
}
diff --git a/src/forms/controls/form-control.ts b/src/forms/controls/form-control.ts
index 5e3d8d4..f1bf06a 100644
--- a/src/forms/controls/form-control.ts
+++ b/src/forms/controls/form-control.ts
@@ -1,31 +1,31 @@
import Router from "@koa/router";
import { Context } from "koa";
import { FlatTemplatable } from "tempstream";
import { FormMessage, FormData } from "../form-types.js";
import type { Form } from "../form.js";
export type FieldMessages<Fieldnames extends string = string> = Record<
Fieldnames,
{ type: "error" | "info"; message: string }
>;
export class FormControlContext {
constructor(
public ctx: Context,
public data: FormData,
public messages: FormMessage[],
public field_name_prefix: string,
public form_id: string,
public validate: boolean
) {}
}
export abstract class FormControl {
abstract render(
fctx: FormControlContext
): FlatTemplatable | Promise<FlatTemplatable>;
abstract role: "input" | "decoration" | "messages" | "submit";
- // eslint-disable-next-line @typescript-eslint/no-empty-function, @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
mount(_router: Router, _form: Form<any, any>) {}
}
diff --git a/src/forms/controls/hidden-input.ts b/src/forms/controls/hidden-input.ts
index c97d1bb..ab95325 100644
--- a/src/forms/controls/hidden-input.ts
+++ b/src/forms/controls/hidden-input.ts
@@ -1,23 +1,24 @@
+/* eslint @typescript-eslint/no-base-to-string: off */
import { FlatTemplatable, tempstream } from "tempstream";
import { attribute } from "../../sanitize.js";
import { FormField } from "../fields/field.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export class HiddenInput extends FormFieldControl {
constructor(public field: FormField) {
super([field]);
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const { raw } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return tempstream`<input type="hidden" name="${
this.field.name
}" value="${attribute((raw || "").toString())}" form="${
fctx.form_id
}">`;
}
}
diff --git a/src/forms/controls/html.ts b/src/forms/controls/html.ts
index 960b142..885c8e4 100644
--- a/src/forms/controls/html.ts
+++ b/src/forms/controls/html.ts
@@ -1,35 +1,36 @@
import { FlatTemplatable } from "tempstream";
import { FormControl, FormControlContext } from "./form-control.js";
type Renderer =
| ((fctx: FormControlContext) => FlatTemplatable)
| FlatTemplatable;
export class HTML extends FormControl {
role = (<const>"decoration") as "decoration" | "submit";
public renderer: Renderer;
constructor(role: "decoration" | "submit", renderer: Renderer);
constructor(renderer: Renderer);
constructor(
+ // eslint-disable-next-line @typescript-eslint/no-redundant-type-constituents
role_or_renderer: "decoration" | "submit" | Renderer,
renderer_or_undefined?: Renderer | FlatTemplatable
) {
super();
if (arguments.length == 2) {
this.role = role_or_renderer as "decoration" | "submit";
this.renderer = renderer_or_undefined as Renderer;
} else {
this.renderer = role_or_renderer;
}
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
if (typeof this.renderer === "string") {
return this.renderer;
}
return typeof this.renderer == "function"
? this.renderer(fctx)
: this.renderer;
}
}
diff --git a/src/forms/controls/image.test.ts b/src/forms/controls/image.test.ts
index cd15259..4634dc9 100644
--- a/src/forms/controls/image.test.ts
+++ b/src/forms/controls/image.test.ts
@@ -1,133 +1,133 @@
import Router from "@koa/router";
import getPort from "get-port";
import { Browser, Page } from "playwright";
import type { Context } from "koa";
import Koa from "koa";
import { mount } from "../../mount.js";
import { Form } from "../form.js";
import { getBrowser } from "../../utils/browser-creator.js";
import { Fields } from "../../index.js";
import { Image } from "./image.js";
import _locreq from "locreq";
import { module_dirname } from "../../utils/module-dirname.js";
import { FileManager, PathFilePointer } from "@sealcode/file-manager";
import assert from "node:assert";
const locreq = _locreq(module_dirname(import.meta.url));
describe("photo-control", () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
let browser: Browser;
let page: Page;
after(() => {
server.close();
});
it("sends the old photo if it wasn't changed and it has an initial value", async () => {
const port = await getPort();
- console.log(`Using port ${port} for photo.test.ts`);
+ console.info(`Using port ${port} for photo.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
photo: new Fields.File(false),
};
let received_photo: unknown;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new Image(fields.photo)];
async onSubmit(ctx: Context) {
const data = await this.getParsedValues(ctx);
received_photo = data.photo;
}
async getInitialValues(_ctx: Context) {
const file = new PathFilePointer(
new FileManager("/tmp", "/uploaded_files"),
locreq.resolve("assets/important.png")
);
return {
photo: await file.save(false), // to get the token
};
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
assert(received_photo !== undefined && (received_photo as any).old !== null);
});
it("doesn't require image input if it already has old-value", async () => {
const port = await getPort();
- console.log(`Using port ${port} for photo.test.ts`);
+ console.info(`Using port ${port} for photo.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
photo: new Fields.File(true),
};
let received_photo: unknown;
let submit_called = false;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new Image(fields.photo)];
async onSubmit(ctx: Context) {
submit_called = true;
const data = await this.getParsedValues(ctx);
received_photo = data.photo;
}
async getInitialValues(_ctx: Context) {
const file = new PathFilePointer(
new FileManager("/tmp", "/uploaded_files"),
locreq.resolve("assets/important.png")
);
return {
photo: await file.save(false), // to get the token
};
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
assert(submit_called, "Submit not called - something prevented submit on click?");
});
}).timeout(10000);
});
diff --git a/src/forms/controls/image.ts b/src/forms/controls/image.ts
index 94ad608..87bede5 100644
--- a/src/forms/controls/image.ts
+++ b/src/forms/controls/image.ts
@@ -1,75 +1,75 @@
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import { File } from "./file.js";
import { FormField } from "../fields/field.js";
import { SimpleInputOptions } from "./simple-input.js";
import { FormControlContext } from "./form-control.js";
import { FileContainer } from "../fields/file.js";
import { FilePointer } from "@sealcode/file-manager";
export class Image extends File {
constructor(
public field: FormField<boolean, FileContainer>,
options?: SimpleInputOptions
) {
super(field, options);
}
async getImgStyle() {
return "width: 100px; height: 100px; object-fit: contain";
}
async renderFilePreview(
ctx: Context,
file: FilePointer | null
): Promise<FlatTemplatable> {
const class_name = "file_preview";
const empty_container = `<div class="${class_name}"></div>`;
if (!file) {
return empty_container;
}
- return tempstream/* HTML */ `<div class="${class_name}">
+ return tempstream /* HTML */ `<div class="${class_name}">
${ctx.$app.imageRouter.image(await file.getPath(), {
resolutions: [100, 200],
sizesAttr: "100px",
crop: { width: 100, height: 100 },
container: { width: 100, height: 100 },
imgStyle: await this.getImgStyle(),
alt: "Image preview",
})}
</div>`;
}
getWrapperModifiers(): string[] {
return [
...super.getWrapperModifiers(),
"control-type__image",
"control-type__photo",
];
}
async getInputAttributes(fctx: FormControlContext) {
const original = await super.getInputAttributes(fctx);
const onchange =
((original.onchange as string) || "") +
";" +
`
const file = this.files[0];
const preview_container = this.parentElement.querySelector(".file_preview");
const target = this;
if (file) {
const fileReader = new FileReader();
fileReader.readAsDataURL(file);
fileReader.addEventListener("load", function () {
preview_container.innerHTML = \`<img src="\${this.result}" style="${await this.getImgStyle()}" />\`;
});
}`
.replaceAll("\n", " ")
.replaceAll(`"`, "'");
return {
...original,
accept: "image/*",
onchange,
};
}
}
diff --git a/src/forms/controls/multiple-files.ts b/src/forms/controls/multiple-files.ts
index 4906b29..475a8c6 100644
--- a/src/forms/controls/multiple-files.ts
+++ b/src/forms/controls/multiple-files.ts
@@ -1,275 +1,273 @@
import Router from "@koa/router";
import { Collection, CollectionItem, Field as SealiousField } from "sealious";
import { Context } from "koa";
import { inputWrapper } from "../../utils/input-wrapper.js";
import { FlatTemplatable, tempstream } from "tempstream";
import { MultipleFiles as MultipleFilesField } from "../fields/multiple-files.js";
import { FormFieldControl } from "./form-field-control.js";
import { is, predicates } from "@sealcode/ts-predicates";
import { renderAttributes } from "../../utils/render-attributes.js";
import { FormControlContext } from "./form-control.js";
import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
export type MultipleFilesOptions = {
label?: string;
uploadLabel?: string;
getAdditionalFields: (
ctx: Context,
file: FilePointer
) => Promise<Record<string, unknown>>;
};
export class MultipleFiles extends FormFieldControl {
public options: MultipleFilesOptions;
constructor(
public field: MultipleFilesField,
options?: Partial<MultipleFilesOptions>
) {
super([field]);
this.options = { getAdditionalFields: async () => ({}), ...options };
}
getClassModifiers(): string[] {
return [];
}
mount(router: Router) {
router.get(this.getFrameRelativeURL(), async (ctx) => {
ctx.body = this.renderFrame(
ctx,
await this.renderFrameContent(ctx)
);
});
router.post(
this.getFrameRelativeURL() + "/delete/:file_item_id",
async (ctx) => {
await this.deleteFileAssociation(ctx, ctx.params.file_item_id);
ctx.body = this.renderFrame(
ctx,
await this.renderFrameContent(ctx)
);
}
);
router.post(this.getFrameRelativeURL() + "/add", async (ctx) => {
let files = ctx.$body.files as FilePointer | FilePointer[];
if (!files || !is(files, predicates.object)) {
ctx.body = "Missing files";
return;
}
if (!Array.isArray(files)) {
files = [files];
}
await Promise.all(
files.map((file) =>
this.addFileAssociation(ctx, file as unknown as FilePointer)
)
);
ctx.body = this.renderFrame(
ctx,
await this.renderFrameContent(ctx)
);
});
}
async deleteFileAssociation(ctx: Context, file_item_id: string) {
await ctx.$app.collections[
this.field.collection_field.referencing_collection
].removeByID(ctx.$context, file_item_id);
}
async addFileAssociation(ctx: Context, file: FilePointer) {
const file_field = this.getFileField();
if (!file_field) {
throw new Error("No file field in referencing collection");
}
const body = {
...(await this.options.getAdditionalFields(ctx, file)),
[this.field.collection_field.referencing_field]:
await this.field.getItemId(ctx),
[file_field.name]: file,
};
await ctx.$app.collections[
this.field.collection_field.referencing_collection
].create(ctx.$context, body);
}
getFrameRelativeURL() {
return `${this.field.name}_files`;
}
getFrameID(): string {
// the "A" is necessary here
return `A${this.field.name}__multiple-fields-control`;
}
renderFrame(_ctx: Context, content?: FlatTemplatable) {
- return tempstream/* HTML */ `<turbo-frame
+ return tempstream /* HTML */ `<turbo-frame
${content ? "" : `src="./${this.getFrameRelativeURL()}"`}
id="${this.getFrameID()}"
target="_top"
>
${content || ""}
</turbo-frame>`;
}
render(
fctx: FormControlContext
): FlatTemplatable | Promise<FlatTemplatable> {
return this.renderFrame(fctx.ctx, "");
}
getReferencingCollection() {
const result =
this.field.collection_field.app.collections[
this.field.collection_field.referencing_collection
];
return result;
}
// eslint-disable-next-line @typescript-eslint/no-explicit-any
getFileField(): SealiousField<any> | null {
for (const [_, field] of Object.entries(
this.getReferencingCollection().fields
)) {
if (field.handles_large_data) {
return field;
}
}
return null;
}
async extractFileFromItem(
item: CollectionItem<Collection>
): Promise<FilePointer | null> {
const sealious_field = this.getFileField();
if (!sealious_field) {
return null;
}
const token = (item.get(sealious_field.name) as FilePointer).token;
if (!token) {
return null;
}
return await item.collection.app.fileManager.fromToken(token);
}
async renderFileItemPreview(
_fileItem: CollectionItem,
file: FilePointer
): Promise<FlatTemplatable> {
return file.getOriginalFilename();
}
async renderFileItem(
fileItem: CollectionItem,
file: FilePointer
): Promise<FlatTemplatable> {
if (!(file instanceof PathFilePointer)) {
return "";
}
- return tempstream/* HTML */ `<li class="file-list-item">
+ return tempstream /* HTML */ `<li class="file-list-item">
<a
class="file-list-item__preview"
href="${file.getURL()}"
data-turbo="false"
>
${this.renderFileItemPreview(fileItem, file)}
</a>
${this.renderFileRemoveButton(fileItem)}
</li>`;
}
renderFileRemoveButton(fileItem: CollectionItem): FlatTemplatable {
return /* HTML */ ` <form
data-turbo-frame="${this.getFrameID()}"
action="${this.getFrameRelativeURL()}/delete/${fileItem.id}"
method="POST"
>
<input
type="submit"
value="X"
class="file-list-action file-list-item__button file-list-item__button--delete"
/>
</form>`;
}
async getFileItems(ctx: Context) {
const item_id = await this.field.getItemId(ctx);
const {
items: [item],
} = await this.field.collection_field.collection
.list(ctx.$context)
.ids([item_id])
.attach({ [this.field.collection_field.name]: true })
.fetch();
return item
.getAttachments(this.field.collection_field.name)
.filter((f) => f);
}
getInputAttributes() {
return { type: "file", name: "files", multiple: true };
}
async renderFrameContent(ctx: Context): Promise<FlatTemplatable> {
const files = (
await Promise.all(
- (
- await this.getFileItems(ctx)
- )
+ (await this.getFileItems(ctx))
.filter((item) => item) // filter out undefineds
.map(async (item: CollectionItem<Collection>) => [
item,
await this.extractFileFromItem(item),
])
)
).filter(([_, f]) => f !== null) as [
CollectionItem<Collection>,
- FilePointer
+ FilePointer,
][];
return inputWrapper(
"multiple-files",
["multiple-files", this.field.name, ...this.getClassModifiers()],
- tempstream/* HTML */ `
+ tempstream /* HTML */ `
<label>${this.options.label || this.field.name}</label>
<ul class="multiple-files__list">
${files.map(([item, file]) =>
this.renderFileItem(item, file)
)}
</ul>
<form
action="${this.getFrameRelativeURL()}/add"
method="POST"
enctype="multipart/form-data"
data-turbo-frame="${this.getFrameID()}"
>
<input ${renderAttributes(this.getInputAttributes())} />
<input
type="submit"
value="${this.options.uploadLabel || "Upload"}"
class="file-list-action"
/>
</form>
`
);
}
setLabel(label: string) {
this.options.label = label;
}
setUploadLabel(label: string) {
this.options.uploadLabel = label;
}
setAdditionalFieldsGetter(
fn: (
ctx: Context,
file: FilePointer
) => Promise<Record<string, unknown>>
) {
this.options.getAdditionalFields = fn;
}
}
diff --git a/src/forms/controls/multiple-images.ts b/src/forms/controls/multiple-images.ts
index 5fd51fb..ed2ce83 100644
--- a/src/forms/controls/multiple-images.ts
+++ b/src/forms/controls/multiple-images.ts
@@ -1,50 +1,50 @@
import { CollectionItem } from "sealious";
import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
import { FlatTemplatable, tempstream } from "tempstream";
import { MultipleFiles, MultipleFilesOptions } from "./multiple-files.js";
import { MultipleFiles as MultipleFilesField } from "../fields/multiple-files.js";
import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
export class MultipleImages extends MultipleFiles {
constructor(
public field: MultipleFilesField,
public imageRouter: KoaResponsiveImageRouter,
options?: Partial<MultipleFilesOptions>
) {
super(field, options);
}
getClassModifiers() {
return ["multiple-files--photos"];
}
getInputAttributes() {
return { ...super.getInputAttributes(), accept: "image/*" };
}
async renderFileItem(
fileItem: CollectionItem,
file: FilePointer
): Promise<FlatTemplatable> {
if (!(file instanceof PathFilePointer)) {
return "";
}
const path = await file.getPath();
if (!path) {
return "missing file";
}
- return tempstream/* HTML */ `<li>
+ return tempstream /* HTML */ `<li>
<a href="${file.getURL()}" data-turbo="false">
${this.imageRouter.image(path, {
resolutions: [150, 300],
sizesAttr: "150px",
alt: "",
})}
</a>
<span class="filename">
${(await file.getOriginalFilename()) || "no filename"}</span
>
${this.renderFileRemoveButton(fileItem)}
</li>`;
}
}
diff --git a/src/forms/controls/simple-input.ts b/src/forms/controls/simple-input.ts
index d370b85..328d4f9 100644
--- a/src/forms/controls/simple-input.ts
+++ b/src/forms/controls/simple-input.ts
@@ -1,141 +1,145 @@
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
import { renderAttributes } from "../../utils/render-attributes.js";
import { FormField } from "../fields/field.js";
import { FormDataValue } from "../form-types.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export type SimpleInputOptions = {
id?: string;
label?: string;
autocomplete?: boolean;
hide_errors?: boolean;
type?: string;
value?: string;
placeholder?: string;
readonly?: boolean;
step?: number;
suffix?: string;
pattern?: string;
};
export class SimpleInput<
- Options extends SimpleInputOptions = SimpleInputOptions
+ Options extends SimpleInputOptions = SimpleInputOptions,
> extends FormFieldControl {
options: SimpleInputOptions;
- constructor(public field: FormField<boolean, any>, options?: Options) {
+ constructor(
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ public field: FormField<boolean, any>,
+ options?: Options
+ ) {
super([field]);
this.options = options || {};
}
async preInput(
_ctx: FormControlContext,
_data: Record<string, FormDataValue>
): Promise<FlatTemplatable> {
return "";
}
getType(): string {
return this.options.type || "text";
}
getLabel(): string {
return this.options.label != undefined
? this.options.label
: this.field.name;
}
getID(): string {
return this.options.id || this.field.name;
}
getPlaceholder(): string {
return this.options.placeholder === ""
? ""
: this.options.placeholder || this.getType();
}
async getInputAttributes(
fctx: FormControlContext
): Promise<Record<string, string | boolean>> {
const readonly = this.options.readonly || false;
const required = this.field.required;
const { raw, valid } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values,
true
);
return Object.fromEntries([
<const>["id", this.getID()],
<const>["type", this.getType()],
<const>["name", `${fctx.field_name_prefix}${this.field.name}`],
<const>["value", raw],
...(fctx.form_id ? [["form", fctx.form_id]] : []),
<const>["placeholder", this.getPlaceholder()],
...(readonly ? [["readonly", true]] : []),
...(required ? [["required", true]] : []),
...(!this.options.autocomplete ? [["autocomplete", "off"]] : []),
...(this.options.step ? [["step", this.options.step]] : []),
["aria-invalid", String(!valid)],
]) as Record<string, string>;
}
async postInput(_: Context): Promise<FlatTemplatable> {
return this.options.suffix
? /* HTML */ `<span class="suffix">${this.options.suffix}</span>`
: "";
}
async renderInput(
_ctx: Context,
attributes_str: string,
_data: Record<string, FormDataValue>
): Promise<FlatTemplatable> {
return `<input ${attributes_str} />`;
}
getWrapperModifiers(): string[] {
return [
this.getID(),
this.getType(),
"type__" + this.getType(),
getRequiredClass(this.field.required),
];
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
const id = this.getID();
const label = this.getLabel();
const { valid, message } = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values,
true
);
return inputWrapper(
"simple-input",
this.getWrapperModifiers(),
- tempstream/* HTML */ `
+ tempstream /* HTML */ `
${label ? `<label for="${id}">${label}</label>` : ""}
${await this.preInput(fctx, fctx.data.raw_values)}
${this.renderInput(
fctx.ctx,
renderAttributes(await this.getInputAttributes(fctx)),
fctx.data.raw_values
)}
${this.postInput(fctx.ctx)}
${~valid && !this.options.hide_errors && fctx.validate
? `<div class="input__error">${[
message,
fctx.data.field_messages?.[this.field.name]
?.message,
- ]
+ ]
.filter((e) => !!e)
.join(" · ")}</div>`
: ""}
`
);
}
}
diff --git a/src/forms/controls/single-reference.test.ts b/src/forms/controls/single-reference.test.ts
index 2738422..7b7f887 100644
--- a/src/forms/controls/single-reference.test.ts
+++ b/src/forms/controls/single-reference.test.ts
@@ -1,64 +1,64 @@
import { Page } from "playwright";
import { collectionTemplate } from "../../templates/collection.js";
import { formTemplate } from "../../templates/form.js";
import { RealAppTest } from "../../test_utils/test-on-real-app.js";
import { getBrowser } from "../../utils/browser-creator.js";
import { expect as PlaywritghtExpect } from "@playwright/test";
describe("single-reference.test", () => {
let page: Page;
before(async () => {
const browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
});
after(async () => {
await page.close();
});
it("creates minimal sealious app and adds form using single-reference field that works", async function () {
const test_app = await RealAppTest.init();
// add possiblity to modify templates (form and collection) and create test case
await test_app.addFile(
"src/back/collections/articles.ts",
collectionTemplate("articles", `title: new FieldTypes.Text(),`)
);
await test_app.addFile(
"src/back/collections/comments.ts",
collectionTemplate(
"comments",
`text: new FieldTypes.Text(),
article: new FieldTypes.SingleReference("articles"),`
)
);
const form_file_path = "src/back/routes/some-form.form.ts";
await test_app.addFile(
form_file_path,
- await formTemplate("SomeForm", form_file_path, {
+ await formTemplate("SomeForm", {
postimport: `import {Comments} from "../collections/collections.js"; import {Fields} from "@sealcode/sealgen";`,
fields: `article: new Fields.CollectionField(true, Comments.fields.article),`,
controls: `new Controls.SingleReferenceDropdown(fields.article, {getLabel: item=>item.get("title")}),`,
validate_method: "",
success_message: "Submit OK",
})
);
await test_app.start();
await test_app.httpPOST(`/api/v1/collections/articles`, { title: "article 1" });
await test_app.httpPOST(`/api/v1/collections/articles`, { title: "article 2" });
await page.goto(`http://localhost:${test_app.app_port}/some-form/`);
await page.locator("html").click();
await PlaywritghtExpect(page.getByLabel("article")).toBeVisible();
await page.getByLabel("article").selectOption({ label: "article 2" });
await page.getByRole("button", { name: "Wyślij" }).click();
await page.getByLabel("article").selectOption({ label: "--" }); // "--" means empty value - it should be available, as the field is not required
await test_app.close();
}).timeout(100 * 1000);
});
diff --git a/src/forms/controls/single-reference.ts b/src/forms/controls/single-reference.ts
index 42383a8..1e5ce31 100644
--- a/src/forms/controls/single-reference.ts
+++ b/src/forms/controls/single-reference.ts
@@ -1,49 +1,49 @@
import { FieldTypes as SealiousFieldTypes } from "sealious";
import { CollectionField } from "../fields/collection-field.js";
import { DropdownOptions, FreeformDropdown } from "./dropdown.js";
import { Collection, CollectionItem } from "sealious";
export class SingleReferenceDropdown<
TargetCollection extends Collection,
F extends SealiousFieldTypes.SingleReference,
- Required extends boolean
+ Required extends boolean,
> extends FreeformDropdown {
constructor(
public field: CollectionField<F, Required>,
public options: DropdownOptions & {
getLabel?: (item: CollectionItem<Collection>) => string;
} = {
label: field.name,
autosubmit: false,
autocomplete: true,
}
) {
super(
field,
async (ctx) => {
const { items } = await ctx.$app.collections[
field.sealiousField.target_collection
]
.list(ctx.$context)
.fetch();
return [
{ value: "", label: "--" },
...items.map((item) => ({
value: item.id,
label: options.getLabel
? options.getLabel(item)
: item.id,
})),
];
},
options
);
}
setOptionLabelGetter(
getter: (item: CollectionItem<TargetCollection>) => string
): this {
this.options.getLabel = getter;
return this;
}
}
diff --git a/src/forms/controls/table.ts b/src/forms/controls/table.ts
index 1c6ac41..7127e75 100644
--- a/src/forms/controls/table.ts
+++ b/src/forms/controls/table.ts
@@ -1,318 +1,313 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
import Router from "@koa/router";
import { hasShape, is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import qs from "qs";
import { FlatTemplatable, tempstream } from "tempstream";
import { FormField } from "../fields/field.js";
import {
ExtractFormFieldParsed,
Table as TableField,
} from "../fields/table.js";
import { FormReaction } from "../form-types.js";
import { Form } from "../form.js";
import { FormControl, FormControlContext } from "./form-control.js";
export type TableControlOptions<F extends Record<string, FormField>> = {
subfield_controls: {
[field_name in keyof F]: FormControl;
};
allow_removing?: boolean;
label_add?: string;
label: string;
label_remove?: string;
} & (
| { allow_adding: false }
| {
allow_adding: true;
make_new_row: (
ctx: Context
) => Promise<{ [field_name in keyof F]: unknown }>;
}
);
export const TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER =
"TABLE_ROW_INDEX________________";
export class Table<F extends Record<string, FormField>> extends FormControl {
role = <const>"input";
constructor(
public table_field: TableField<F>,
public options: TableControlOptions<F>
) {
super();
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
let rows = fctx.data.raw_values?.[this.table_field.name] as any[];
if (!rows) {
rows = [];
}
const get_row_fctx = (
row:
| {
[field_name in keyof F]: ExtractFormFieldParsed<
F[field_name]
>;
}
| null,
row_index: number | string
) => {
return typeof row_index == "number"
? {
data: {
raw_values:
(Object.fromEntries(
Object.entries(
row as Record<string, unknown>
).map(([key, value]) => [
this.table_field.columns[key].name,
value,
])
) as any) || {},
messages: [],
field_messages: {},
},
- }
+ }
: {};
};
const make_row = async (
row:
| {
[field_name in keyof F]: ExtractFormFieldParsed<
F[field_name]
>;
}
| null,
row_index: number | string
) => {
return /* HTML */ tempstream`<tr>
- ${(
- await Promise.all(
- Object.entries(this.table_field.columns).map(
- ([column_name]) => {
- const inner_fctx = get_row_fctx(
- row,
- row_index
- );
- return tempstream`<td>${this.options.subfield_controls[
- column_name
- ].render({ ...fctx, ...inner_fctx })}</td>`;
- }
+ ${Promise.all(
+ Object.entries(this.table_field.columns)
+ .map(([column_name]) => {
+ const inner_fctx = get_row_fctx(row, row_index);
+ return tempstream`<td>${this.options.subfield_controls[
+ column_name
+ ].render({ ...fctx, ...inner_fctx })}</td>`;
+ })
+ .map(async (html) =>
+ (await html).replaceAll(
+ TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
+ row_index.toString()
+ )
)
- )
- ).map((html) =>
- html.replaceAll(
- TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
- row_index.toString()
- )
)}
${
this.options.allow_removing
? /* HTML */ `<td>
<button
onclick="this.closest('tr').remove()"
>
remove
</button>
<noscript>
<input
type="submit"
data-turbo-frame="${this.getFrameID()}"
value="${this.options
.label_remove || "remove"}"
form="${fctx.form_id}"
formnovalidate
formaction="${this.getActionURL(
this.table_field.name,
{
remove: {
index: row_index,
},
}
)}"
/>
</noscript>
- </td>`
+ </td>`
: ""
}
</tr>`;
};
- return tempstream/* HTML */ `<turbo-frame
+ return tempstream /* HTML */ `<turbo-frame
id="${this.getFrameID()}"
class="${[
"form-input__wrapper",
"form-input__wrapper--type--table",
"form-input__wrapper--options-count--" + rows.length.toString(),
...(rows.length >= 5
? ["form-input__wrapper--options-count--5-or-more"]
: []),
...(rows.length >= 10
? ["form-input__wrapper--options-count--10-or-more"]
: []),
...(rows.length >= 15
? ["form-input__wrapper--options-count--15-or-more"]
: []),
...(rows.length >= 20
? ["form-input__wrapper--options-count--20-or-more"]
: []),
].join(" ")}"
>
<label>${this.options.label}</label>
<div class="table__wrapper">
<table>
<tbody>
${rows?.map((row, index) => make_row(row, index))}
</tbody>
</table>
<template>
${make_row(null, TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER)}
</template>
${
/* because of https://github.com/ljharb/qs/issues/252 we have to
put the indexes in the field names */
this.options.allow_adding
? /* HTML */ `<button
data-controller="table-add-button"
data-action="click->table-add-button#addRow"
data-table-placeholder="${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}"
>
${this.options.label_add || "add"}
</button>
<noscript>
<input
type="submit"
value="add"
form="${fctx.form_id}"
formnovalidate
formaction="${this.getActionURL(
this.table_field.name,
{
insert: {
index: rows.length,
value: {},
},
}
)}"
/>
</noscript>`
: ""
}
</div>
</turbo-frame>`;
}
getFrameID() {
return `array-frame-${this.table_field.name}`;
}
getActionURL(field_name: string, action: Record<string, unknown>) {
return `./?${qs.stringify({
action,
field_name,
})}`;
}
mount(router: Router, form: Form<any, any>) {
router.post("/", async (ctx, next) => {
const action = ctx.$body.action;
const field_name = ctx.$body.field_name;
if (
!is(action, predicates.object) ||
!is(field_name, predicates.string)
) {
await next();
return;
}
if (
this.options.allow_adding &&
hasShape(
{
insert: predicates.shape({ index: predicates.string }),
},
action
)
) {
if (field_name !== this.table_field.name) {
await next();
return;
}
if (!ctx.$body[this.table_field.name]) {
ctx.$body[this.table_field.name] = {};
}
(ctx.$body[this.table_field.name] as any)[action.insert.index] =
await this.options.make_new_row(ctx);
}
if (
hasShape(
{
remove: predicates.shape({ index: predicates.string }),
},
action
)
) {
if (field_name !== this.table_field.name) {
await next();
return;
}
if (!ctx.$body[this.table_field.name]) {
ctx.$body[this.table_field.name] = {};
}
(ctx.$body[this.table_field.name] as any) = Object.fromEntries(
Object.entries(
Object.values(
ctx.$body[this.table_field.name] as any
).filter(
(_, index) => index != parseInt(action.remove.index)
)
)
);
}
ctx.override_reaction = {
action: "stay",
content: await form.render(
ctx,
{
raw_values: await form.extractRawValues(ctx),
messages: [],
field_messages: {},
},
false
),
} as FormReaction;
await next();
});
}
setAllowRemoving(value: boolean) {
this.options.allow_removing = value;
return this;
}
setAllowAdding(value: boolean) {
this.options.allow_adding = value;
return this;
}
setLabel(value: string) {
this.options.label = value;
return this;
}
setRemoveLabel(value: string) {
this.options.label_remove = value;
return this;
}
setAddLabel(value: string) {
this.options.label_add = value;
return this;
}
}
diff --git a/src/forms/controls/textarea.ts b/src/forms/controls/textarea.ts
index c77eeef..af8bdec 100644
--- a/src/forms/controls/textarea.ts
+++ b/src/forms/controls/textarea.ts
@@ -1,57 +1,57 @@
import { Context } from "koa";
import { FormField } from "../fields/field.js";
import { FormDataValue } from "../form-types.js";
import { FormControlContext } from "./form-control.js";
import { SimpleInput, SimpleInputOptions } from "./simple-input.js";
export class Textarea extends SimpleInput {
constructor(
public field: FormField<boolean>,
public options: SimpleInputOptions & {
label?: string;
rows?: number;
cols?: number;
description?: string;
autogrow?: boolean;
} = {}
) {
super(field, options);
}
renderDescription() {
return this.options.description
? /* HTML */ `<div class="form-input__description">
${this.options.description}
- </div>`
+ </div>`
: "";
}
async getInputAttributes(
fctx: FormControlContext
): Promise<Record<string, string | boolean>> {
const original = await super.getInputAttributes(fctx);
let onkeydown = original.onkeydown || "";
if (this.options.autogrow) {
onkeydown += `;this.style.height = '5px';this.style.height = Math.max((this.scrollHeight)+32, ${
((this.options.rows || 2) + 1) * 16
} )+'px';`;
}
return {
...original,
rows: this.options.rows ? this.options.rows.toString() : false,
cols: this.options.cols ? this.options.cols.toString() : false,
onkeydown,
};
}
async renderInput(
ctx: Context,
attributes: string,
data: Record<string, FormDataValue>
) {
const { parsed: value } = await this.field.getParsedValue(ctx, data);
return /* HTML */ `<textarea ${attributes}>
${String(value) || ""}</textarea
>`;
}
}
diff --git a/src/forms/controls/tickable.ts b/src/forms/controls/tickable.ts
index db5d54b..3fb78f4 100644
--- a/src/forms/controls/tickable.ts
+++ b/src/forms/controls/tickable.ts
@@ -1,138 +1,136 @@
import { Context } from "koa";
import { FlatTemplatable } from "tempstream";
import { attribute } from "../../sanitize.js";
import { getRequiredClass, inputWrapper } from "../../utils/input-wrapper.js";
import { FormField } from "../fields/field.js";
import { FormDataValue } from "../form-types.js";
import { FormControlContext } from "./form-control.js";
import { FormFieldControl } from "./form-field-control.js";
export type TickableOptions<T> = {
id?: string;
name?: string;
label?: string;
hide_errors?: boolean;
readonly?: boolean;
default_value: T;
};
export abstract class Tickable<T> extends FormFieldControl {
constructor(
public field: FormField<boolean, T>,
public options: TickableOptions<T>
) {
super([field]);
}
public type: "checkbox" | "radio";
abstract getValueAttribute(
ctx: Context,
data: Record<string, FormDataValue>,
value: T
): string;
abstract isChecked(
ctx: Context,
data: Record<string, FormDataValue>,
value: T
): boolean;
makeInputID(
ctx: Context,
data: Record<string, FormDataValue>,
value: T
): string {
const value_attr = this.getValueAttribute(ctx, data, value);
return (
this.options.id ||
this.field.name + (value_attr ? "--" + value_attr : "")
);
}
getWrapperClasses(
ctx: Context,
data: Record<string, FormDataValue>,
value: T
): string[] {
return [
this.makeInputID(ctx, data, value),
this.type,
this.field.name.replaceAll(/\W/g, "-"),
getRequiredClass(this.field.required),
...(this.isChecked(ctx, data, value) ? ["checked"] : []),
];
}
async render(fctx: FormControlContext): Promise<FlatTemplatable> {
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const {
parsed: _parsed,
valid,
message,
} = await this.field.getParsedValue(
fctx.ctx,
fctx.data.raw_values,
true
);
const parsed = _parsed === null ? this.options.default_value : _parsed;
const value = this.getValueAttribute(
fctx.ctx,
fctx.data.raw_values,
parsed
);
const id = this.makeInputID(fctx.ctx, fctx.data.raw_values, parsed);
const label =
this.options.label != undefined
? this.options.label
: this.field.name;
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const readonly = this.options.readonly || false;
const required = this.field.required;
return inputWrapper(
this.type,
this.getWrapperClasses(fctx.ctx, fctx.data.raw_values, parsed),
/* HTML */ `
<input
id="${id}"
type="${this.type}"
name="${fctx.field_name_prefix}${this.options.name ||
this.field.name}"
${value ? `value="${attribute(value)}"` : ""}
${fctx.form_id ? `form="${fctx.form_id}"` : ""}
${this.isChecked(fctx.ctx, fctx.data.raw_values, parsed)
? "checked"
: ""}
${readonly ? "readonly" : ""}
${required ? "required" : ""}
autocomplete="off"
onchange="this.closest('.form-container').querySelectorAll('.form-input__wrapper--${this
.field
.name}').forEach(e=>e.setAttribute('data-checked','false'));
this.closest('.form-input__wrapper').setAttribute('data-checked',this.checked);"
/>
<label for="${id}">${label}</label>
<script>
(function () {
let wrapper = document.currentScript.closest(
".form-input__wrapper"
);
wrapper.setAttribute(
"data-checked",
wrapper.querySelector("input").checked.toString()
);
})();
</script>
${~valid && !this.options.hide_errors && fctx.validate
? `<div class="input__error">${message}</div>`
: ""}
`
);
}
}
diff --git a/src/forms/fields/boolean.ts b/src/forms/fields/boolean.ts
index 22e69c4..5718ec0 100644
--- a/src/forms/fields/boolean.ts
+++ b/src/forms/fields/boolean.ts
@@ -1,85 +1,88 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { Checkbox } from "../controls/checkbox.js";
import { FormDataValue } from "../form-types.js";
import { FieldParseResult, FormField } from "./field.js";
import { FormControlContext } from "../controls/form-control.js";
const truthy = ["true", "on", "yes", "1"];
const falsy = ["false", "off", "no", "0"];
export class Boolean<Required extends boolean> extends FormField<
Required,
boolean,
Checkbox
> {
predicate = predicates.boolean;
- constructor(required: Required, public error_message: string = "") {
+ constructor(
+ required: Required,
+ public error_message: string = ""
+ ) {
super(required);
}
public async isValueValid(
_: Context,
value: boolean
): Promise<{ valid: boolean; message: string }> {
if (this.required && !value) {
return { valid: false, message: this.error_message };
}
return { valid: true, message: "" };
}
async parse(
_: Context,
value: FormDataValue
): Promise<FieldParseResult<boolean>> {
if (is(value, predicates.boolean)) {
return { parsable: true, parsed_value: value, error: null };
} else if (
is(value, predicates.string) &&
[...truthy, ...falsy].includes(value)
) {
return {
parsable: true,
parsed_value: truthy.includes(value),
error: null,
};
} else if (is(value, predicates.undefined)) {
return {
parsable: true,
parsed_value: false,
error: null,
};
} else if (value === null || value === "") {
return { parsable: true, parsed_value: false, error: null };
} else {
return {
parsable: false,
parsed_value: null,
error: "Please enter a boolean",
};
}
}
public getEmptyValue(): boolean {
return false;
}
public getControl(): Checkbox {
return new Checkbox(this, { label: this.name });
}
async getSealiousCreateValue(fctx: FormControlContext): Promise<boolean> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return !!parsed;
}
async sealiousValueToForm(
_: Context,
value: boolean | null
): Promise<FormDataValue> {
return value ? "true" : "false";
}
}
diff --git a/src/forms/fields/checkboxed-list.ts b/src/forms/fields/checkboxed-list.ts
index e34e39c..ebbb708 100644
--- a/src/forms/fields/checkboxed-list.ts
+++ b/src/forms/fields/checkboxed-list.ts
@@ -1,79 +1,79 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { CheckboxedListInput } from "../controls/checkboxed-list-input.js";
import { FormDataValue } from "../form-types.js";
import {
FieldParseResult,
FormField,
FormFieldValidationResponse,
} from "./field.js";
export type CheckboxedListItem = {
value: string;
label?: string;
group?: string;
};
export class CheckboxedListField<
Required extends boolean,
- Values extends string
+ Values extends string,
> extends FormField<
Required,
Record<Values, "on">,
CheckboxedListInput<Values>
> {
constructor(
public required: Required,
public generateOptions: (ctx: Context) => Promise<CheckboxedListItem[]>,
public isVisible: (ctx: Context) => Promise<boolean> = () =>
Promise.resolve(true)
) {
super(required);
}
predicate = predicates.array(predicates.string); // TODO: this is probably wrong
public async isValueValid(
_: Context,
value: unknown
): Promise<FormFieldValidationResponse> {
if (is(value, predicates.string)) {
return { valid: false, message: "you need an array" };
}
if (is(value, predicates.null)) {
return { valid: false, message: "you need an array" };
}
return { valid: true, message: "" };
}
async parse(
_: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<Record<string, "on">>> {
if (is(raw_value, predicates.object)) {
return {
parsable: true,
parsed_value: Object.fromEntries(
Object.entries(raw_value).filter(
([, value]) => value === "on"
)
) as Record<string, "on">,
error: null,
};
} else {
return {
parsed_value: null,
parsable: false,
error: "Expected an object",
};
}
}
public getEmptyValue(): Record<string, "on"> {
return {};
}
getControl(): CheckboxedListInput<Values> {
return new CheckboxedListInput(this, { label: this.name });
}
}
diff --git a/src/forms/fields/collection-field.ts b/src/forms/fields/collection-field.ts
index 7b53d4d..df378fc 100644
--- a/src/forms/fields/collection-field.ts
+++ b/src/forms/fields/collection-field.ts
@@ -1,80 +1,83 @@
import { predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { Depromisify, ExtractFieldDecoded, Field } from "sealious";
import { SimpleInput } from "../controls/controls.js";
import { FormDataValue } from "../form-types.js";
import {
FieldParseResult,
FormField,
FormFieldValidationResponse,
} from "./field.js";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
export class CollectionField<
// eslint-disable-next-line @typescript-eslint/no-explicit-any
F extends Field<any>,
- Required extends boolean
+ Required extends boolean,
> extends FormField<Required, ExtractFieldDecoded<F> | null, SimpleInput> {
- constructor(required: Required, public sealiousField: F) {
+ constructor(
+ required: Required,
+ public sealiousField: F
+ ) {
super(required);
}
predicate = predicates.unknown;
async parse(
ctx: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<ExtractFieldDecoded<F> | null>> {
if (raw_value === undefined) {
return { parsable: true, parsed_value: null, error: null };
}
const encoded_value = (await this.sealiousField.encode(
ctx.$context,
raw_value
)) as Depromisify<ReturnType<F["encode"]>>;
const parsed_value = (await this.sealiousField.decode(
ctx.$context,
encoded_value,
null,
this.sealiousField.typeName == "text" ? "original" : {}
)) as ExtractFieldDecoded<F>;
return {
parsable: true,
error: null,
parsed_value,
};
}
public async isValueValid(
ctx: Context,
value: ExtractFieldDecoded<F>
): Promise<FormFieldValidationResponse> {
const { valid, reason } = await this.sealiousField.checkValue(
ctx.$context,
value,
undefined,
null
);
return { valid, message: reason || (!valid ? "Wrong value" : "") };
}
public getEmptyValue(): ExtractFieldDecoded<F> {
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return "" as unknown as ExtractFieldDecoded<F>;
}
getControl(): SimpleInput {
return new SimpleInput(this);
}
generateFieldDeclaration(
field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${String(
field_info.is_required
)}, ${vars.sealious_field})`;
}
}
diff --git a/src/forms/fields/color.ts b/src/forms/fields/color.ts
index dac5558..b7cb67d 100644
--- a/src/forms/fields/color.ts
+++ b/src/forms/fields/color.ts
@@ -1,9 +1,9 @@
import { TextBasedSimpleField } from "./simple-form-field.js";
export class Color<
- Required extends boolean
+ Required extends boolean,
> extends TextBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "color");
}
}
diff --git a/src/forms/fields/coordinates.ts b/src/forms/fields/coordinates.ts
index d9a9c86..76f3a25 100644
--- a/src/forms/fields/coordinates.ts
+++ b/src/forms/fields/coordinates.ts
@@ -1,66 +1,66 @@
import { Context } from "koa";
import { FormControl, FormControlContext } from "../controls/form-control.js";
import { SimpleInput } from "../controls/simple-input.js";
import { FormDataValue } from "../form-types.js";
import { FieldParseResult } from "./field.js";
import { SimpleFormField } from "./simple-form-field.js";
export class Coordinates<
Required extends boolean,
- DefaultControl extends FormControl = SimpleInput
+ DefaultControl extends FormControl = SimpleInput,
> extends SimpleFormField<Required, DefaultControl, [number, number]> {
async parse(
_: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<[number, number]>> {
if (typeof raw_value == "string") {
return {
parsed_value: raw_value
?.split(",")
.map((e) => parseFloat(e)) as [number, number],
parsable: true,
error: null,
};
}
if (Array.isArray(raw_value)) {
return {
parsed_value: raw_value.map((e) => parseFloat(e)) as [
number,
- number
+ number,
],
parsable: true,
error: null,
};
}
return {
parsed_value: null,
parsable: false,
error: "should be an array or string",
};
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<[number, number] | undefined> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || undefined;
}
async postSealiousCreate(): Promise<void> {}
async postSealiousEdit(): Promise<void> {}
getControl(): DefaultControl {
return new SimpleInput(this, {
label: this.name,
type: this.type,
}) as unknown as DefaultControl;
}
public getEmptyValue(): [number, number] {
return [0, 0];
}
}
diff --git a/src/forms/fields/deep-reverse-single-reference-list.ts b/src/forms/fields/deep-reverse-single-reference-list.ts
index ba8e5d3..c59e06a 100644
--- a/src/forms/fields/deep-reverse-single-reference-list.ts
+++ b/src/forms/fields/deep-reverse-single-reference-list.ts
@@ -1,136 +1,130 @@
+/* eslint @typescript-eslint/no-explicit-any: off */
import { Context } from "koa";
import { CollectionItem, FieldTypes as SealiousFieldTypes } from "sealious";
import { FormDataValue, FormData } from "../form-types.js";
import { CheckboxedListField } from "./checkboxed-list.js";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
import { wrapKeyName } from "../../utils/wrap-attributes.js";
export class DeepReverseSingleReferenceList extends CheckboxedListField<
false,
string
> {
public item_label_getter: (item: CollectionItem<any>) => string = (item) =>
item.get("name") as string;
constructor(
public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
) {
super(false, async (ctx: Context) => {
const { items } = await ctx.$app.collections[
sealious_field.target_collection
]
.list(ctx.$context)
.fetch();
return items.map((s) => ({
label: this.item_label_getter(s),
value: s.id,
}));
});
}
setItemLabelGetter(getter: (item: CollectionItem<any>) => string) {
this.item_label_getter = getter;
}
getSealiousCreateValue(): never {
throw new Error(
"This field is not set directly through field value, but instead relies on postSealiousCreate and postSealiousEdit"
);
}
async postSealiousCreate(
ctx: Context,
created_item: CollectionItem<any>,
form_data: FormData
) {
// First, we remove links refering to current item
const { items: existing_links } = await ctx.$app.collections[
this.sealious_field.intermediary_collection
]
.list(ctx.$context)
.filter({
[this.sealious_field.referencing_field]: created_item.id,
})
.fetch();
const { parsed: value } = await this.getParsedValue(
ctx,
form_data.raw_values,
false
);
const should_exist_ids = Object.entries(value || {})
.filter(([, value]) => value === "on")
.map(([key]) => key);
const to_delete = existing_links.filter(
(link) =>
!should_exist_ids.includes(
link.get(
this.sealious_field.intermediary_field_that_points_there
) as string
)
);
const to_create_ids = should_exist_ids.filter(
(id) =>
!existing_links
.map((link) =>
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
link.get(
this.sealious_field
.intermediary_field_that_points_there
)
)
.includes(id)
);
await Promise.all(
to_delete.map((item) => {
return item.remove(ctx.$context);
})
);
// Then, we iterate over all selected values and insert appropriate missing links
const promises = to_create_ids.map(async (id) => {
await this.sealious_field
.getReferencingCollection()
.create(ctx.$context, {
[this.sealious_field.referencing_field]: created_item.id,
[this.sealious_field.intermediary_field_that_points_there]:
id,
});
});
await Promise.all(promises);
}
async postSealiousEdit(
ctx: Context,
edited_item: CollectionItem<any>,
value: FormData
) {
return this.postSealiousCreate(ctx, edited_item, value);
}
async sealiousValueToForm(
_ctx: Context,
value: string[] | null
): Promise<FormDataValue> {
return Object.fromEntries((value || []).map((id) => [id, "on"]));
}
generateFieldDeclaration(
_field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
}
- generateCreateValueGetter(
- field_info: ExtractedFieldInfo,
- vars: {
- form_field_types: string;
- sealious_field: string;
- form_fields: string;
- }
- ): string {
+ generateCreateValueGetter(field_info: ExtractedFieldInfo): string {
return `${wrapKeyName(
field_info.name
)}: undefined /* handled below in postSealiousCreate */`;
}
}
diff --git a/src/forms/fields/deep-reverse-single-reference-table.ts b/src/forms/fields/deep-reverse-single-reference-table.ts
index e509182..bf678a2 100644
--- a/src/forms/fields/deep-reverse-single-reference-table.ts
+++ b/src/forms/fields/deep-reverse-single-reference-table.ts
@@ -1,213 +1,213 @@
-/* eslint-disable @typescript-eslint/no-unsafe-assignment */
+/* eslint @typescript-eslint/no-explicit-any: off */
import {
FieldTypes as SealiousFieldTypes,
Field as SealiousField,
CollectionItem,
} from "sealious";
import { Boolean, TextBasedSimpleField } from "./fields.js";
import { sealiousToFormField } from "./get-field-for-sealious.js";
import { Table } from "./table.js";
import { Table as TableControl } from "../controls/table.js";
import { Context } from "koa";
import { FormDataValue, FormData } from "../form-types.js";
import { FormControlContext } from "../controls/form-control.js";
import { HiddenInput } from "../controls/hidden-input.js";
import { FormField } from "./field.js";
function getReferencingFields(
sealious_field: SealiousFieldTypes.DeepReverseSingleReference
): Record<string, SealiousField<unknown>> {
const referencing_collection =
sealious_field.collection.app.collections[
sealious_field.referencing_collection
];
if (!referencing_collection) {
throw new Error(
"Unknown collection: " + sealious_field.referencing_collection
);
}
return referencing_collection.fields;
}
export class DeepReverseSingleReferenceTable extends Table<
Record<string, FormField>
> {
constructor(
public sealious_field: SealiousFieldTypes.DeepReverseSingleReference
) {
super({
selected: new Boolean(false),
[sealious_field.referencing_field]: new TextBasedSimpleField(true),
[sealious_field.intermediary_field_that_points_there]:
new TextBasedSimpleField(true),
...Object.fromEntries(
Object.values(getReferencingFields(sealious_field))
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [field.name, sealiousToFormField(field)])
),
});
}
getControl(): TableControl<any> {
return new TableControl(this, {
label: this.name,
allow_adding: false,
subfield_controls: {
selected: this.columns.selected.getControl(),
[this.sealious_field.referencing_field]: new HiddenInput(
this.columns[this.sealious_field.referencing_field]
),
[this.sealious_field.intermediary_field_that_points_there]:
new HiddenInput(
this.columns[
this.sealious_field.intermediary_field_that_points_there
]
),
...Object.fromEntries(
Object.values(getReferencingFields(this.sealious_field))
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [
field.name,
this.columns[field.name].getControl(),
])
),
},
});
}
getSealiousCreateValue(_fctx: FormControlContext): Promise<unknown> {
throw new Error("Method not implemented.");
}
async postSealiousCreate(
ctx: Context,
created_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {
// First, we remove links refering to current item
const { items: to_delete } = await ctx.$app.collections[
"${toKebabCase(referencing_collection)}"
]
.list(ctx.$context)
.filter({ "${referencing_field}": created_item.id })
.fetch();
await Promise.all(to_delete.map((item) => item.remove(ctx.$context)));
// Then, we iterate over all selected values and insert appropriate entries for the subcategories relation
const referencing_fields = getReferencingFields(this.sealious_field);
const { parsed: value } = await this.getParsedValue(
ctx,
form_data.raw_values,
false
);
const promises = (value || [])
.filter((s) => s.selected == true)
.map(async (link_info) => {
await ctx.$app.collections[
"${toKebabCase(referencing_collection)}"
].create(ctx.$context, {
"${referencing_field}": created_item.id,
"${intermediary_field_that_points_there}": String(
link_info["${intermediary_field_that_points_there}"]
),
...Object.fromEntries(
Object.values(referencing_fields)
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [field.name, link_info[field.name]])
),
});
});
await Promise.all(promises);
}
postSealiousEdit(
ctx: Context,
edited_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {
return this.postSealiousCreate(ctx, edited_item, form_data);
}
async sealiousValueToForm(
ctx: Context,
_value: string[],
item: CollectionItem<any>
): Promise<FormDataValue> {
// convert from an array to array-like object
const referencing_fields = getReferencingFields(this.sealious_field);
return Object.fromEntries(
await Promise.all([
this.sealious_field.collection.list(ctx.$context).fetch(),
this.sealious_field
.getReferencingCollection()
.list(ctx.$context)
.fetch(),
]).then(([{ items: targets }, { items: links }]) =>
targets
.map((target) => {
return {
selected: (
(item.get(
this.sealious_field.name
) as string[]) || []
).includes(target.id)
? "on"
: "off",
[this.sealious_field.referencing_field]: item.id,
[this.sealious_field
.intermediary_field_that_points_there]:
target.id,
...Object.fromEntries(
Object.values(referencing_fields)
.filter(
(field) =>
!(
field instanceof
SealiousFieldTypes.SingleReference
)
)
.map((field) => [
field.name,
links
.find(
(e) =>
e.get(
this.sealious_field
.intermediary_field_that_points_there
) == target.id &&
e.get(
this.sealious_field
.referencing_field
) == item.id
)
?.get("rank") || 0,
])
),
};
})
.entries()
)
) as FormDataValue;
}
}
diff --git a/src/forms/fields/email.ts b/src/forms/fields/email.ts
index 865463d..991d5b6 100644
--- a/src/forms/fields/email.ts
+++ b/src/forms/fields/email.ts
@@ -1,29 +1,29 @@
import { predicates } from "@sealcode/ts-predicates";
import { RegExpField } from "./regexp.js";
import { SimpleInput } from "../controls/controls.js";
export class EmailField<
- Required extends boolean
+ Required extends boolean,
> extends RegExpField<Required> {
predicate = predicates.string;
constructor(
required: Required,
public error_message = "Please enter a proper email address",
public default_value = ""
) {
super(
required,
/^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
error_message,
default_value
);
}
setErrorMessage(message: string) {
this.error_message = message;
}
public getControl(): SimpleInput {
return new SimpleInput(this, { label: this.name, type: "email" });
}
}
diff --git a/src/forms/fields/enum-multiple-sealious.ts b/src/forms/fields/enum-multiple-sealious.ts
index acf0549..3b556df 100644
--- a/src/forms/fields/enum-multiple-sealious.ts
+++ b/src/forms/fields/enum-multiple-sealious.ts
@@ -1,48 +1,48 @@
import { FieldTypes as SealiousFieldTypes } from "sealious";
import { Context } from "koa";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
import { CheckboxedListField } from "./checkboxed-list.js";
import { FormControlContext } from "../controls/form-control.js";
import { FormDataValue } from "../form-types.js";
export class EnumMultipleSealious<
- Values extends string
+ Values extends string,
> extends CheckboxedListField<boolean, Values> {
public sealious_field: SealiousFieldTypes.EnumMultiple<Values>;
constructor(sealious_field: SealiousFieldTypes.EnumMultiple<Values>) {
super(sealious_field.required, async (ctx: Context) =>
(await sealious_field.getAllowedValues(ctx.$context)).map(
(value: Values) => ({ value, label: value })
)
);
this.sealious_field = sealious_field;
}
generateFieldDeclaration(
field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
}
async getSealiousCreateValue(fctx: FormControlContext): Promise<Values[]> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
const result = Object.entries(parsed || {})
.filter(([, value]) => value == "on")
.map(([key]) => key as Values);
return result;
}
async sealiousValueToForm(
ctx: Context,
sealious_value: Values[] | null
): Promise<FormDataValue> {
return Object.fromEntries(
(sealious_value || []).map((key) => [key, "on"])
);
}
}
diff --git a/src/forms/fields/existing-sealious-value.ts b/src/forms/fields/existing-sealious-value.ts
index 8778aea..5281e90 100644
--- a/src/forms/fields/existing-sealious-value.ts
+++ b/src/forms/fields/existing-sealious-value.ts
@@ -1,23 +1,23 @@
import { Field } from "sealious";
import { PickFromListField } from "./pick-from-list.js";
export class ExistingSealiousValue<
- Required extends boolean
+ Required extends boolean,
> extends PickFromListField<Required> {
constructor(required: Required, field: Field<unknown>) {
super(required, async (ctx) => {
const { items } = await field.collection.list(ctx.$context).fetch();
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return Object.fromEntries(
items.map((item) => {
const value = item.get(field.name) as unknown;
return [value, value];
})
);
});
}
getEmptyValue() {
return "";
}
}
diff --git a/src/forms/fields/field.test.ts b/src/forms/fields/field.test.ts
index bdc0643..80b2f0a 100644
--- a/src/forms/fields/field.test.ts
+++ b/src/forms/fields/field.test.ts
@@ -1,165 +1,165 @@
import Router from "@koa/router";
import getPort from "get-port";
import { Browser, Page } from "playwright";
import type { Context } from "koa";
import Koa from "koa";
import { mount } from "../../mount.js";
import { Form } from "../form.js";
import { getBrowser } from "../../utils/browser-creator.js";
import assert from "assert";
import { TextBasedSimpleField } from "./simple-form-field.js";
import { SimpleInput } from "../controls/simple-input.js";
import { FormData } from "../form-types.js";
import { Boolean } from "./boolean.js";
import { Checkbox } from "../controls/checkbox.js";
describe("basic field", () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
let browser: Browser;
let page: Page;
afterEach(() => {
server.close();
});
it("sends the values", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
const fields = {
text: new TextBasedSimpleField(true),
};
let received_values: unknown;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new SimpleInput(fields.text)];
async onSubmit(ctx: Context, data: FormData) {
received_values = await this.getParsedValues(ctx);
const { parsed: email } = await this.fields.text.getParsedValue(
ctx,
data.raw_values
);
email?.padStart(2, "0"); // if the typechecks are ok, this will not throw
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
});
it("Doesn't call `isValueValid` and `parse` if the value is empty", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
let is_value_valid_called = false;
let parse_called = false;
const fields = {
text: new (class MockField extends TextBasedSimpleField<false> {
public async isValueValid() {
is_value_valid_called = true;
return true as any;
}
public async parse() {
parse_called = true;
return true as any;
}
})(false),
};
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new SimpleInput(fields.text)];
async onSubmit() {
//noop
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
assert(is_value_valid_called == false);
assert(parse_called == false);
});
it("Accepts a form where non-required values are empty", async () => {
const port = await getPort();
- console.log(`Using port ${port} form checkboxed-list-input.test.ts`);
+ console.info(`Using port ${port} form checkboxed-list-input.test.ts`);
const app = new Koa();
const router = new Router();
let submit_called = false;
const fields = {
text: new TextBasedSimpleField(false),
checkbox: new Boolean(false),
};
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new SimpleInput(fields.text), new Checkbox(fields.checkbox)];
async onSubmit() {
submit_called = true;
//noop
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByRole("button", { name: "Wyślij" }).click();
assert(submit_called, "onSubmit() triggered");
await page.getByText("Done").click();
});
});
});
diff --git a/src/forms/fields/field.ts b/src/forms/fields/field.ts
index 8bd380e..e1c0197 100644
--- a/src/forms/fields/field.ts
+++ b/src/forms/fields/field.ts
@@ -1,268 +1,269 @@
-/* eslint-disable @typescript-eslint/no-empty-function */
+/* eslint @typescript-eslint/no-unused-vars: off, @typescript-eslint/no-explicit-any: off */
import { Predicate, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { Collection, CollectionItem } from "sealious";
import { t } from "../../utils/translate.js";
import { FormControl, FormControlContext } from "../controls/form-control.js";
import { FormDataValue, FormData } from "../form-types.js";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
import { wrapAttribute, wrapKeyName } from "../../utils/wrap-attributes.js";
export type FormFieldValidationResponse = { valid: boolean; message: string };
export type FormDisplayInfo<C extends Collection> = {
field: keyof C["fields"];
label: string;
format?: (value: unknown, item: CollectionItem<C>) => JSX.Element;
};
export type FormFieldValidationFn<ValueType> = (
ctx: Context,
value: ValueType,
field: FormField<boolean, ValueType>
) => Promise<FormFieldValidationResponse>;
export type FieldParsedValue<T> = T extends FormField<infer R> ? R : never;
-export type GetPredicate<F extends FormField> = F extends FormField<true>
- ? F["predicate"]
- : F["predicate"] | typeof predicates.undefined;
+export type GetPredicate<F extends FormField> =
+ F extends FormField<true>
+ ? F["predicate"]
+ : F["predicate"] | typeof predicates.undefined;
// for quickly testing GetPredicate conditonally applying the undefined predicate:
// const f = new SimpleFormField(true);
// type p = GetPredicate<typeof f>;
// const f2 = new SimpleFormField(false);
// type p2 = GetPredicate<typeof f2>;
export type FieldsToShape<T extends Record<string, FormField>> = {
[property in keyof T]: GetPredicate<T[property]>;
};
export function fieldsToShape<Fields extends Record<string, FormField>>(
obj: Fields
): FieldsToShape<Fields> {
return Object.fromEntries(
Object.entries(obj).map(([key, value]) => [key, value.predicate])
) as FieldsToShape<Fields>;
}
export type FieldParseResult<T> =
| {
parsable: true;
error: null;
parsed_value: T;
}
| {
parsable: false;
error: string;
parsed_value: null;
};
export abstract class FormField<
Required extends boolean = boolean,
ParsedValue = unknown,
DefaultFormControl extends FormControl = FormControl,
- SealiousValue = any
+ SealiousValue = any,
> {
name: string;
constructor(public readonly required: Required) {}
predicate: Predicate = predicates.unknown;
mapToFilter: (parsed: ParsedValue) => unknown = (value) => value;
async init(): Promise<void> {}
setName(name: string): this {
this.name = name;
return this;
}
public async _validate(
ctx: Context,
value: ParsedValue
): Promise<FormFieldValidationResponse> {
if (value === "" || value === null || value === undefined) {
if (this.required) {
return {
valid: false,
message: t(
ctx,
"field_is_required",
[],
"This field is required"
),
};
} else {
return {
valid: true,
message: "",
};
}
}
return this.isValueValid(ctx, value);
}
public abstract getEmptyValue(): ParsedValue;
public async isValueValid(
_ctx: Context,
_value: ParsedValue
): Promise<FormFieldValidationResponse> {
return { valid: true, message: "" };
}
abstract parse(
ctx: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<ParsedValue>>;
async getParsedValue(
ctx: Context,
all_form_values: Record<string, FormDataValue>,
validate: true
): Promise<{
valid: boolean;
message: string;
parsed: ParsedValue | null;
raw: FormDataValue;
}>;
async getParsedValue(
ctx: Context,
all_form_values: Record<string, FormDataValue>,
validate?: false
): Promise<{
message: string;
parsed: ParsedValue | null;
raw: FormDataValue;
}>;
async getParsedValue(
ctx: Context,
all_form_values: Record<string, FormDataValue>,
validate = false
): Promise<{
valid?: boolean;
message: string;
parsed: ParsedValue | null;
raw: FormDataValue;
}> {
const raw = all_form_values[this.name];
if (raw == undefined || raw == null || raw == "") {
return {
parsed: null,
message: this.required
? "empty value, but field is required"
: "",
raw,
...(validate ? { valid: !this.required } : {}),
};
}
const {
parsable,
parsed_value,
error: parse_error,
} = await this.parse(ctx, raw);
if (!parsable) {
return {
...(validate ? { valid: false } : {}),
parsed: this.getEmptyValue(),
raw,
message: parse_error || "Error",
};
}
if (validate) {
const { valid, message } = await this._validate(ctx, parsed_value);
return {
parsed: parsed_value,
...(validate ? { valid } : {}),
message,
raw: all_form_values[this.name],
};
} else {
return { parsed: parsed_value, raw, message: "parsed" };
}
}
setMapToFilter(fn: (parsed: ParsedValue) => unknown) {
this.mapToFilter = fn;
return this;
}
//return undefined here to delete a value
async getDatabaseValue(
ctx: Context,
data: Record<string, FormDataValue>
): Promise<unknown> {
const { parsed } = await this.getParsedValue(ctx, data);
return parsed;
}
abstract getControl(): DefaultFormControl;
getSealiousCreateValue(fctx: FormControlContext): Promise<SealiousValue> {
throw new Error("This field does not have a default sealious mapping");
}
sealiousValueToForm(
ctx: Context,
sealiousValue: SealiousValue | null,
item: CollectionItem<any>
): Promise<FormDataValue> {
throw new Error("This field does not have a default sealious mapping");
}
async postSealiousCreate(
ctx: Context,
created_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {}
async postSealiousEdit(
ctx: Context,
edited_item: CollectionItem<any>,
form_data: FormData
): Promise<void> {}
generateFieldDeclaration(
field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${String(
field_info.is_required
)})`;
}
generateCreateValueGetter(
field_info: ExtractedFieldInfo,
vars: {
form_field_types: string;
sealious_field: string;
form_fields: string;
}
): string {
return `${wrapKeyName(field_info.name)}: await ${
vars.form_fields
}${wrapAttribute(field_info.name)}.getSealiousCreateValue(fctx)`;
}
generateInitialValue(
field_info: ExtractedFieldInfo,
vars: {
form_field_types: string;
form_fields: string;
}
): string {
return `${wrapKeyName(field_info.name)}: await ${
vars.form_fields
}${wrapAttribute(field_info.name)}.sealiousValueToForm(ctx, item.get("${
field_info.name
}"))`;
}
generateImportsForFieldList(field_info: ExtractedFieldInfo): {
what: string;
from: string;
as?: string;
}[] {
return [];
}
}
diff --git a/src/forms/fields/file.test.ts b/src/forms/fields/file.test.ts
index cee917e..b039d97 100644
--- a/src/forms/fields/file.test.ts
+++ b/src/forms/fields/file.test.ts
@@ -1,75 +1,75 @@
import Router from "@koa/router";
import { Context } from "koa";
import { FilePointer } from "@sealcode/file-manager";
import getPort from "get-port";
import Koa from "koa";
import fs from "node:fs/promises";
import { mount } from "../../mount.js";
import { Image } from "../controls/image.js";
import { Form } from "../form.js";
import { File as FileField } from "./file.js";
import { getBrowser } from "../../utils/browser-creator.js";
import assert from "node:assert";
import { Browser, Page } from "playwright";
import { module_dirname } from "../../utils/module-dirname.js";
import _locreq from "locreq";
const locreq = _locreq(module_dirname(import.meta.url));
describe("file field", () => {
let server: ReturnType<Koa["listen"]>;
let browser: Browser;
let page: Page;
afterEach(() => {
server.close();
});
it("should handle as imple upload scenario", async () => {
const port = await getPort();
- console.log(`Using port http://localhost:${port} form file field test`);
+ console.info(`Using port http://localhost:${port} form file field test`);
const app = new Koa();
const router = new Router();
const fields = {
file: new FileField(true),
};
let received_values: any;
mount(
router,
"/",
new (class extends Form<typeof fields, unknown> {
fields = fields;
controls = [new Image(fields.file)];
async onSubmit(ctx: Context) {
received_values = await this.getParsedValues(ctx);
}
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
// await sleep(999999999);
await page.goto(`http://localhost:${port}`);
// await page.getByPlaceholder("file").click();
await page.getByPlaceholder("file").setInputFiles({
name: "important.png",
mimeType: "image/png",
buffer: await fs.readFile(locreq.resolve("assets/important.png")),
});
await page.getByRole("button", { name: "Wyślij" }).click();
assert.ok(received_values.file.old == null);
assert.ok(received_values.file.new instanceof FilePointer);
}).timeout(999999);
});
diff --git a/src/forms/fields/file.ts b/src/forms/fields/file.ts
index b4c1c41..402398e 100644
--- a/src/forms/fields/file.ts
+++ b/src/forms/fields/file.ts
@@ -1,113 +1,113 @@
import { hasFieldOfType, is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { FilePointer, PathFilePointer } from "@sealcode/file-manager";
import { FormDataValue } from "../form-types.js";
import { FieldParseResult, FormField } from "./field.js";
import { File as FileControl } from "../controls/file.js";
import { FormControl, FormControlContext } from "../controls/form-control.js";
export type FileContainer = {
old: FilePointer | null;
new: FilePointer | null;
};
export class File<Required extends boolean> extends FormField<
Required,
FileContainer,
FormControl
> {
constructor(public readonly required: Required) {
super(required);
}
async parse(
ctx: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<FileContainer>> {
let result;
if (is(raw_value, predicates.string)) {
const file = await ctx.$app.fileManager.fromToken(raw_value);
result = {
parsed_value: { old: file, new: null },
error: null,
parsable: true as const,
};
} else if (!is(raw_value, predicates.object)) {
result = {
parsed_value: null,
error: "Expected a field with old.id:string, old.filename:string and new?:File",
parsable: false as const,
};
} else {
const old_file = hasFieldOfType(
raw_value,
"old",
predicates.instanceOf(PathFilePointer)
)
? await ctx.$app.fileManager.toPointer(
raw_value.old as string | FilePointer
- )
+ )
: null;
const new_file = hasFieldOfType(
raw_value,
"new",
predicates.or(
predicates.array(predicates.instanceOf(PathFilePointer)),
predicates.instanceOf(PathFilePointer)
)
)
? Array.isArray(raw_value.new)
? raw_value.new[0]
: raw_value.new
: null;
result = {
parsable: true as const,
error: null,
parsed_value: { old: old_file, new: new_file },
};
}
return result;
}
async getDatabaseValue(ctx: Context, data: Record<string, FormDataValue>) {
const { parsed } = await this.getParsedValue(ctx, data);
return parsed?.new || undefined;
}
getEmptyValue() {
return { old: null, new: null };
}
- getControl(...args: any[]): FileControl {
+ getControl(): FileControl {
return new FileControl(this, { label: this.name, autocomplete: false });
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<FilePointer | undefined> {
const { parsed: value } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
const pointer = value?.new || value?.old || undefined;
if (this.required && !pointer) {
throw new Error("File is required, but no value is provided");
}
return pointer;
}
async sealiousValueToForm(
ctx: Context,
sealiousValue: FilePointer | string | null
): Promise<{ old: FilePointer | undefined } | Record<string, never>> {
if (!sealiousValue) {
return {};
}
if (typeof sealiousValue == "string") {
sealiousValue = await ctx.$app.fileManager.fromToken(sealiousValue);
}
return {
old: sealiousValue, // FilePointer
};
}
}
diff --git a/src/forms/fields/float.ts b/src/forms/fields/float.ts
index 54ad3b8..fd3eb3a 100644
--- a/src/forms/fields/float.ts
+++ b/src/forms/fields/float.ts
@@ -1,9 +1,9 @@
import { NumberBasedSimpleField } from "./simple-form-field.js";
export class Float<
- Required extends boolean
+ Required extends boolean,
> extends NumberBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "number");
}
}
diff --git a/src/forms/fields/get-field-for-sealious.ts b/src/forms/fields/get-field-for-sealious.ts
index 6cd8926..b5bcf8c 100644
--- a/src/forms/fields/get-field-for-sealious.ts
+++ b/src/forms/fields/get-field-for-sealious.ts
@@ -1,304 +1,337 @@
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import {
Collection,
Field as SealiousField,
FieldTypes as SealiousFieldTypes,
RequiredField as SealiousRequiredField,
} from "sealious";
import { Boolean as BooleanField } from "./boolean.js";
import { SimpleFormField, TextBasedSimpleField } from "./simple-form-field.js";
import { File } from "./file.js";
import { CollectionField } from "./collection-field.js";
import { StructuredArray as StructuredArrayField } from "./structured-array.js";
import { Color } from "./color.js";
import { DateField } from "./date.js";
import { DateTime } from "./datetime.js";
import { EmailField } from "./email.js";
import { Float } from "./float.js";
import { HTML } from "./html.js";
import { Int } from "./int.js";
import { JSONField } from "./json.js";
import { Password } from "./password.js";
import { Text } from "./text.js";
import { Markdown } from "./markdown.js";
import { DeepReverseSingleReferenceTable } from "./deep-reverse-single-reference-table.js";
import { DeepReverseSingleReferenceList } from "./deep-reverse-single-reference-list.js";
import { Coordinates } from "./coordinates.js";
import { SimpleInput } from "../controls/simple-input.js";
import { FormField } from "./field.js";
import { PickFromListSealious } from "./pick-from-list-sealious.js";
import { SingleReference } from "./single-reference.js";
import extract_fields_from_collection, {
ExtractedFieldInfo,
} from "../../utils/extract-fields-from-collection.js";
import { EnumMultipleSealious } from "./enum-multiple-sealious.js";
import { URLField } from "./url.js";
import { Image } from "./image.js";
export type SealiousToFormField<T> = T extends SealiousFieldTypes.Boolean
? BooleanField<false>
: T extends SealiousFieldTypes.Color
- ? Color<false>
- : T extends SealiousFieldTypes.ControlAccess<infer R>
- ? SealiousToFormField<R>
- : T extends SealiousFieldTypes.Date
- ? DateField<false>
- : T extends SealiousFieldTypes.DateTime
- ? DateTime<false>
- : T extends SealiousFieldTypes.DeepReverseSingleReference
- ? DeepReverseSingleReferenceList | DeepReverseSingleReferenceTable
- : T extends SealiousFieldTypes.DisallowUpdate<any, any, any, infer R>
- ? SealiousToFormField<R>
- : T extends SealiousFieldTypes.Email
- ? EmailField<false>
- : T extends SealiousFieldTypes.Enum<any>
- ? PickFromListSealious<false>
- : T extends SealiousFieldTypes.EnumMultiple<infer R>
- ? R extends string[]
- ? EnumMultipleSealious<R>
- : TextBasedSimpleField<false>
- : T extends SealiousFieldTypes.File
- ? File<false>
- : T extends SealiousFieldTypes.Float
- ? Float<false>
- : T extends SealiousFieldTypes.HTML
- ? HTML<false>
- : T extends SealiousFieldTypes.Image
- ? Image<false>
- : T extends SealiousFieldTypes.Int
- ? Int<false>
- : T extends SealiousFieldTypes.JsonObject
- ? JSONField<false>
- : T extends SealiousFieldTypes.JDD
- ? TextBasedSimpleField<false, SimpleInput>
- : T extends SealiousFieldTypes.Password
- ? Password<false>
- : T extends SealiousFieldTypes.ReverseSingleReference
- ? TextBasedSimpleField<false, SimpleInput>
- : T extends SealiousFieldTypes.SecretToken
- ? TextBasedSimpleField<false, SimpleInput>
- : T extends SealiousFieldTypes.SettableBy<infer R>
- ? SealiousToFormField<R>
- : T extends SealiousFieldTypes.SingleReference
- ? SingleReference<Collection, boolean, T>
- : T extends SealiousFieldTypes.Text
- ? Text<false>
- : T extends SealiousFieldTypes.Username
- ? CollectionField<SealiousFieldTypes.Username, false>
- : T extends SealiousFieldTypes.ValueExistingInCollection
- ? SimpleFormField<false>
- : T extends SealiousFieldTypes.ValueNotExistingInCollection
- ? SimpleFormField<false>
- : T extends SealiousRequiredField<any, any, any>
- ? SimpleFormField<false>
- : T extends SealiousFieldTypes.Url
- ? URLField<false>
- : T extends SealiousFieldTypes.Money
- ? SimpleFormField<false>
- : T extends SealiousFieldTypes.Markdown
- ? Markdown<false>
- : T extends SealiousFieldTypes.Coordinates
- ? Coordinates<false>
- : T extends SealiousFieldTypes.StructuredArray<infer R>
- ? StructuredArrayField<R>
- : TextBasedSimpleField<any>;
+ ? Color<false>
+ : T extends SealiousFieldTypes.ControlAccess<infer R>
+ ? SealiousToFormField<R>
+ : T extends SealiousFieldTypes.Date
+ ? DateField<false>
+ : T extends SealiousFieldTypes.DateTime
+ ? DateTime<false>
+ : T extends SealiousFieldTypes.DeepReverseSingleReference
+ ?
+ | DeepReverseSingleReferenceList
+ | DeepReverseSingleReferenceTable
+ : T extends SealiousFieldTypes.DisallowUpdate<
+ any,
+ any,
+ any,
+ infer R
+ >
+ ? SealiousToFormField<R>
+ : T extends SealiousFieldTypes.Email
+ ? EmailField<false>
+ : T extends SealiousFieldTypes.Enum<any>
+ ? PickFromListSealious<false>
+ : T extends SealiousFieldTypes.EnumMultiple<
+ infer R
+ >
+ ? R extends string[]
+ ? EnumMultipleSealious<R>
+ : TextBasedSimpleField<false>
+ : T extends SealiousFieldTypes.File
+ ? File<false>
+ : T extends SealiousFieldTypes.Float
+ ? Float<false>
+ : T extends SealiousFieldTypes.HTML
+ ? HTML<false>
+ : T extends SealiousFieldTypes.Image
+ ? Image<false>
+ : T extends SealiousFieldTypes.Int
+ ? Int<false>
+ : T extends SealiousFieldTypes.JsonObject
+ ? JSONField<false>
+ : T extends SealiousFieldTypes.JDD
+ ? TextBasedSimpleField<
+ false,
+ SimpleInput
+ >
+ : T extends SealiousFieldTypes.Password
+ ? Password<false>
+ : T extends SealiousFieldTypes.ReverseSingleReference
+ ? TextBasedSimpleField<
+ false,
+ SimpleInput
+ >
+ : T extends SealiousFieldTypes.SecretToken
+ ? TextBasedSimpleField<
+ false,
+ SimpleInput
+ >
+ : T extends SealiousFieldTypes.SettableBy<
+ infer R
+ >
+ ? SealiousToFormField<R>
+ : T extends SealiousFieldTypes.SingleReference
+ ? SingleReference<
+ Collection,
+ boolean,
+ T
+ >
+ : T extends SealiousFieldTypes.Text
+ ? Text<false>
+ : T extends SealiousFieldTypes.Username
+ ? CollectionField<
+ SealiousFieldTypes.Username,
+ false
+ >
+ : T extends SealiousFieldTypes.ValueExistingInCollection
+ ? SimpleFormField<false>
+ : T extends SealiousFieldTypes.ValueNotExistingInCollection
+ ? SimpleFormField<false>
+ : T extends SealiousRequiredField<
+ any,
+ any,
+ any
+ >
+ ? SimpleFormField<false>
+ : T extends SealiousFieldTypes.Url
+ ? URLField<false>
+ : T extends SealiousFieldTypes.Money
+ ? SimpleFormField<false>
+ : T extends SealiousFieldTypes.Markdown
+ ? Markdown<false>
+ : T extends SealiousFieldTypes.Coordinates
+ ? Coordinates<false>
+ : T extends SealiousFieldTypes.StructuredArray<
+ infer R
+ >
+ ? StructuredArrayField<R>
+ : TextBasedSimpleField<any>;
export function sealiousToFormField<SF extends SealiousField<any>>(
sealious_field: SF
): SealiousToFormField<SF> {
if (sealious_field instanceof SealiousFieldTypes.Boolean) {
return new BooleanField(
sealious_field.required
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Color) {
return new Color(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.ControlAccess) {
const target_field = sealious_field.virtual_field;
return sealiousToFormField(target_field) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Date) {
return new DateField(
sealious_field.required
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.DateTime) {
return new DateTime(sealious_field.required) as SealiousToFormField<SF>;
}
if (
sealious_field instanceof SealiousFieldTypes.DeepReverseSingleReference
) {
const referencing_collection =
sealious_field.collection.app.collections[
sealious_field.referencing_collection
];
if (!referencing_collection) {
throw new Error(
"Unknown collection: " + sealious_field.referencing_collection
);
}
if (Object.keys(referencing_collection.fields).length == 2) {
return new DeepReverseSingleReferenceList(
sealious_field
) as SealiousToFormField<SF>;
} else {
return new DeepReverseSingleReferenceTable(
sealious_field
) as SealiousToFormField<SF>;
}
}
if (sealious_field instanceof SealiousFieldTypes.DisallowUpdate) {
return sealiousToFormField(
sealious_field.virtual_field
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Email) {
return new EmailField(
sealious_field.required
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Enum) {
return new PickFromListSealious(
sealious_field
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.EnumMultiple) {
return new EnumMultipleSealious(
sealious_field
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.File) {
return new File(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Float) {
return new Float(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.HTML) {
return new HTML(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Image) {
return new Image(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Int) {
return new Int(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.JsonObject) {
return new JSONField(
sealious_field.required
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Password) {
return new Password(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.SettableBy) {
return sealiousToFormField(
sealious_field.virtual_field
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.SingleReference) {
return new SingleReference(
false,
sealious_field
) as unknown as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Text) {
return new Text(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Username) {
return new Text(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Url) {
return new URLField(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Money) {
return new Float(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Markdown) {
return new Markdown(sealious_field.required) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.Coordinates) {
return new Coordinates(
sealious_field.required
) as SealiousToFormField<SF>;
}
if (sealious_field instanceof SealiousFieldTypes.StructuredArray) {
return new StructuredArrayField(
sealious_field
) as SealiousToFormField<SF>;
}
return new TextBasedSimpleField(false) as SealiousToFormField<SF>;
}
export async function sealiousFieldInfoToFormField(
field_info: ExtractedFieldInfo
): Promise<FormField> {
switch (field_info.type) {
case "boolean":
return new BooleanField(field_info.is_required);
case "color":
return new Color(field_info.is_required);
case "date":
return new DateField(field_info.is_required);
case "datetime":
return new DateTime(field_info.is_required);
case "deep-reverse-single-reference": {
const referencing_fields = await extract_fields_from_collection(
field_info.referencing_collection as string
);
if (referencing_fields.length == 2) {
return new DeepReverseSingleReferenceList({} as any);
} else {
return new DeepReverseSingleReferenceTable({} as any);
}
}
case "email":
return new EmailField(field_info.is_required);
case "enum":
return new PickFromListSealious({} as any);
case "enum-multiple":
return new EnumMultipleSealious({} as any);
case "file":
return new File(field_info.is_required);
case "float":
return new Float(field_info.is_required);
case "html":
return new HTML(field_info.is_required);
case "image":
return new Image(field_info.is_required);
case "int":
return new Int(field_info.is_required);
case "json-object":
return new JSONField(field_info.is_required);
case "password":
return new Password(field_info.is_required);
case "single-reference":
return new SingleReference(false, {} as any);
case "text":
return new Text(field_info.is_required);
case "username":
return new Text(field_info.is_required);
case "url":
return new URLField(field_info.is_required);
case "money":
return new Float(field_info.is_required);
case "markdown":
return new Markdown(field_info.is_required);
case "coordinates":
return new Coordinates(field_info.is_required);
case "structured-array":
// we don't need the full thing at this point, so we don't fill in the subfields
return new StructuredArrayField(
new SealiousFieldTypes.StructuredArray({})
);
default:
return new TextBasedSimpleField(false);
}
}
diff --git a/src/forms/fields/int.ts b/src/forms/fields/int.ts
index 1be0571..eb42d1f 100644
--- a/src/forms/fields/int.ts
+++ b/src/forms/fields/int.ts
@@ -1,25 +1,25 @@
import { FormControlContext } from "../controls/form-control.js";
import { NumberBasedSimpleField } from "./simple-form-field.js";
export class Int<
- Required extends boolean
+ Required extends boolean,
> extends NumberBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "number");
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<number | undefined> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
if (parsed == null) {
return undefined;
}
if (isNaN(parsed)) {
return undefined;
} else return parsed;
}
}
diff --git a/src/forms/fields/number.ts b/src/forms/fields/number.ts
index 2506bbb..8abbe5a 100644
--- a/src/forms/fields/number.ts
+++ b/src/forms/fields/number.ts
@@ -1,77 +1,77 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { SimpleInput } from "../controls/simple-input.js";
import { FormDataValue } from "../form-types.js";
import { FieldParseResult, FormField } from "./field.js";
export class NumberField<
DefaultValue extends number | null = number,
- Required extends boolean = boolean
+ Required extends boolean = boolean,
> extends FormField<Required, number | DefaultValue, SimpleInput> {
constructor(
required: Required,
public default_value: DefaultValue,
public options: Partial<{
max: number;
min: number;
decimalDigits: number;
}> = {}
) {
super(required);
}
predicate = predicates.number;
public async isValueValid(_: Context, value: unknown) {
if (
(is(value, predicates.string) &&
!isNaN(parseFloat(value)) &&
parseFloat(value).toString() == value.trim()) ||
is(value, predicates.number) ||
((is(value, predicates.undefined) || value == "") && !this.required)
) {
return { valid: true, message: "" };
}
return { valid: false, message: "Proszę wprowadzić liczbę" };
}
async parse(
_: Context,
value: FormDataValue
): Promise<FieldParseResult<number>> {
if (
(is(value, predicates.string) &&
!isNaN(parseFloat(value)) &&
parseFloat(value).toString() == value.trim()) ||
is(value, predicates.number)
) {
return {
parsable: true,
parsed_value: this.options.decimalDigits
? parseFloat(
parseFloat(value.toString()).toFixed(
this.options.decimalDigits
)
- )
+ )
: parseFloat(value.toString()),
error: null,
};
} else {
return {
parsable: false,
parsed_value: null,
error: "Please enter a number",
};
}
}
public getEmptyValue(): DefaultValue {
return this.default_value;
}
getControl(): SimpleInput {
return new SimpleInput(this as FormField<boolean, number>, {
type: "number",
});
}
}
diff --git a/src/forms/fields/password.ts b/src/forms/fields/password.ts
index 7bbef36..dfb3df0 100644
--- a/src/forms/fields/password.ts
+++ b/src/forms/fields/password.ts
@@ -1,17 +1,13 @@
-import { Context } from "koa";
import { TextBasedSimpleField } from "./simple-form-field.js";
export class Password<
- Required extends boolean
+ Required extends boolean,
> extends TextBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "password");
}
- async sealiousValueToForm(
- ctx: Context,
- value: unknown
- ): Promise<undefined> {
+ async sealiousValueToForm(): Promise<undefined> {
return undefined;
}
}
diff --git a/src/forms/fields/pick-from-list-sealious.ts b/src/forms/fields/pick-from-list-sealious.ts
index 43a16a2..b97968a 100644
--- a/src/forms/fields/pick-from-list-sealious.ts
+++ b/src/forms/fields/pick-from-list-sealious.ts
@@ -1,22 +1,22 @@
import { FieldTypes as SealiousFieldTypes } from "sealious";
import { PickFromListField } from "./pick-from-list.js";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
export class PickFromListSealious<
- Required extends boolean
+ Required extends boolean,
> extends PickFromListField<Required> {
constructor(public sealious_field: SealiousFieldTypes.Enum<string>) {
super(sealious_field.required as Required, async (ctx) =>
sealious_field
.getAllowedValues(ctx.$app)
.map((value) => ({ value, label: value }))
);
}
generateFieldDeclaration(
field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
}
}
diff --git a/src/forms/fields/pick-from-list.ts b/src/forms/fields/pick-from-list.ts
index c786f58..03d9ec8 100644
--- a/src/forms/fields/pick-from-list.ts
+++ b/src/forms/fields/pick-from-list.ts
@@ -1,56 +1,56 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { Dropdown, DropdownOption } from "../controls/dropdown.js";
import { FormFieldValidationResponse } from "./field.js";
import { TextBasedSimpleField } from "./simple-form-field.js";
export class PickFromListField<
- Required extends boolean
+ Required extends boolean,
> extends TextBasedSimpleField<Required, Dropdown> {
constructor(
public required: Required,
public generateOptions: (ctx: Context) => Promise<DropdownOption[]>,
public customValidation: (
ctx: Context,
value: unknown,
instance: PickFromListField<Required>
) => Promise<FormFieldValidationResponse> = (ctx, value, instance) =>
instance.valueInList(ctx, value)
) {
super(required);
}
predicate = predicates.string;
public isValueValid(
ctx: Context,
value: string
): Promise<FormFieldValidationResponse> {
return this.customValidation(ctx, value, this);
}
async valueInList(
ctx: Context,
value: unknown
): Promise<FormFieldValidationResponse> {
const options = await this.generateOptions(ctx);
if (!is(value, predicates.string)) {
return { valid: false, message: "not a string" };
}
if (this.required && !options.map((o) => o.value).includes(value)) {
return {
valid: false,
message: `"${value}" is not one of the options`,
};
}
return { valid: true, message: "" };
}
public getEmptyValue(): string {
return "";
}
getControl(): Dropdown {
return new Dropdown(this);
}
}
diff --git a/src/forms/fields/proxy-field.ts b/src/forms/fields/proxy-field.ts
index 48845ad..d0705e6 100644
--- a/src/forms/fields/proxy-field.ts
+++ b/src/forms/fields/proxy-field.ts
@@ -1,29 +1,30 @@
import { FormControl } from "../controls/form-control.js";
import { FormField } from "./field.js";
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
export class ProxyFormField<T> extends FormField<boolean, T, any> {
constructor(
required: boolean,
public name: string,
public empty_value: T,
public parsed_value: T
) {
super(required);
}
getEmptyValue() {
return this.empty_value;
}
async parse() {
return <const>{
parsable: true,
error: null,
parsed_value: this.parsed_value,
};
}
getControl(): FormControl {
throw new Error("This field does not have a default control assigned");
}
}
diff --git a/src/forms/fields/simple-form-field.ts b/src/forms/fields/simple-form-field.ts
index a0eea94..70ff92d 100644
--- a/src/forms/fields/simple-form-field.ts
+++ b/src/forms/fields/simple-form-field.ts
@@ -1,118 +1,126 @@
+/* eslint @typescript-eslint/no-unused-vars: off */
import { FormDataValue } from "../form-types.js";
import { Context } from "koa";
import { predicates } from "@sealcode/ts-predicates";
import { FieldParseResult, FormField } from "./field.js";
import { SimpleInput } from "../controls/simple-input.js";
import { FormControl } from "../controls/controls.js";
import { CollectionItem } from "sealious";
import { FormControlContext } from "../controls/form-control.js";
export abstract class SimpleFormField<
Required extends boolean,
DefaultControl extends FormControl = SimpleInput,
- Parsed = string
+ Parsed = string,
> extends FormField<Required, Parsed, DefaultControl> {
predicate = predicates.string;
- constructor(required: Required, public type: string = "text") {
+ constructor(
+ required: Required,
+ public type: string = "text"
+ ) {
super(required);
}
async sealiousValueToForm(
- ctx: Context,
+ _ctx: Context,
value: unknown
): Promise<FormDataValue> {
if (value === null) {
return "";
}
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
return String(value) as FormDataValue;
}
}
export class TextBasedSimpleField<
Required extends boolean,
- DefaultControl extends FormControl = SimpleInput
+ DefaultControl extends FormControl = SimpleInput,
> extends SimpleFormField<Required, DefaultControl, string | null> {
async parse(
_: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<string>> {
return {
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
parsed_value: (raw_value || "").toString(),
parsable: true,
error: null,
};
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<string | null> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || "";
}
async postSealiousCreate(
ctx: Context,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
created_item: CollectionItem<any>
): Promise<void> {}
async postSealiousEdit(
ctx: Context,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
edited_item: CollectionItem<any>
): Promise<void> {}
getControl(): DefaultControl {
return new SimpleInput(this, {
label: this.name,
type: this.type,
}) as unknown as DefaultControl;
}
public getEmptyValue(): string {
return "";
}
}
export class NumberBasedSimpleField<
Required extends boolean,
- DefaultControl extends FormControl = SimpleInput
+ DefaultControl extends FormControl = SimpleInput,
> extends SimpleFormField<Required, DefaultControl, number> {
async parse(
_: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<number>> {
return {
parsed_value: parseFloat(raw_value as string) || 0,
parsable: true,
error: null,
};
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<number | undefined> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || 0;
}
async postSealiousCreate(): Promise<void> {}
async postSealiousEdit(): Promise<void> {}
getControl(): DefaultControl {
return new SimpleInput(this, {
label: this.name,
type: this.type,
}) as unknown as DefaultControl;
}
public getEmptyValue(): number {
return 0;
}
}
diff --git a/src/forms/fields/single-reference.ts b/src/forms/fields/single-reference.ts
index 0573f7e..52b83ba 100644
--- a/src/forms/fields/single-reference.ts
+++ b/src/forms/fields/single-reference.ts
@@ -1,62 +1,62 @@
import { Collection, FieldTypes as SealiousFieldTypes } from "sealious";
import { CollectionField } from "./collection-field.js";
import { SingleReferenceDropdown } from "../controls/single-reference.js";
import { FormControlContext } from "../controls/form-control.js";
import { Context } from "koa";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
import { toPascalCase } from "js-convert-case";
export class SingleReference<
TargetCollection extends Collection,
Required extends boolean,
- F extends SealiousFieldTypes.SingleReference
+ F extends SealiousFieldTypes.SingleReference,
> extends CollectionField<F, Required> {
getControl(): SingleReferenceDropdown<TargetCollection, F, Required> {
return new SingleReferenceDropdown(this, {
label: this.name,
getLabel: (item) => item.id,
});
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<string | undefined> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || undefined;
}
- async sealiousValueToForm(ctx: Context, value: string | null) {
+ async sealiousValueToForm(_ctx: Context, value: string | null) {
return value || undefined;
}
generateImportsForFieldList(field_info: ExtractedFieldInfo) {
if (!field_info.target) {
throw new Error("Expected 'target' attribute in field info");
}
return [
{
what: toPascalCase(field_info.target),
from: "src/back/collections/collections.js",
},
];
}
generateFieldDeclaration(
field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
if (!field_info.target) {
throw new Error("Expected 'target' attribute in field info");
}
return `new ${vars.form_field_types}.${
this.constructor.name
}<typeof ${toPascalCase(field_info.target)}, ${String(
field_info.is_required
)}, typeof ${vars.sealious_field}>(${String(field_info.is_required)}, ${
vars.sealious_field
})`;
}
}
diff --git a/src/forms/fields/structured-array.ts b/src/forms/fields/structured-array.ts
index a690294..ce6ff31 100644
--- a/src/forms/fields/structured-array.ts
+++ b/src/forms/fields/structured-array.ts
@@ -1,124 +1,120 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
/* eslint-disable @typescript-eslint/no-unsafe-return */
/* eslint-disable @typescript-eslint/no-unsafe-call */
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
import { Context } from "koa";
import {
Field as SealiousField,
FieldTypes as SealiousFieldTypes,
FieldsetInput,
} from "sealious";
import { FormDataValue } from "../form-types.js";
import { Table as TableControl } from "../controls/table.js";
import {
sealiousToFormField,
SealiousToFormField,
} from "./get-field-for-sealious.js";
import { FormControl, FormControlContext } from "../controls/form-control.js";
import { ExtractedFieldInfo } from "../../utils/extract-fields-from-collection.js";
import { Table } from "./table.js";
export class StructuredArray<
- SealiousFields extends Record<string, SealiousField<unknown>>
+ SealiousFields extends Record<string, SealiousField<unknown>>,
> extends Table<{
[name in keyof SealiousFields]: SealiousToFormField<SealiousFields[name]>;
}> {
public sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>;
constructor(
sealious_field: SealiousFieldTypes.StructuredArray<SealiousFields>
) {
const columns = Object.fromEntries(
Object.entries(sealious_field.subfields).map(
([key, sealious_field]) => [
key,
sealiousToFormField(sealious_field),
]
)
) as {
[name in keyof SealiousFields]: SealiousToFormField<
SealiousFields[name]
>;
};
super(columns);
this.sealious_field = sealious_field;
}
getControl(): TableControl<{
[name in keyof SealiousFields]: SealiousToFormField<
SealiousFields[name]
>;
}> {
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
return new TableControl<{
[name in keyof SealiousFields]: SealiousToFormField<
SealiousFields[name]
>;
}>(this as any, {
label: this.name,
subfield_controls: Object.fromEntries(
Object.entries(this.columns).map(([column_name, subfield]) => [
column_name as keyof SealiousFields,
subfield.getControl(),
])
) as unknown as Record<keyof SealiousFields, FormControl>,
allow_adding: true,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- // eslint-disable-next-line @typescript-eslint/no-unsafe-return
- make_new_row: () => ({} as any),
+ make_new_row: () => ({}) as any,
});
}
generateFieldDeclaration(
_field_info: ExtractedFieldInfo,
vars: { form_field_types: string; sealious_field: string }
): string {
return `new ${vars.form_field_types}.${this.constructor.name}(${vars.sealious_field})`;
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<
SealiousFieldTypes.ArrayStorageInput<FieldsetInput<SealiousFields>>
> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return (
(parsed as SealiousFieldTypes.ArrayStorageInput<
FieldsetInput<SealiousFields>
>) || this.getEmptyValue()
);
}
async sealiousValueToForm(
ctx: Context,
sealiousValue: Record<string, FormDataValue | null>[] | null
): Promise<FormDataValue> {
return Promise.all(
(sealiousValue || []).map(async (element) =>
Object.fromEntries(
await Promise.all(
Object.entries(element).map(async ([key, value]) => {
const form_subfield = this.columns[key];
if (!form_subfield) {
return [key, ""];
}
return [
key,
await form_subfield.sealiousValueToForm(
ctx,
value,
{} as any
),
];
})
)
)
)
);
}
}
diff --git a/src/forms/fields/table.ts b/src/forms/fields/table.ts
index 052544d..1c41b17 100644
--- a/src/forms/fields/table.ts
+++ b/src/forms/fields/table.ts
@@ -1,123 +1,115 @@
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { FormDataValue } from "../form-types.js";
import { FieldParseResult, FormField } from "./field.js";
import {
Table as TableControl,
TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER,
} from "../controls/table.js";
import { FormControl } from "../controls/form-control.js";
export type ExtractFormFieldParsed<Field extends FormField> =
- Field extends FormField<
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- true,
- infer T
- >
+ Field extends FormField<true, infer T>
? NonNullable<T>
- : Field extends FormField<
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
- true,
- infer T
- >
- ? T
- : never;
+ : Field extends FormField<true, infer T>
+ ? T
+ : never;
export type TableFieldParsed<F extends Record<string, FormField>> = {
[field_name in keyof F]: ExtractFormFieldParsed<F[field_name]>;
}[];
export class Table<F extends Record<string, FormField>> extends FormField<
false,
TableFieldParsed<F>
> {
constructor(public columns: F) {
super(false);
}
getEmptyValue() {
return [];
}
setName(name: string) {
super.setName(name);
for (const [column_name, field] of Object.entries(this.columns)) {
field.setName(
`${this.name}[${TABLE_COLUMN_FIELD_INDEX_PLACEHOLDER}][${column_name}]`
);
}
return this;
}
async parse(
ctx: Context,
raw_value: FormDataValue
): Promise<FieldParseResult<TableFieldParsed<F>>> {
// we expect an array-like object: {"0": {...}, ...etc}
if (!is(raw_value, predicates.object)) {
return {
parsable: false,
error: "Expected an object",
parsed_value: null,
};
}
const result: { [field_name in keyof F]: unknown }[] = [];
for (const row_number in raw_value) {
const row_data = raw_value[row_number];
const parsed_row: Record<string, unknown> = {};
if (!is(row_data, predicates.object)) {
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
throw new Error(`Expected object, got ${String(row_data)}`);
}
- for (const key in row_data) {
+ for (const key of Object.keys(row_data)) {
const field = this.columns[key];
if (field == undefined) {
return {
parsable: false,
error: `Unknown column: ${key}`,
parsed_value: null,
};
}
// eslint-disable-next-line no-await-in-loop
const parse_result = await field.parse(
ctx,
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
(row_data as any)[key]
);
if (!parse_result.parsable) {
const message = `Invalid value for row ${row_number}.${key}: ${parse_result.error}`;
console.warn(
`Invalid value for row ${row_number}.${key}: ${parse_result.error}`
);
return {
parsable: false,
error: message,
parsed_value: null,
};
}
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
parsed_row[key] = parse_result.parsed_value as any;
}
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
result.push(parsed_row as { [field_name in keyof F]: unknown });
}
const ret = { parsed_value: result, parsable: true, error: null };
return ret as FieldParseResult<TableFieldParsed<F>>;
}
getControl(): TableControl<F> {
return new TableControl<F>(this, {
label: this.name,
subfield_controls: Object.fromEntries(
Object.entries(this.columns).map(([column_name, field]) => [
column_name as keyof F,
field.getControl(),
])
) as Record<keyof F, FormControl>,
allow_adding: true,
make_new_row: async () =>
Object.fromEntries(
Object.keys(this.columns).map((key) => [key, ""])
) as Record<keyof F, string>,
});
}
}
diff --git a/src/forms/fields/text.ts b/src/forms/fields/text.ts
index ac9c6b7..8f10d93 100644
--- a/src/forms/fields/text.ts
+++ b/src/forms/fields/text.ts
@@ -1,18 +1,18 @@
import { FormControlContext } from "../controls/form-control.js";
import { TextBasedSimpleField } from "./simple-form-field.js";
export class Text<
- Required extends boolean
+ Required extends boolean,
> extends TextBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "text");
}
async getSealiousCreateValue(fctx: FormControlContext): Promise<string> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || this.getEmptyValue();
}
}
diff --git a/src/forms/fields/url.ts b/src/forms/fields/url.ts
index ab898ed..3f264d3 100644
--- a/src/forms/fields/url.ts
+++ b/src/forms/fields/url.ts
@@ -1,20 +1,20 @@
import { FormControlContext } from "../controls/form-control.js";
import { TextBasedSimpleField } from "./simple-form-field.js";
export class URLField<
- Required extends boolean
+ Required extends boolean,
> extends TextBasedSimpleField<Required> {
constructor(required: Required) {
super(required, "text");
}
async getSealiousCreateValue(
fctx: FormControlContext
): Promise<string | null> {
const { parsed } = await this.getParsedValue(
fctx.ctx,
fctx.data.raw_values
);
return parsed || null;
}
}
diff --git a/src/forms/form-types.ts b/src/forms/form-types.ts
index c32a553..fb3f730 100644
--- a/src/forms/form-types.ts
+++ b/src/forms/form-types.ts
@@ -1,37 +1,36 @@
import { FilePointer } from "@sealcode/file-manager";
import type { FlatTemplatable } from "tempstream";
import type { FormField } from "./fields/field.js";
import { FieldMessages } from "./controls/form-control.js";
export type FormDataPrimitive =
| string
| string[]
| number
| undefined
| FilePointer;
export type FormDataValue =
| FormDataPrimitive
| Record<string, FormDataPrimitive>;
-export type FieldValueType<F extends FormField> = F extends FormField<infer R>
- ? R
- : never;
+export type FieldValueType<F extends FormField> =
+ F extends FormField<infer R> ? R : never;
export type FormFieldsToValues<
- F extends Record<string, FormField<boolean, keyof F>>
+ F extends Record<string, FormField<boolean, keyof F>>,
> = {
[Property in keyof F]: FieldValueType<F[Property]>;
};
export type FormMessage = { type: "info" | "success" | "error"; text: string };
export type FormData<Fieldnames extends string = string> = {
raw_values: Record<Fieldnames, FormDataValue>;
messages: FormMessage[];
field_messages: FieldMessages<Fieldnames>;
};
export type FormReaction =
| { action: "stay"; content: FlatTemplatable; messages?: FormMessage[] }
| { action: "redirect"; url: string; messages?: FormMessage[] };
diff --git a/src/forms/form.test.ts b/src/forms/form.test.ts
index c0bc306..a5c43c8 100644
--- a/src/forms/form.test.ts
+++ b/src/forms/form.test.ts
@@ -1,402 +1,401 @@
import Router from "@koa/router";
import axios from "axios";
import Koa, { Context } from "koa";
import { Page } from "playwright";
import { Controls, Fields, Form, Mountable } from "../index.js";
import { mount } from "../mount.js";
import { locator_is_visible } from "../test_utils/locator_is_visible.js";
import { getBrowser } from "../utils/browser-creator.js";
import { assertThrowsAsync } from "../utils/utils.js";
import { FormDataValue } from "./form-types.js";
import getPort from "get-port";
import { TextBasedSimpleField } from "./fields/simple-form-field.js";
import { expect as PlaywritghtExpect } from "@playwright/test";
const fields = {
text: new Fields.TextBasedSimpleField(true),
};
export function form_factory(canAccessFun?: Mountable["canAccess"]): Form<typeof fields, void> {
const result = new (class extends Form<typeof fields, void> {
fields = fields;
submitButtonText = "Submit";
controls = [
new Controls.SimpleInput(fields.text, {
label: "This is a test:",
type: "password",
}),
];
async onSubmit() {
return;
}
})();
if (canAccessFun) result.canAccess = canAccessFun;
return result;
}
const port = await getPort();
-console.log("Using port " + port + " for form.test.ts");
+console.info("Using port " + port + " for form.test.ts");
describe("form test", () => {
let page: Page;
before(async () => {
const browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
});
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
mount(router, "/", form_factory(), true);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
await page.goto(`http://localhost:${port}`);
});
after(async () => {
server.close();
});
it("does not allow to submit an empty form when there's a required field", async () => {
await page.getByRole("button", { name: "Submit", exact: true }).click();
await assertThrowsAsync(async () => {
return page.getByText("Done").click({ timeout: 500 });
});
});
it("allows to submit a form when all required fields have a value", async () => {
await page.getByPlaceholder("password").click();
await page.getByPlaceholder("password").fill("testpasswd");
await page.getByRole("button", { name: "Submit", exact: true }).click();
await page.getByText("Done").click();
});
it("does not allow submitting an empty form by circumventing HTML-based validation", async () => {
const res_axios = await axios.post(
`http://localhost:${port}`,
{
text: "",
},
{
validateStatus: (status: number) => {
if (status == 422) return true;
return false;
},
}
);
- console.log(res_axios.data);
if (!res_axios.data.includes("Some fields are invalid")) {
throw new Error("when sending a empty request with axios, the error didnt appear");
}
});
});
describe("canAccess tests", async () => {
let server: ReturnType<Koa["listen"]>;
afterEach(async () => {
server.close();
});
it("allows visit when configured when canAccess returns true", async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
form_factory(
async (ctx: Koa.Context): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: true, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 200) {
throw new Error(`Should return 200 status and it returns ${response?.status()}`);
}
});
describe("declines access when canAccess returns false", async () => {
const app = new Koa();
const router = new Router();
before(async () => {
mount(
router,
"/",
form_factory(
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: false, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
});
beforeEach(async () => {
server = app.listen(port);
});
it("prevents the form from rendering", async () => {
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 403) {
throw new Error(
`Should return 403 status and it returns ${response?.status()}`
);
}
});
it("does not allow submitting of the form through axios", async () => {
await axios.post(
`http://localhost:${port}`,
{
text: "sample",
},
{
validateStatus: (status: number) => {
if (status == 403) return true;
return false;
},
}
);
});
});
it("passes the context to canAccess (false case)", async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
form_factory(
async (ctx: Koa.Context): Promise<{ canAccess: boolean; message: string }> => {
return ctx.$context && ctx.$context.user_id
? { canAccess: true, message: "" }
: { canAccess: false, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 403) {
throw new Error(`Should return 403 status and it returns ${response?.status()}`);
}
});
it("passes the context to canAccess (true case)", async () => {
const app = new Koa();
const router = new Router();
router.use(async (ctx: Context, next: any) => {
ctx.$context = {
user_id: "miguel",
} as any;
await next();
});
mount(
router,
"/",
form_factory(
async (ctx: Koa.Context): Promise<{ canAccess: boolean; message: string }> => {
return ctx.$context && ctx.$context.user_id
? { canAccess: true, message: "" }
: { canAccess: false, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 200) {
throw new Error(`Should return 200 status and it returns ${response?.status()}`);
}
});
});
describe("validation e2e", async () => {
describe("validation message", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
new (class extends Form<typeof fields, void> {
fields = fields;
submitButtonText = "Submit";
controls = [
new Controls.SimpleInput(fields.text, {
label: "This is a test:",
type: "password",
}),
];
async onSubmit() {
return;
}
async validateValues(
ctx: Koa.Context,
data: Record<string, FormDataValue>
): Promise<{ valid: boolean; error: string }> {
if (data.text === "incorrect")
return {
valid: false,
error: "Incorrect input",
};
return { valid: true, error: "" };
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
await page.goto(`http://localhost:${port}`);
});
after(async () => {
server.close();
});
it("shows up when incorrect input is given", async () => {
await page.getByPlaceholder("password").click();
await page.getByPlaceholder("password").fill("incorrect");
await page.getByRole("button", { name: "Submit" }).click();
if (!(await locator_is_visible(page.getByText("Incorrect input"))))
throw new Error("validation message doens't show up when input is incorrect");
});
it("doesn't show when correct input is given", async () => {
await page.getByPlaceholder("password").click();
await page.getByPlaceholder("password").fill("correct");
await page.getByRole("button", { name: "Submit" }).click();
await assertThrowsAsync(async () => {
return page.getByText("Incorrect input").click({ timeout: 500 });
});
});
});
describe("field specific validation message", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
const fields = {
text: new Fields.EmailField(true),
};
mount(
router,
"/",
new (class extends Form<typeof fields, void> {
fields = fields;
submitButtonText = "Submit";
controls = [
new Controls.SimpleInput(fields.text, {
label: "This is a test:",
type: "text",
}),
];
async onSubmit() {
return;
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
await page.goto(`http://localhost:${port}`);
});
after(async () => {
server.close();
});
it("shows up when incorrect input is given", async () => {
await page.getByPlaceholder("text").click();
await page.getByPlaceholder("text").fill("notanemail");
await page.getByRole("button", { name: "Submit" }).click();
await page.getByText("Please enter a proper email address").click();
});
it("doesn't show up when correct input is given", async () => {
await page.getByPlaceholder("text").click();
await page.getByPlaceholder("text").fill("yes@an.email");
await page.getByRole("button", { name: "Submit" }).click();
- assertThrowsAsync(async () => {
+ await assertThrowsAsync(async () => {
return page
.getByText("Please enter a proper email address")
.click({ timeout: 500 });
});
});
});
});
describe("getInitialValues tests", async () => {
let server: ReturnType<Koa["listen"]>;
afterEach(async () => {
server.close();
});
it("fills the form with values from getInitialValues", async () => {
const app = new Koa();
const router = new Router();
const fields = {
title: new TextBasedSimpleField(true),
};
mount(
router,
"/",
new (class extends Form<typeof fields, null> {
fields = fields;
controls = [new Controls.SimpleInput(fields.title)];
async getInitialValues() {
return { title: "Hello" };
}
onSubmit() {
return null;
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 200) {
throw new Error(`Should return 200 status and it returns ${response?.status()}`);
}
await PlaywritghtExpect(page.getByLabel("title")).toHaveValue("Hello");
});
});
});
diff --git a/src/forms/form.ts b/src/forms/form.ts
index 7251a5e..8871888 100644
--- a/src/forms/form.ts
+++ b/src/forms/form.ts
@@ -1,307 +1,305 @@
import { Context } from "koa";
import { randomUUID } from "crypto";
import Router from "@koa/router";
import { tempstream } from "tempstream";
import {
hasFieldOfType,
hasShape,
is,
predicates,
} from "@sealcode/ts-predicates";
import {
FormData,
FormDataValue,
FormMessage,
FormReaction,
} from "./form-types.js";
import {
Fields,
MountableWithFields,
PageErrorMessage,
} from "../page/mountable-with-fields.js";
import { Readable } from "stream";
import { FormField } from "../index.js";
import { FieldMessages } from "./controls/form-control.js";
import { Errors as SealiousErrors } from "sealious";
export abstract class Form<
F extends Fields,
- SubmitResult
+ SubmitResult,
> extends MountableWithFields<F> {
defaultSuccessMessage = "Done";
submitButtonText = "Wyślij";
action = "./";
useTurbo = true;
form_id = randomUUID() as string;
async canAccess(
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
_: Context
): Promise<{ canAccess: boolean; message: string }> {
return { canAccess: true, message: "" };
}
async renderError(
_: Context,
error: PageErrorMessage
): Promise<JSX.Element | Readable> {
- return tempstream/* HTML */ `<div>${error.message}</div>`;
+ return tempstream /* HTML */ `<div>${error.message}</div>`;
}
makeSubmitButton(): JSX.Element {
return /* HTML */ `<input
type="submit"
value="${this.submitButtonText}"
formaction="${this.action}"
${this.form_id ? `form="${this.form_id}"` : ""}
/>`;
}
async render(
ctx: Context,
data: FormData,
show_field_errors: boolean
): Promise<JSX.Element | Readable> {
- return tempstream/* HTML */ `<div class="form-container">
+ return tempstream /* HTML */ `<div class="form-container">
${this.makeOpenFormTag(ctx)}
${!this.controls.some((control) => control.role == "messages")
? this.renderMessages(ctx, data)
: ""}
${this.renderControls(
this.makeFormControlContext(ctx, data, show_field_errors)
)}
${this.controls.some((control) => control.role == "submit")
? ""
: this.makeSubmitButton()}
${this.makeCloseFormTag()}
</div>`;
}
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
public async makeFormClasses(_ctx: Context): Promise<string[]> {
return [];
}
public makeOpenFormTag(ctx: Context): JSX.Element {
return tempstream`<form enctype="multipart/form-data" method="POST" id="${
this.form_id
}" action="${this.action}" class="${this.makeFormClasses(ctx).then(
(classes) => classes.join(" ")
)}" ${
this.useTurbo ? "" : `data-turbo="false"`
}></form><div class="form">`;
}
public makeCloseFormTag(): JSX.Element {
return `</div>`;
}
public async onValuesInvalid(
ctx: Context,
form_messages: FormMessage[],
field_errors: FieldMessages<keyof Fields>
): Promise<FormReaction> {
const messages = form_messages.length
? form_messages
: [<const>{ type: "error", text: "Some fields are invalid" }];
return {
action: "stay",
content: await this.render(
ctx,
{
raw_values: await this.extractRawValues(ctx),
messages,
field_messages: field_errors,
},
true
),
messages,
};
}
public async onError(
ctx: Context,
data: FormData,
error: unknown
): Promise<FormReaction> {
let error_message = "Unknown error has occured";
let field_messages: FieldMessages = {};
if (
is(error, predicates.object) &&
hasShape({ message: predicates.string }, error)
) {
error_message = error.message;
}
if (error instanceof SealiousErrors.FieldsError) {
field_messages = Object.fromEntries(
Object.entries(error.field_messages).map(([key, value]) => {
const message = value?.message || "";
return [key, { type: "error", message }];
})
);
}
const messages = [<const>{ type: "error", text: error_message }];
return {
action: "stay",
content: await this.render(
ctx,
{
raw_values: data.raw_values,
messages,
field_messages,
},
true
),
};
}
public abstract onSubmit(
ctx: Context,
data: FormData
): SubmitResult | Promise<SubmitResult>;
public async onSuccess(
ctx: Context,
_data: FormData,
_submitResult: SubmitResult
): Promise<FormReaction> {
const messages = [
<const>{ type: "success", text: this.defaultSuccessMessage },
];
return {
action: "stay",
content: await this.render(
ctx,
{
raw_values: await this.getInitialValues(ctx),
messages,
field_messages: {},
},
false
),
messages,
};
}
async getRawValuesOnSuccess(ctx: Context) {
return this.extractRawValues(ctx);
}
async handlePost(ctx: Context): Promise<FormReaction> {
const raw_values = await this.extractRawValues(ctx);
const { valid, form_messages, field_errors } = await this.validate(
ctx,
raw_values
);
if (!valid) {
return this.onValuesInvalid(ctx, form_messages, field_errors);
}
try {
ctx.status = 303;
const result = await this.onSubmit(ctx, {
raw_values,
messages: [],
field_messages: {},
});
return this.onSuccess(
ctx,
{
raw_values: await this.getRawValuesOnSuccess(ctx),
messages: [],
field_messages: {},
},
result
);
} catch (e: unknown) {
// eslint-disable-next-line no-console
console.dir(e, { depth: 5 });
const message =
is(e, predicates.object) &&
hasFieldOfType(e, "message", predicates.string)
? e?.message
: is(e, predicates.string)
- ? e
- : "Wystąpił błąd";
+ ? e
+ : "Wystąpił błąd";
return this.onError(
ctx,
{
raw_values,
messages: [
{
type: "error",
text: message,
},
],
field_messages: {},
},
e
);
}
}
public mount(router: Router, path: string): void {
router.use(path, async (ctx, next) => {
const result = await this.canAccess(ctx);
if (!result.canAccess) {
ctx.body = this.renderError(ctx, {
type: "access",
message: result.message,
});
ctx.status = 403;
return;
}
await next();
});
// for use with other subroutes or middlewares that individual controls
// might register
const subrouter = new Router();
for (const control of this.controls) {
control.mount(subrouter, this);
}
router.use(path, subrouter.routes(), subrouter.allowedMethods());
router.get(path, async (ctx) => {
ctx.type = "html";
ctx.body = await this.render(
ctx,
{
raw_values: await this.extractRawValues(ctx),
messages: [],
field_messages: {},
},
false
);
});
router.post(path, async (ctx) => {
const reaction =
(ctx.override_reaction as FormReaction | undefined) ||
(await this.handlePost(ctx));
if (reaction.action == "stay") {
ctx.status = 422;
ctx.body = reaction.content;
} else if (reaction.action == "redirect") {
ctx.status = 303;
ctx.redirect(reaction.url);
}
});
}
async extractRawValues(
ctx: Context
): Promise<Record<string, FormDataValue>> {
return Object.keys(ctx.$body).length
? ctx.$body
: this.getInitialValues(ctx);
}
static initFieldNames(fields: Record<string, FormField>): void {
for (const [field_name, field] of Object.entries(fields)) {
field.setName(field_name);
}
}
}
diff --git a/src/forms/multiform.test.ts b/src/forms/multiform.test.ts
index b96736b..86120f3 100644
--- a/src/forms/multiform.test.ts
+++ b/src/forms/multiform.test.ts
@@ -1,549 +1,549 @@
import Router from "@koa/router";
import Koa from "koa";
import axios from "axios";
import { Browser, Page } from "playwright";
import { expect } from "@playwright/test";
import { FlatTemplatable, tempstream } from "tempstream";
import { mount } from "../mount.js";
import { Multiform } from "./multiform.js";
import { assertThrowsAsync } from "../utils/utils.js";
import { form_factory } from "./form.test.js";
import { getBrowser } from "../utils/browser-creator.js";
import { TextBasedSimpleField } from "./fields/simple-form-field.js";
import { Form } from "./form.js";
import { FormHeader } from "./controls/form-header.js";
import { SimpleInput } from "./controls/simple-input.js";
import { Mountable } from "../page/mountable.js";
import { FormDataValue, FormMessage } from "./form-types.js";
import { EmailField } from "./fields/email.js";
import getPort from "get-port";
const port = await getPort();
-console.log(`Using port ${port} form multiform.test.ts`);
+console.info(`Using port ${port} form multiform.test.ts`);
const fields1 = {
email: new TextBasedSimpleField(true),
};
const form1 = new (class extends Form<typeof fields1, void> {
defaultSuccessMessage = "Form1 done!";
controls = [new FormHeader("form1"), new SimpleInput(fields1.email)];
fields = fields1;
onSubmit() {
return;
}
})();
const fields2 = {
name: new TextBasedSimpleField(true),
};
const form2 = new (class extends Form<Record<never, unknown>, void> {
defaultSuccessMessage = "Form2 done!";
controls = [new FormHeader("form2"), new SimpleInput(fields2.name)];
fields = fields2;
onSubmit() {
return;
}
})();
function multiform_factory(
canAccessFun1?: Mountable["canAccess"],
canAccessFun2?: Mountable["canAccess"]
): Multiform {
return new (class extends Multiform {
name = "multiform_test";
forms = {
form1: form_factory(canAccessFun1),
form2: form_factory(canAccessFun2),
};
async render(...args: Parameters<Multiform["render"]>): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `<!DOCTYPE html>
+ return tempstream /* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Multiform Test - Sealgen</title>
<script type="module">
import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
</script>
</head>
<body>
${super.render(...args)}
</body>
</html>`;
}
})();
}
async function tests(js_enabled: boolean) {
let page: Page;
before(async () => {
const browser = await getBrowser();
const context = await browser.newContext({
javaScriptEnabled: js_enabled,
});
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByLabel("email").click();
await page.getByLabel("email").fill("sample1");
await page.getByLabel("name").click();
await page.getByLabel("name").fill("sample2");
await page.locator("#multiform_test_form1_submit").click();
});
it("checking whether only one submit handler is run", async () => {
await page.getByText("Form1 done!").click();
await assertThrowsAsync(async () => {
return page.getByText("Form2 done!").click({ timeout: 500 });
});
});
it("checking whether the input in the not submitted form prevails", async () => {
await expect(page.getByLabel("name")).toHaveValue("sample2");
});
}
async function general_form_validation_e2e_tests(js_enabled: boolean) {
let browser: Browser;
let page: Page;
browser = await getBrowser();
const context = await browser.newContext({
javaScriptEnabled: js_enabled,
});
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
await page.getByPlaceholder("text").click();
await page.getByPlaceholder("text").fill("incorrect");
await page.getByPlaceholder("password").click();
await page.getByPlaceholder("password").fill("test");
await page.locator("#multiform_test_form2_submit").click();
await assertThrowsAsync(async () => {
await page.getByText("Incorrect input").click({ timeout: 500 });
});
}
async function individual_field_validation_e2e_tests(javaScriptEnabled: boolean) {
let browser: Browser;
let page: Page;
before(async () => {
browser = await getBrowser();
const context = await browser.newContext({
javaScriptEnabled,
});
page = await context.newPage();
await page.goto(`http://localhost:${port}`);
});
it("validation message shows when incorrect input is given", async () => {
await page.getByPlaceholder("text").click();
await page.getByPlaceholder("text").fill("notanemail");
await page.locator("#multiform_test_form1_submit").click();
await page.getByText("Please enter a proper email address").click();
});
it("validation message doesn't show when correct input is given", async () => {
await page.getByPlaceholder("text").click();
await page.getByPlaceholder("text").fill("yes@an.email");
await page.locator("#multiform_test_form1_submit").click();
- assertThrowsAsync(async () => {
+ await assertThrowsAsync(async () => {
return page.getByText("Please enter a proper email address").click({ timeout: 500 });
});
});
}
describe("multiform test", () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
new (class extends Multiform {
name = "multiform_test";
forms = { form1, form2 };
async render(
ctx: Koa.Context,
messages: FormMessage[],
prerenderedForms?: Record<string, FlatTemplatable | undefined>,
show_field_errors = true
): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `<!DOCTYPE html>
+ return tempstream /* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Multiform Test - Sealgen</title>
<script type="module">
import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
</script>
</head>
<body>
${super.render(
ctx,
messages,
prerenderedForms,
show_field_errors
)}
</body>
</html>`;
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
});
after(() => {
server.close();
});
describe("turbolinks + js enabled", async () => tests(true));
describe("turbolinks + js disabled", async () => tests(false));
});
describe("canAccess", async () => {
let page: Page;
let server: ReturnType<Koa["listen"]>;
describe("allow access to both forms when both canAccess return true", async () => {
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
multiform_factory(
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: true, message: "" };
},
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: true, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
});
after(async () => {
server.close();
});
it("check wether it renders", async () => {
const response = await page.goto(`http://localhost:${port}`);
if (response?.status() != 200) {
throw new Error(
`Should return 200 status and it returns ${response?.status()}`
);
}
await page.locator("#form1").getByText("This is a test:").click();
await page.locator("#form2").getByText("This is a test:").click();
});
it("check wether you can submit through http (axios)", async () => {
await axios.post(
`http://localhost:${port}/form2`,
{
form2__text: "pass",
},
{
validateStatus: (status: number) => {
if (status == 422) return true;
return false;
},
}
);
});
});
describe("deny access to both forms", async () => {
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
multiform_factory(
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: false, message: "" };
},
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: false, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const browser = await getBrowser();
const context = await browser.newContext();
page = await context.newPage();
});
after(async () => {
server.close();
});
it("check wether forms didnt render", async () => {
await page.goto(`http://localhost:${port}`);
await assertThrowsAsync(async () => {
return page
.locator("#form1")
.getByText("This is a test:")
.click({ timeout: 300 });
});
});
it("check wether it's possible to submit through http", async () => {
await axios.post(
`http://localhost:${port}/form2`,
{
form2__text: "pass",
},
{
validateStatus: (status: number) => {
if (status == 403) return true;
return false;
},
}
);
});
});
describe("allow access to one form, deny to the other", async () => {
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
multiform_factory(
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: true, message: "" };
},
async (
ctx: Koa.Context
): Promise<{ canAccess: boolean; message: string }> => {
return { canAccess: false, message: "" };
}
),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
const browser = await getBrowser();
const context = await browser.newContext({});
page = await context.newPage();
});
after(async () => {
server.close();
});
it("check wether form1 renders", async () => {
await page.goto(`http://localhost:${port}`);
await page.locator("#form1").getByText("This is a test:").click({ timeout: 300 });
});
it("check wether it's possible to submit to form1 through http", async () => {
await axios.post(
`http://localhost:${port}/form1`,
{
form1__text: "pass",
},
{
validateStatus: (status: number) => {
if (status == 422) return true;
return false;
},
}
);
});
it("check wether form2 does not render", async () => {
await page.goto(`http://localhost:${port}`);
await assertThrowsAsync(async () => {
return page
.locator("#form2")
.getByText("This is a test:")
.click({ timeout: 300 });
});
});
it("check wether it's possible to submit to form2 through http", async () => {
await axios.post(
`http://localhost:${port}/form2`,
{
form2__text: "pass",
},
{
validateStatus: (status: number) => {
if (status == 403) return true;
return false;
},
}
);
});
});
});
describe("validation e2e", async () => {
describe("basic tests", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
mount(
router,
"/",
new (class extends Multiform {
name = "multiform_test";
forms = {
form1: new (class extends Form<typeof fields1, void> {
fields = fields1;
submitButtonText = "Submit";
controls = [
new SimpleInput(fields1.email, {
label: "This is a test:",
type: "text",
}),
];
async onSubmit() {
return;
}
async validateValues(
ctx: Koa.Context,
data: Record<string, FormDataValue>
): Promise<{ valid: boolean; error: string }> {
if (data.email === "incorrect")
return {
valid: false,
error: "Incorrect input",
};
return { valid: true, error: "" };
}
})(),
form2: form_factory(),
};
async render(
...args: Parameters<Multiform["render"]>
): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `<!DOCTYPE html>
+ return tempstream /* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Multiform Test - Sealgen</title>
<script type="module">
import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
</script>
</head>
<body>
${super.render(...args)}
</body>
</html>`;
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
});
after(async () => {
server.close();
});
it("js enabled", async () => general_form_validation_e2e_tests(true));
it("js disabled", async () => general_form_validation_e2e_tests(false));
});
describe("field specific validation", async () => {
let server: ReturnType<Koa["listen"]>;
before(async () => {
const app = new Koa();
const router = new Router();
const fields = {
text: new EmailField(true),
};
mount(
router,
"/",
new (class extends Multiform {
name = "multiform_test";
forms = {
form1: new (class extends Form<typeof fields, void> {
fields = fields;
submitButtonText = "Submit";
controls = [
new SimpleInput(fields.text, {
label: "This is a test:",
type: "text",
}),
];
async onSubmit() {
return;
}
})(),
form2: form_factory(),
};
async render(
...args: Parameters<Multiform["render"]>
): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `<!DOCTYPE html>
+ return tempstream /* HTML */ `<!DOCTYPE html>
<html>
<head>
<title>Multiform Test - Sealgen</title>
<script type="module">
import hotwiredTurbo from "https://cdn.skypack.dev/pin/@hotwired/turbo@v7.0.0-9XNv1By6uiqRlBzQLO2d/mode=imports,min/optimized/@hotwired/turbo.js";
</script>
</head>
<body>
${super.render(...args)}
</body>
</html>`;
}
})(),
true
);
app.use(router.routes()).use(router.allowedMethods());
server = app.listen(port);
});
after(async () => {
server.close();
});
describe("js enabled", async () => individual_field_validation_e2e_tests(true));
describe("js disabled", async () => individual_field_validation_e2e_tests(false));
});
});
});
diff --git a/src/forms/multiform.ts b/src/forms/multiform.ts
index 6efca6f..8f81414 100644
--- a/src/forms/multiform.ts
+++ b/src/forms/multiform.ts
@@ -1,240 +1,240 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Router from "@koa/router";
import { is, predicates } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import { Fields, MountableWithFields } from "../page/mountable-with-fields.js";
import { attribute } from "../sanitize.js";
import type { FormDataValue, FormMessage } from "./form-types.js";
import { Form } from "./form.js";
const FIELD_PREFIX_SEPARATOR = "___";
export class Multiform extends MountableWithFields {
controls = [];
public name: string;
public forms: Record<string, Form<Fields, unknown>>;
init(): void {
super.init();
for (const [key, form] of Object.entries(this.forms)) {
if (key !== attribute(key)) {
throw new Error(
`Form name "${key}" is not url-safe. Try: "${attribute(
key
)}"`
);
}
form.makeOpenFormTag = () => `<div>`;
form.makeCloseFormTag = () => `</div>`;
form.field_names_prefix = key + FIELD_PREFIX_SEPARATOR;
form.form_id = this.name;
form.action = "./" + key;
form.init();
form.extractRawValues = async (context) =>
this.getSubformRawValues(context, key);
const submit_button_id = this.name + "_" + key + "_submit";
- form.makeSubmitButton = () => /* HTML */ `<input
- type="submit"
- value="${form.submitButtonText}"
- formaction="${form.action}"
- id="${submit_button_id}"
- ${form.form_id ? `form="${form.form_id}"` : ""}
- /> `;
+ form.makeSubmitButton = () =>
+ /* HTML */ `<input
+ type="submit"
+ value="${form.submitButtonText}"
+ formaction="${form.action}"
+ id="${submit_button_id}"
+ ${form.form_id ? `form="${form.form_id}"` : ""}
+ /> `;
}
for (const form of Object.values(this.forms)) {
for (const field of Object.values(form.fields)) {
if (field.name.includes(FIELD_PREFIX_SEPARATOR)) {
throw new Error(
`A field name within multiform cannot contain '${FIELD_PREFIX_SEPARATOR}'`
);
}
}
}
}
async extractRawValues(
ctx: Context
): Promise<Record<string, FormDataValue>> {
return ctx.$body || {};
}
async canAccess(): Promise<{ canAccess: boolean; message: string }> {
return {
canAccess: true,
message:
"this view includes multiple forms and each of them have their unique access rules",
};
}
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
getSubformsToRender(
ctx: Context
): Array<readonly [string, Form<any, unknown>]> {
const requested_frame = ctx.headers["turbo-frame"];
if (
!is(
requested_frame,
predicates.or(predicates.undefined, predicates.string)
)
) {
throw new Error("Wrong turbo-frame header value type");
}
const forms_to_render =
requested_frame && this.forms[requested_frame]
? [<const>[requested_frame, this.forms[requested_frame]]]
: Object.entries(this.forms);
return forms_to_render;
}
async renderSubform(
ctx: Context,
sub_form_name: string,
show_field_errors: boolean
): Promise<FlatTemplatable> {
const form = this.forms[sub_form_name];
const result = await form.canAccess(ctx);
if (!result.canAccess) {
return result.message;
}
return form.render(
ctx,
{
raw_values: await this.getSubformRawValues(ctx, sub_form_name),
messages: [],
field_messages: {},
},
show_field_errors
);
}
async getSubformRawValues(
ctx: Context,
sub_form_name: string
): Promise<Record<string, FormDataValue>> {
const result = Object.fromEntries(
Object.entries(await this.extractRawValues(ctx))
.filter(([key]) =>
key.startsWith(sub_form_name + FIELD_PREFIX_SEPARATOR)
)
.map(([key, value]) => [
key.slice((sub_form_name + FIELD_PREFIX_SEPARATOR).length),
value,
])
);
return result;
}
async render(
ctx: Context,
messages: FormMessage[],
prerenderedForms: Record<string, FlatTemplatable | undefined> = {},
show_field_errors: boolean
): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `${this.renderMessages(ctx, {
+ return tempstream /* HTML */ `${this.renderMessages(ctx, {
raw_values: {},
messages,
field_messages: {},
})}
<div class="forms">
<form
id="${this.name}"
novalidate
${
/* novalidate is here because all the subforms are actually one form and errors in one will prevent submitting all of the forms */ ""
}
method="POST"
></form>
${this.getSubformsToRender(ctx).map(([form_name]) => {
const frame_form_id =
this.name + "_" + form_name + "_frame_form";
- return tempstream/* HTML */ `<turbo-frame
+ return tempstream /* HTML */ `<turbo-frame
id="${form_name}"
contains-subform
subform-id="${frame_form_id}"
>
${prerenderedForms[form_name] ||
this.renderSubform(ctx, form_name, show_field_errors)}
<form id="${frame_form_id}" method="POST"></form>
</turbo-frame>`;
})}
</div>
${this.makeBottomScript()}`;
}
makeBottomScript(): string {
// this script assigns each field to its corresponding form, instead of
// the html-only version where all fields are attached to one meta-form
return /* HTML */ ` <script>
(function () {
if (!window.subform_handlers) {
window.subform_handlers = {};
}
if (window.subform_handlers["${this.name}"]) {
return;
}
const handler = () => {
document
.querySelectorAll("turbo-frame[contains-subform]")
.forEach((frame) => {
frame_form_id = frame.getAttribute("subform-id");
frame.querySelectorAll("input").forEach((input) => {
input.setAttribute("form", frame_form_id);
});
});
};
window.subform_handlers["${this.name}"] = handler;
document.documentElement.addEventListener(
"turbo:load",
handler
);
document.documentElement.addEventListener(
"turbo:frame-render",
handler
);
})();
</script>`;
}
mount(router: Router, path: string): void {
router.get(path, async (ctx) => {
ctx.type = "html";
ctx.body = await this.render(ctx, [], {}, false);
});
for (const [key, form] of Object.entries(this.forms)) {
router.post(
path + (path.endsWith("/") ? "" : "/") + key,
async (ctx) => {
const result = await form.canAccess(ctx);
if (!result.canAccess) {
ctx.body = this.renderError(ctx, {
type: "access",
message: result.message,
});
ctx.status = 403;
return;
}
const reaction = await form.handlePost(ctx);
if (reaction.action == "stay") {
ctx.status = 422;
const form_content = reaction.content;
ctx.body = this.render(
ctx,
[],
{
[key]: form_content,
},
true
);
} else if (reaction.action == "redirect") {
ctx.status = 303;
ctx.redirect(reaction.url);
}
}
);
}
}
}
diff --git a/src/generate-collections.ts b/src/generate-collections.ts
index 80e11a1..2c9b443 100644
--- a/src/generate-collections.ts
+++ b/src/generate-collections.ts
@@ -1,78 +1,77 @@
import _locreq from "locreq";
-import * as prettier from "prettier";
import { promises as fs } from "fs";
import { assertType, predicates } from "@sealcode/ts-predicates";
-import { getPrettierConfig } from "./utils/prettier.js";
+import { formatWithPrettier } from "./utils/prettier.js";
const target_locreq = _locreq(process.cwd());
export async function extractCollectionClassname(
full_file_path: string
): Promise<string> {
const file_content = await fs.readFile(full_file_path, "utf-8");
const result = /export default class (\w+)/.exec(file_content);
if (result === null) {
throw new Error("Missing 'export default class' statement?");
}
return assertType(
result[1],
predicates.string,
`Missing export default class in '${full_file_path}'?`
);
}
export async function generateCollections(): Promise<void> {
const collections_dir = target_locreq.resolve("src/back/collections");
const files = (await fs.readdir(collections_dir)).filter(
(f) =>
!/\.(sub)?test\./.exec(f) &&
f != "collections.ts" &&
!f.includes(".#") &&
f.endsWith(".ts")
);
const file_data = await Promise.all(
files.map(async (file) => {
const full_path = target_locreq.resolve(
"src/back/collections/" + file
);
const class_name = await extractCollectionClassname(full_path);
return {
class_name,
file,
full_path,
urlname: file.replace(".ts", ""),
};
})
);
const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-collections'
import { App } from "sealious";
${file_data
.map(
({ class_name, urlname }) =>
`import _${class_name} from "./${urlname}.js";`
)
.join("\n")}
${file_data
.map(
({ class_name }) => `export const ${class_name} = new _${class_name}();`
)
.join("\n")}
export const collections = {
...App.BaseCollections,
${file_data
.map(({ class_name, urlname }) => ` "${urlname}": ${class_name},`)
.join("\n")}
};`;
await fs.writeFile(
target_locreq.resolve("src/back/collections/collections.ts"),
- prettier.format(content, await getPrettierConfig())
+ await formatWithPrettier(content)
);
// eslint-disable-next-line no-console
console.log(
"Successfuly generated new src/back/collections/collections.ts file"
);
}
diff --git a/src/generate-components.ts b/src/generate-components.ts
index f691cb4..682f2b0 100644
--- a/src/generate-components.ts
+++ b/src/generate-components.ts
@@ -1,47 +1,46 @@
import _locreq from "locreq";
-import * as prettier from "prettier";
import { promises as fs } from "fs";
-import { getPrettierConfig } from "./utils/prettier.js";
+import { formatWithPrettier } from "./utils/prettier.js";
import recursive from "recursive-readdir";
import path from "path";
import { toKebabCase, toPascalCase } from "js-convert-case";
import { mkdir } from "fs/promises";
const target_locreq = _locreq(process.cwd());
export async function generateComponents(): Promise<void> {
const components_dir = target_locreq.resolve("src/back/jdd-components");
await mkdir(components_dir, { recursive: true });
const component_names = (await recursive(components_dir))
.filter((c) => c.endsWith(".jdd.tsx"))
.sort();
const component_data = component_names
.map(
(p) =>
"./" +
path.relative(components_dir, p).replace(/\.[tj]sx?$/, ".js")
)
.map((relative_path) => {
const name = relative_path.match(/\/([^/]+).jdd/)?.[1];
return { name, relative_path };
});
const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-components'
import { Registry } from "@sealcode/jdd";
export const registry = new Registry();
${component_data
.map(
(c) => `
import { ${toPascalCase(c.name)} } from "${c.relative_path}";
registry.add("${toKebabCase(c.name)}", ${toPascalCase(c.name)});`
)
.join("\n")}`;
const target = "src/back/jdd-components/components.ts";
await fs.writeFile(
target_locreq.resolve(target),
- prettier.format(content, await getPrettierConfig())
+ await formatWithPrettier(content)
);
// eslint-disable-next-line no-console
console.log(`Successfuly generated new ${target} file`);
}
diff --git a/src/generate-routes.test.ts b/src/generate-routes.test.ts
index d5b6ca3..3fa5b6d 100644
--- a/src/generate-routes.test.ts
+++ b/src/generate-routes.test.ts
@@ -1,68 +1,59 @@
import { generateURL, sortRoutes } from "./generate-routes.js";
-import * as prettier from "prettier";
-import { getPrettierConfig } from "./utils/prettier.js";
+import { formatWithPrettier } from "./utils/prettier.js";
import assert from "node:assert";
describe("generate routes", () => {
it("handles a url with params", async () => {
assert.strictEqual(
- prettier.format(
- generateURL("EditUser", "/admin/users/:id/edit/"),
- await getPrettierConfig()
- ),
- prettier.format(
+ await formatWithPrettier(generateURL("EditUser", "/admin/users/:id/edit/")),
+ await formatWithPrettier(
`export const EditUserURL = (id: string) => \`/admin/users/\${id}/edit/\`;
EditUserURL.params = ["id"];
-EditUserURL.rawURL = "/admin/users/:id/edit/";`,
- await getPrettierConfig()
+EditUserURL.rawURL = "/admin/users/:id/edit/";`
)
);
});
it("handles polish characters in the url", () => {
assert.strictEqual(
generateURL("Users", "/admin/użytkownicy/"),
`export const UsersURL = "/admin/u%C5%BCytkownicy/";`
);
});
it("handles a url with params and diacritics", async () => {
assert.strictEqual(
- prettier.format(
- generateURL("EditUser", "/admin/użytkownicy/:id/edit/"),
- await getPrettierConfig()
- ),
- prettier.format(
+ await formatWithPrettier(generateURL("EditUser", "/admin/użytkownicy/:id/edit/")),
+ await formatWithPrettier(
`export const EditUserURL = (id: string) => \`/admin/u%C5%BCytkownicy/\${id}/edit/\`;
EditUserURL.params = ["id"];
-EditUserURL.rawURL = "/admin/u%C5%BCytkownicy/:id/edit/";`,
- await getPrettierConfig()
+EditUserURL.rawURL = "/admin/u%C5%BCytkownicy/:id/edit/";`
)
);
});
it("sorts routes from most specific first to least specific last, considering directory structure", () => {
assert.deepStrictEqual(
sortRoutes(
[
"/home",
"/foo/:bar/:baz",
"/:param1/:param2/:param3",
"/foo/bar/baz",
"/foo/:bar",
"/:param1",
].map((url) => ({
url,
}))
).map(({ url }: { url: string }) => url),
[
"/home",
"/:param1",
"/foo/:bar",
"/foo/bar/baz",
"/foo/:bar/:baz",
"/:param1/:param2/:param3",
]
);
});
});
diff --git a/src/generate-routes.ts b/src/generate-routes.ts
index d4e7c53..181066f 100644
--- a/src/generate-routes.ts
+++ b/src/generate-routes.ts
@@ -1,146 +1,142 @@
import { promises as fs } from "fs";
-import * as prettier from "prettier";
import { relative, resolve, basename } from "path";
import _locreq from "locreq";
import { walkDir } from "./utils/walk.js";
import { importPath } from "./utils/import-path.js";
import { assertType, predicates } from "@sealcode/ts-predicates";
import { unescape_url_params } from "./utils/escape-url-params.js";
-import { getPrettierConfig } from "./utils/prettier.js";
+import { formatWithPrettier } from "./utils/prettier.js";
import { Templates } from "./templates/templates.js";
const target_locreq = _locreq(process.cwd());
async function extractActionName(full_file_path: string): Promise<string> {
const file_content = await fs.readFile(full_file_path, "utf-8");
const result = /export const actionName = "(\w+)"/.exec(file_content);
if (result === null) {
throw new Error("Missing 'export const actionName' statement?");
}
return assertType(
result[1],
predicates.string,
"Missing export default class?"
);
}
export function generateURL(actionName: string, url: string) {
const parts = url.split("/");
const params = parts
.filter((part) => part.startsWith(":"))
.map((part) => part.slice(1));
if (params.length === 0) {
return `export const ${actionName}URL = "${encodeURI(url)}";`;
}
return `export const ${actionName}URL = (${params
.map((s) => s + ": string")
.join(", ")})=>\`${parts
.map((part) =>
part.startsWith(":")
? "${" + part.slice(1) + "}"
: encodeURIComponent(part)
)
.join("/")}\`;
${actionName}URL.params = [${params
- .map((param) => `"${param}"`)
- .join(",")}];
+ .map((param) => `"${param}"`)
+ .join(",")}];
${actionName}URL.rawURL = "${encodeURI(url)}";`;
}
export function sortRoutes<T extends { url: string }>(urls: T[]): T[] {
return urls.sort(({ url: url1 }, { url: url2 }) => {
const [segments1, segments2] = [url1, url2].map((url) =>
url.split("/")
);
if (segments1.length < segments2.length) {
return -1;
}
if (segments1.length > segments2.length) {
return 1;
}
// if they are the same length, map each url to a string like 00010
// where "0" is for static (so should be sorted earlier, and "1" is for
// dynamic parts
const [encoded1, encoded2] = [url1, url2].map((url) =>
url.split("/").map((e) => (e.startsWith(":") ? "1" : "0"))
);
return encoded1 < encoded2 ? -1 : 1;
});
}
export async function generateRoutes(): Promise<void> {
const files = await Promise.all(
- (
- await walkDir(target_locreq.resolve("src/back/routes"))
- )
+ (await walkDir(target_locreq.resolve("src/back/routes")))
.filter((f) =>
Object.keys(Templates).some(
(key) =>
f.endsWith(`.${key}.ts`) || f.endsWith(`.${key}.tsx`)
)
)
.map(async (fullpath) => ({
fullpath,
actionName: await extractActionName(fullpath),
// trailing slash is important here, as it enables to use the entire path while building relative URLs. For example, while visiting /users/123, the path ./add-photo leads to /users/add-photo. While visiting /users/123/ (note the trailing slash), the path ./add-photo leads to /users/123/add-photo
url: unescape_url_params(
"/" +
relative(
target_locreq.resolve("src/back/routes"),
resolve(
fullpath,
basename(fullpath).startsWith("index.")
? "../"
: ""
)
).replace(/\..+/, "") +
"/"
).replace(/\/\//g, "/"),
}))
);
const routes_content = `// DO NOT EDIT! This file is generated automaticaly with npm run generate-routes
import type Router from "@koa/router";
import { mount } from "@sealcode/sealgen";
import * as URLs from "./urls.js"
${sortRoutes(files)
.map(
({ actionName, fullpath }) =>
`import { default as ${actionName} } from "${importPath(
target_locreq.resolve("src/back/routes/routes.ts"),
fullpath
)}";`
)
.join("\n")}
export default function mountAutoRoutes(router: Router) {
${sortRoutes(files)
.map(
({ actionName }) =>
` mount(router, URLs.${actionName}URL, ${actionName});`
)
.join("\n")}
}`;
const urls_content = `${sortRoutes(files)
.map(({ actionName, url }) => generateURL(actionName, url))
.join("\n")}
`;
- const prettier_config = await getPrettierConfig();
await fs.writeFile(
target_locreq.resolve("src/back/routes/routes.ts"),
- prettier.format(routes_content, prettier_config)
+ await formatWithPrettier(routes_content)
);
await fs.writeFile(
target_locreq.resolve("src/back/routes/urls.ts"),
- prettier.format(urls_content, prettier_config)
+ await formatWithPrettier(urls_content)
);
// eslint-disable-next-line no-console
console.log(
"Successfuly generated new src/back/routes/routes.ts and src/back/routes/urls.ts"
);
}
diff --git a/src/generate-stimulus.ts b/src/generate-stimulus.ts
index 4cd1918..3cd0460 100644
--- a/src/generate-stimulus.ts
+++ b/src/generate-stimulus.ts
@@ -1,61 +1,59 @@
import _locreq from "locreq";
-import * as prettier from "prettier";
import { promises as fs } from "fs";
-import { getPrettierConfig } from "./utils/prettier.js";
+import { formatWithPrettier } from "./utils/prettier.js";
import recursive from "recursive-readdir";
import path, { dirname } from "path";
import { toKebabCase, toPascalCase } from "js-convert-case";
const target_locreq = _locreq(process.cwd());
export async function generateStimulusControllers(
controller_dirs: string[]
): Promise<void> {
const output_file = "src/front/controllers.ts";
const stimulus_search_dirs = [
target_locreq.resolve("src/"),
...controller_dirs,
];
- console.log("Looking for controllers in ", stimulus_search_dirs);
+ console.info("Looking for controllers in ", stimulus_search_dirs);
const controller_names = (
await Promise.all(stimulus_search_dirs.map((dir) => recursive(dir)))
)
.flat()
.filter((c) => c.endsWith(".stimulus.ts"))
.sort();
const controller_data = controller_names
.map(
(p) =>
"./" +
path
.relative(target_locreq.resolve(dirname(output_file)), p)
.replace(/\.[tj]sx?$/, ".js")
)
.map((relative_path) => {
const name = relative_path.match(/\/([^/]+).stimulus/)?.[1];
return { name, relative_path };
});
const content = `// DO NOT EDIT! This file is generated automaticaly with 'npm run generate-stimulus'
import * as Turbo from "@hotwired/turbo";
import { Application } from "stimulus";
const application = Application.start();
${controller_data
.map(
(c) => `
import { default as ${toPascalCase(c.name)} } from "${c.relative_path}";
application.register("${toKebabCase(c.name)}", ${toPascalCase(c.name)});`
)
.join("\n")}
export { Turbo };
`;
await fs.writeFile(
target_locreq.resolve(output_file),
- prettier.format(content, await getPrettierConfig())
+ await formatWithPrettier(content)
);
- // eslint-disable-next-line no-console
- console.log(`Successfuly generated new ${output_file} file`);
+ console.info(`Successfuly generated new ${output_file} file`);
}
diff --git a/src/get-fonts.ts b/src/get-fonts.ts
index 2718b03..f2cf3da 100644
--- a/src/get-fonts.ts
+++ b/src/get-fonts.ts
@@ -1,99 +1,101 @@
import { mkdir, readFile, writeFile, unlink, rmdir } from "fs/promises";
import { constructURL, download } from "google-fonts-helper";
import { resolve } from "node:path";
import { target_locreq } from "./target-locreq.js";
import { exec } from "child_process";
import { is, predicates } from "@sealcode/ts-predicates";
import { promisify } from "util";
import _locreq from "locreq";
const locreq = _locreq(import.meta.dirname);
const path_to_fonsta = locreq.resolve("node_modules/fonsta/bin/fonsta");
import JSON5 from "json5";
export const FONTS_CONFIG_PATH = "src/fonts.json";
const execPromise = promisify(exec);
export async function getFonts(_: Record<string, string | boolean> = {}) {
const fonts_config_path = target_locreq.resolve(FONTS_CONFIG_PATH);
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const fonts_config = JSON5.parse(await readFile(fonts_config_path, "utf8"));
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-unsafe-member-access
const google_fonts = constructURL(fonts_config.googleFonts);
if (!google_fonts) {
throw new Error("Invalid font config");
}
const downloader = download(google_fonts, {
base64: false,
overwriting: false,
outputDir: target_locreq.resolve("public/dist/fonts"),
stylePath: "fonts.css",
fontsDir: "./",
fontsPath: "/dist/fonts",
});
await downloader.execute();
- console.log("Downloaded new fonts pack from google fonts");
+ console.info("Downloaded new fonts pack from google fonts");
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access, @typescript-eslint/no-unsafe-assignment
const squirrel_fonts = fonts_config.fontSquirrel;
if (
- !is(
+ is(
squirrel_fonts,
predicates.record(
predicates.string,
predicates.array(predicates.string)
)
)
) {
- throw new Error("Inocorrect squirrelfonts file");
- }
-
- await mkdir(target_locreq.resolve("public/dist/fontsquirrel/"), {
- recursive: true,
- });
+ await mkdir(target_locreq.resolve("public/dist/fontsquirrel/"), {
+ recursive: true,
+ });
- const config_file = `{
+ const config_file = `{
"tmpDir": "/tmp/fonts",
"fontsDir": "/dist/fontsquirrel/fonts",
"cssDir": "/dist/fontsquirrel/css",
"cssFile": "fonts.css"
}`;
- await writeFile("public/fonsta.config.json", config_file);
+ await writeFile("public/fonsta.config.json", config_file);
+
+ await Promise.all(
+ Object.keys(squirrel_fonts).map((font) => {
+ if (squirrel_fonts[font].length) {
+ return execPromise(
+ `node ${path_to_fonsta} install ${font}:${squirrel_fonts[
+ font
+ ].join(",")}`,
+ {
+ cwd: target_locreq.resolve("public"),
+ }
+ );
+ } else {
+ return execPromise(
+ `node ${path_to_fonsta} install ${font}`,
+ {
+ cwd: target_locreq.resolve("public"),
+ }
+ );
+ }
+ })
+ );
+ }
- await Promise.all(
- Object.keys(squirrel_fonts).map((font) => {
- if (squirrel_fonts[font].length) {
- return execPromise(
- `node ${path_to_fonsta} install ${font}:${squirrel_fonts[
- font
- ].join(",")}`,
- {
- cwd: target_locreq.resolve("public"),
- }
- );
- } else {
- return execPromise(`node ${path_to_fonsta} install ${font}`, {
- cwd: target_locreq.resolve("public"),
- });
- }
- })
- );
const fonts_css_file_path = resolve(
target_locreq.resolve("public/dist/fonts"),
"fonts.css"
);
const content = await readFile(fonts_css_file_path, "utf-8");
await writeFile(
fonts_css_file_path,
content.replace(/@font-face {/g, "@font-face {\nfont-display: swap;")
);
await unlink("public/fonsta.config.json");
await rmdir("public/tmp");
- console.log("Downloaded new fonts pack from Font Squirrel");
+ console.info("Downloaded new fonts pack from Font Squirrel");
- console.log("Downloaded new fonts pack");
+ console.info("Downloaded new fonts pack");
}
diff --git a/src/make-env.ts b/src/make-env.ts
index 7cabec6..8a52c8e 100644
--- a/src/make-env.ts
+++ b/src/make-env.ts
@@ -1,15 +1,15 @@
import os from "os";
import { promises as fs } from "fs";
import _locreq from "locreq";
const target_locreq = _locreq(process.cwd());
export async function makeEnv(): Promise<void> {
const { uid, gid } = os.userInfo();
const content = `USER_ID=${uid}
GROUP_ID=${gid}
`;
const path = target_locreq.resolve(".env");
await fs.writeFile(path, content);
- console.log("wrote .env");
+ console.info("Wrote .env");
}
diff --git a/src/make-hidden-inputs.ts b/src/make-hidden-inputs.ts
index 3675f8b..198b7df 100644
--- a/src/make-hidden-inputs.ts
+++ b/src/make-hidden-inputs.ts
@@ -1,24 +1,25 @@
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import { FormField } from "./forms/fields/field.js";
import { FormDataValue } from "./forms/form-types.js";
import { attribute } from "./sanitize.js";
export function makeHiddenInputs(
ctx: Context,
fields: Record<string, FormField>,
values: Record<string, FormDataValue>,
fields_to_skip: string[]
): FlatTemplatable {
return tempstream`${Object.entries(fields)
.filter(([key]) => !fields_to_skip.includes(key))
.map(
- ([key, field]) => tempstream/* HTML */ `<input
- type="hidden"
- name="${key}"
- value="${field
- .getParsedValue(ctx, values)
- .then((r) => attribute(JSON.stringify(r.raw) || ""))}"
- />`
+ ([key, field]) =>
+ tempstream /* HTML */ `<input
+ type="hidden"
+ name="${key}"
+ value="${field
+ .getParsedValue(ctx, values)
+ .then((r) => attribute(JSON.stringify(r.raw) || ""))}"
+ />`
)}`;
}
diff --git a/src/mount.ts b/src/mount.ts
index 081ecc2..b6179bd 100644
--- a/src/mount.ts
+++ b/src/mount.ts
@@ -1,105 +1,100 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Router from "@koa/router";
import { FileManager } from "@sealcode/file-manager";
import Koa, { Context } from "koa";
import { Middlewares as SealiousMiddlewares } from "sealious";
import { Mountable } from "./page/mountable.js";
import { KoaResponsiveImageRouter } from "koa-responsive-image-router";
async function handleHtmlPromise(ctx: Context, next: Koa.Next) {
await next();
if (ctx.body instanceof Promise) {
- // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
ctx.body = await ctx.body;
}
ctx.set("content-type", "text/html;charset=utf-8");
}
export function mount(
router: Router,
url: string | { rawURL: string },
mountable: Mountable,
use_dummy_app = false,
file_manager: FileManager | undefined = use_dummy_app
? new FileManager("/tmp", "/uploaded_files")
: undefined
): void {
const raw_url = typeof url === "string" ? url : url.rawURL;
const imageRouter = new KoaResponsiveImageRouter({
staticPath: "/tmp",
thumbnailSize: 10,
cacheManagerResolutionThreshold: 10,
imageStoragePath: "/tmp",
smartCropStoragePath: "/tmp",
});
const fileManager = new FileManager("/tmp", "/uploaded_files");
const args = use_dummy_app
? [
async (ctx: Context, next: any) => {
// this dummy is a temporary solution it's ilustrating the ways that
// sealgen is coupled with sealious. Definitely room for improvement in this
// regard
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
ctx.$app = {
fileManager,
imageRouter,
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
Logger: new Proxy(
{},
{
get: (_target: any, prop: any) => {
if (prop === "info") {
- // eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {};
} else {
- // eslint-disable-next-line @typescript-eslint/no-empty-function
return () => {};
}
},
}
),
getString: (x: string) => x,
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
} as any;
// eslint-disable-next-line @typescript-eslint/no-unsafe-call
await next();
},
SealiousMiddlewares.parseBody(file_manager),
handleHtmlPromise,
- ]
+ ]
: [
SealiousMiddlewares.extractContext(),
SealiousMiddlewares.parseBody(file_manager),
handleHtmlPromise,
- ];
+ ];
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
router.use(raw_url, ...args);
mountable.init();
// to automatically add trailing slashes:
router.get(raw_url.slice(0, -1), async (ctx, next) => {
const url2 = ctx.URL;
if (!url2.pathname.endsWith("/")) {
url2.pathname += "/";
ctx.redirect(url2.pathname + url2.search);
}
await next();
});
router.use(raw_url, async (ctx, next) => {
ctx.set("content-type", "text/html;charset=utf-8");
const access_result = await mountable.canAccess(ctx);
if (!access_result.canAccess) {
ctx.status = 403;
ctx.body = access_result.message || "no access";
return;
}
await next();
});
mountable.mount(router, raw_url);
}
diff --git a/src/notifier.ts b/src/notifier.ts
index 18dcf91..a1722e1 100644
--- a/src/notifier.ts
+++ b/src/notifier.ts
@@ -1,115 +1,113 @@
import { WebSocketServer, WebSocket } from "ws";
const APP_DOWN_ERROR_MESSAGE = "App is currently down";
export const APP_BACK_ALIVE_SIGNAL = "app-back-alive";
const sleep = (time: number) =>
new Promise((resolve) => {
setTimeout(resolve, time);
});
async function get_status(
app_port: number
): Promise<{ started_at: number; status: string }> {
const r = await fetch(`http://127.0.0.1:${app_port}/status.json`);
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return (await r.json()) as { started_at: number; status: string };
}
async function wait_for_run_id_to_change(app_port: number) {
let first_timestamp: number;
try {
const { started_at } = await get_status(app_port);
first_timestamp = started_at;
- } catch (e) {
+ } catch (_e) {
await wait_for_app_to_be_stable(app_port);
return;
}
if (!first_timestamp) {
throw new Error(APP_DOWN_ERROR_MESSAGE);
}
- // eslint-disable-next-line no-constant-condition
while (true) {
// eslint-disable-next-line no-await-in-loop
const { started_at } = await get_status(app_port).catch(() => ({
started_at: first_timestamp,
}));
if (started_at !== first_timestamp) {
return;
}
// eslint-disable-next-line no-await-in-loop
await sleep(100);
}
}
async function wait_for_app_to_be_stable(app_port: number, n = 3) {
// eslint-disable-next-line no-console
console.log("Waiting for app to be stable....");
let counter = 0;
- // eslint-disable-next-line no-constant-condition
+
while (true) {
// eslint-disable-next-line no-await-in-loop
const { status } = await get_status(app_port).catch(() => ({
status: "down",
}));
if (status == "running") {
// eslint-disable-next-line no-console
console.log(counter);
counter++;
} else {
counter = 0;
}
if (counter == n) {
return;
}
// eslint-disable-next-line no-await-in-loop
await sleep(100);
}
}
let restart_promise: Promise<void> | null = null;
async function wait_for_app_restart(app_port: number) {
if (restart_promise) {
return restart_promise;
}
try {
restart_promise = wait_for_run_id_to_change(app_port);
await restart_promise;
} catch (e) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access
if (e.message !== APP_DOWN_ERROR_MESSAGE) {
throw e;
}
}
restart_promise = null;
await wait_for_app_to_be_stable(app_port);
}
export function make_notifier(port: number, app_port: number) {
const server = new WebSocketServer({
port,
});
let sockets: WebSocket[] = [];
server.on("connection", function (socket) {
sockets.push(socket);
// When a socket closes, or disconnects, remove it from the array.
socket.on("close", function () {
sockets = sockets.filter((s) => s !== socket);
});
});
- console.log(
- "build notifier listening on websocket at port " + port.toString()
+ console.info(
+ "🔔 Build notifier listening on websocket at port " + port.toString()
);
return function notify(message: string) {
sockets.forEach((s) => s.send(message));
void wait_for_app_restart(app_port).then(() => {
sockets.forEach((s) => s.send(APP_BACK_ALIVE_SIGNAL));
});
};
}
diff --git a/src/page/default-list-filters.ts b/src/page/default-list-filters.ts
index ac36781..b99d447 100644
--- a/src/page/default-list-filters.ts
+++ b/src/page/default-list-filters.ts
@@ -1,64 +1,65 @@
+/* eslint @typescript-eslint/no-explicit-any: "off" */
import type { Context } from "koa";
import { Field } from "sealious";
import { FlatTemplatable } from "tempstream";
export type ListFilterRender = (
value: string,
field: Field<any>,
ctx: Context
) => FlatTemplatable;
export type DefaultListFilter = {
render: ListFilterRender;
prepareValue?: (filter_value: unknown) => unknown;
};
export const BooleanListFilter = {
render: (value: string, field: Field<any>) => {
return /* HTML */ `<label>
${field.name}
<select name="filter[${field.name}]" autocomplete="off">
<option value="true" ${value == "true" ? "selected" : ""}>
True
</option>
<option value="false" ${value == "false" ? "selected" : ""}>
False
</option>
<option
value=""
${value == "null" ||
value == "" ||
value == "undefined" ||
value == undefined
? "selected"
: ""}
>
-
</option>
</select>
</label>`;
},
};
export const SimpleTextFilter = {
render: (value: string, field: Field<any>) => {
return /* HTML */ `<label>
${field.name}
<input
type="text"
name="filter[${field.name}]"
autocomplete="off"
${value ? `value="${value}"` : value}
/>
</label>`;
},
prepareValue: (value: string) => {
return { regex: `.*${value}.*` };
},
};
export const DefaultListFilters = {
boolean: BooleanListFilter,
text: SimpleTextFilter,
fallback: SimpleTextFilter,
} as Record<"boolean" | "text" | "fallback", DefaultListFilter>;
diff --git a/src/page/list.ts b/src/page/list.ts
index fe16d82..524d615 100644
--- a/src/page/list.ts
+++ b/src/page/list.ts
@@ -1,291 +1,289 @@
import { Context } from "koa";
import { Templatable, tempstream, FlatTemplatable } from "tempstream";
import { Page } from "./page.js";
import { ShapeToType } from "@sealcode/ts-predicates";
import { FormControl } from "../forms/controls/controls.js";
import { FormField } from "../forms/fields/field.js";
import { naturalNumbers, UrlWithNewParams } from "../utils/utils.js";
import { makeHiddenInputs } from "../make-hidden-inputs.js";
import qs from "qs";
import { NumberField } from "../forms/fields/number.js";
import { TextBasedSimpleField } from "../forms/fields/simple-form-field.js";
import { FormDataValue } from "../forms/form-types.js";
export const BasePagePropsShape = <const>{};
export type BasePageProps = ShapeToType<typeof BasePagePropsShape>;
export const DEFAULT_ITEMS_PER_PAGE = 12;
export const BaseListPageFields = <const>{
page: new NumberField(false, 1),
itemsPerPage: new NumberField(false, DEFAULT_ITEMS_PER_PAGE),
sort: new TextBasedSimpleField(false),
};
export type ListSort = { field: string; order: "asc" | "desc" };
const SORT_SEPARATOR = ":";
function decodeSort(s: unknown): ListSort | null {
if (typeof s !== "string" || !s.includes(SORT_SEPARATOR)) {
return null;
}
let order = s.split(SORT_SEPARATOR)[1];
const field = s.split(SORT_SEPARATOR)[0];
if (order !== "asc" && order !== "desc") {
order = "asc";
return {
field,
order: order as "asc",
};
} else {
return { field, order };
}
}
function encodeSort(field: string, order: "asc" | "desc"): string {
return [field, order].join(SORT_SEPARATOR);
}
export abstract class ListPage<
ItemType,
- F extends typeof BaseListPageFields
+ F extends typeof BaseListPageFields,
> extends Page<F> {
abstract getItems(
ctx: Context,
page: number,
itemsPerPage: number | null,
values: Record<string, FormDataValue>
): Promise<ItemType[]>;
abstract getTotalPages(
ctx: Context,
itemsPerPage: number,
values: Record<string, FormDataValue>
): Promise<number>;
abstract renderItem(
ctx: Context,
item: ItemType,
index: number
): Promise<FlatTemplatable>;
filterFields: Record<string, FormField> = {};
filterControls: FormControl[] = [];
init(): void {
super.init();
for (const [, field] of Object.entries(this.filterFields)) {
void field.init();
}
}
renderListContainer(_: Context, content: Templatable): FlatTemplatable {
return tempstream`<div>${content}</div>`;
}
async getPaginationConfig(ctx: Context) {
const values = await this.extractRawValues(ctx);
let { parsed: page } = await this.fields.page.getParsedValue(
ctx,
values
);
if (!page) {
page = 1;
}
const { parsed: itemsPerPage } =
await this.fields.itemsPerPage.getParsedValue(ctx, values);
return { page, itemsPerPage };
}
async renderItems(
ctx: Context,
values?: Record<string, FormDataValue>,
items?: ItemType[]
): Promise<FlatTemplatable> {
if (!values) {
values = await this.extractRawValues(ctx);
}
const { itemsPerPage, page } = await this.getPaginationConfig(ctx);
const items_promise = this.getItems(ctx, page, itemsPerPage, values);
return tempstream`${(items
? Promise.resolve(items)
: items_promise
).then((items) =>
items.map((item, index) => this.renderItem(ctx, item, index))
)}`;
}
async renderPagination(
ctx: Context,
values: Record<string, FormDataValue>
): Promise<FlatTemplatable> {
const { itemsPerPage, page } = await this.getPaginationConfig(ctx);
const totalIems = await this.getTotalPages(
ctx,
itemsPerPage || DEFAULT_ITEMS_PER_PAGE,
values
);
- return tempstream/* HTML */ `<div class="list-pagination">
+ return tempstream /* HTML */ `<div class="list-pagination">
<div class="list-pagination__left">
${page > 1
? this.renderPageButton(ctx, 1, "Pierwsza strona")
: ""}
${page > 1
? this.renderPageButton(ctx, page - 1, "Poprzednia strona")
: ""}
</div>
<div class="list-pagination__center">
<select
title="choose page"
onchange="if (this.value) Turbo.visit(this.value)"
>
${Array.from(naturalNumbers(1, totalIems)).map(
- (n) => /* HTML */ `<option
- value="${UrlWithNewParams(
- ctx,
- //eslint-disable-next-line @typescript-eslint/consistent-type-assertions
- this.propsParser.overwriteProp(ctx, {
- page: n,
- } as Partial<Record<string, unknown>>)
- )}"
- ${page === n ? "selected" : ""}
- >
- ${n}
- </option>`
+ (n) =>
+ /* HTML */ `<option
+ value="${UrlWithNewParams(
+ ctx,
+ this.propsParser.overwriteProp(ctx, {
+ page: n,
+ } as Partial<Record<string, unknown>>)
+ )}"
+ ${page === n ? "selected" : ""}
+ >
+ ${n}
+ </option>`
)}
</select>
</div>
<div class="list-pagination__right">
${page < totalIems
? this.renderPageButton(ctx, page + 1, "Następna strona")
: ""}
${page < totalIems
? this.renderPageButton(ctx, totalIems, "Ostatnia strona")
: ""}
</div>
</div>`;
}
private renderPageButton(ctx: Context, page: number, text: string) {
return /* HTML */ `<a
href="${UrlWithNewParams(
ctx,
- //eslint-disable-next-line @typescript-eslint/consistent-type-assertions
this.propsParser.overwriteProp(ctx, {
page,
} as Partial<Record<string, unknown>>)
)}"
>${text}</a
>`;
}
async getFilterValues(ctx: Context): Promise<Record<string, unknown>> {
const filter = {} as Record<string, unknown>;
const raw_values = await this.extractRawValues(ctx);
for (const [fieldname, field] of Object.entries(this.filterFields)) {
// eslint-disable-next-line no-await-in-loop
const { parsed } = await field.getParsedValue(ctx, raw_values);
filter[fieldname] = field.mapToFilter(parsed);
}
return filter;
}
async getSort(ctx: Context): Promise<ListSort | null> {
const { sort } = await this.extractRawValues(ctx);
const decoded = decodeSort(sort);
if (decoded === null) {
return this.getDefaultSort(ctx);
} else {
return decoded;
}
}
makeSortLink(
ctx: Context,
field: string,
order: "asc" | "desc" | null
): string {
const url = new URL(ctx.url, "https://example.com");
const params = qs.parse(url.search.slice(1));
if (order === null) {
delete params.sort;
} else {
params.sort = encodeSort(field, order);
}
url.search = qs.stringify(params);
return url.pathname + url.search;
}
async renderFilters(ctx: Context): Promise<FlatTemplatable> {
const values = await this.extractRawValues(ctx);
- return tempstream/* HTML */ `<form method="GET">
+ return tempstream /* HTML */ `<form method="GET">
${makeHiddenInputs(ctx, this.fields, values, [
"page",
...Object.values(this.filterFields).map((f) => f.name),
])}
${this.filterControls.map((control) => {
- // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return control.render(
this.makeFormControlContext(
ctx,
{
raw_values: values,
messages: [],
field_messages: {},
},
false
)
);
})}
</form>`;
}
async renderHeading(
ctx: Context,
field: string,
label = field
): Promise<FlatTemplatable> {
const current_sort = await this.getSort(ctx);
const current_order =
current_sort?.field == field ? current_sort.order : null;
const order =
current_order === "asc" // cycles the sort order: null → "asc" → "desc" → null → ...
? "desc"
: current_order === null
- ? "asc"
- : null;
+ ? "asc"
+ : null;
return /* HTML */ `<th data-field="${field}">
<a href="${this.makeSortLink(ctx, field, order)}"
>${label}
${(current_order && (current_order == "asc" ? "↑" : "↓")) ||
""}</a
>
</th>`;
}
getDefaultSort(_: Context): ListSort | null {
return null;
}
renderTableHead(
ctx: Context,
fields: { field: string; label?: string }[]
): FlatTemplatable {
- return tempstream/* HTML */ `<thead>
+ return tempstream /* HTML */ `<thead>
<tr>
${fields.map(({ label, field }) =>
this.renderHeading(ctx, field, label)
)}
</tr>
</thead>`;
}
async render(ctx: Context): Promise<FlatTemplatable> {
const values = await this.extractRawValues(ctx);
return tempstream`${this.renderPagination(ctx, values)}
${this.renderFilters(ctx)}
${this.renderListContainer(ctx, this.renderItems(ctx, values))}`;
}
}
diff --git a/src/page/mountable-with-fields.ts b/src/page/mountable-with-fields.ts
index fa10eb5..d5ca91a 100644
--- a/src/page/mountable-with-fields.ts
+++ b/src/page/mountable-with-fields.ts
@@ -1,187 +1,187 @@
import { ShapeToType } from "@sealcode/ts-predicates";
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import {
FieldMessages,
FormControl,
FormControlContext,
} from "../forms/controls/form-control.js";
import type { FieldsToShape, FormField } from "../forms/fields/field.js";
import type {
FormDataValue,
FormMessage,
FormData,
} from "../forms/form-types.js";
import { Mountable } from "./mountable.js";
export type PageErrorMessage = { type: "access" | "internal"; message: string };
// eslint-disable-next-line @typescript-eslint/no-explicit-any
export type Fields = Record<string, FormField<boolean, any>>;
type Resolved<T> = T extends Promise<infer X> ? X : never;
type ParsedValue<T extends FormField> = Resolved<
ReturnType<T["getParsedValue"]>
>["parsed"];
export abstract class MountableWithFields<
- F extends Fields = Fields
+ F extends Fields = Fields,
> extends Mountable {
fields: F;
field_names_prefix = ""; // useful for multiform, where many forms are merged into one and field assignment is made using the prefix
form_id = ""; // all fields within this mountable will be tied to form of this id
abstract controls: FormControl[];
constructor() {
super();
if (!this.fields) this.fields = {} as F;
}
init(): void {
for (const [field_name, field] of Object.entries(this.fields)) {
void field.init();
field.setName(field_name);
}
}
makeFormControlContext(
ctx: Context,
data: FormData,
validate: boolean,
field_name_prefix = this.field_names_prefix,
form_id = this.form_id
) {
return new FormControlContext(
ctx,
data,
data.messages,
field_name_prefix,
form_id,
validate
);
}
// this one is meant to be overwritten
async validateValues(
_ctx: Context,
_data: Record<string, FormDataValue>
): Promise<{ valid: boolean; error: string }> {
return {
valid: true,
error: "",
};
}
async getInitialValues(
_ctx: Context
): Promise<Record<string, FormDataValue>> {
return {};
}
async validate(
ctx: Context,
values: Record<string, FormDataValue>
): Promise<{
valid: boolean;
field_errors: FieldMessages;
form_messages: FormMessage[];
}> {
const field_errors = {} as FieldMessages;
let valid = true;
const form_messages = [] as FormMessage[];
await Promise.all(
Object.keys(this.fields).map(async (key: keyof F) => {
const field = this.fields[key];
const { valid: fieldvalid, message: fieldmessage } =
await field.getParsedValue(ctx, values, true);
if (!fieldvalid) {
valid = false;
field_errors[field.name] = {
type: "error",
message: fieldmessage,
};
}
})
);
const formValidationResult = await this.validateValues(ctx, values);
if (!formValidationResult.valid) {
form_messages.push({
type: "error",
text: formValidationResult.error,
});
valid = false;
}
return { valid, field_errors, form_messages };
}
public renderControls(fctx: FormControlContext): FlatTemplatable {
- return tempstream/* HTML */ `${this.controls.map((control) =>
+ return tempstream /* HTML */ `${this.controls.map((control) =>
control.render(fctx)
)}`;
}
async renderError(
_: Context,
error: PageErrorMessage
): Promise<FlatTemplatable> {
return error.message;
}
public renderMessages(
_: Context,
data: FormData<keyof Fields>
): FlatTemplatable {
- return tempstream/* HTML */ `<div class="form-messages">
+ return tempstream /* HTML */ `<div class="form-messages">
${data.messages.map(
(message) =>
`<div class="form-message form-message--${message.type}">${message.text}</div>`
)}
</div>`;
}
abstract extractRawValues(
ctx: Context
): Promise<Record<string, FormDataValue>>;
async getParsedValues(ctx: Context): Promise<{
[field in keyof F]: F[field] extends FormField<true>
? Exclude<ParsedValue<F[field]>, null>
: ParsedValue<F[field]>;
}> {
const raw_values = await this.extractRawValues(ctx);
const result: Record<string, unknown> = {};
const promises = Object.entries(this.fields).map(
async ([key, field]) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
const { parsed } = await field.getParsedValue(
ctx,
raw_values,
false
);
result[key] = parsed;
}
);
await Promise.all(promises);
// TODO: remove this any. I don't have the strenght to deal with it now.
// eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-return
return result as any;
}
async getDatabaseValues(
ctx: Context
): Promise<ShapeToType<FieldsToShape<F>>> {
const raw_values = await this.extractRawValues(ctx);
const result: Record<string, unknown> = {};
const promises = Object.entries(this.fields).map(
async ([key, field]) => {
const db_value = await field.getDatabaseValue(ctx, raw_values);
if (db_value !== undefined) {
result[key] = db_value;
}
}
);
await Promise.all(promises);
return result as ShapeToType<FieldsToShape<F>>;
}
}
diff --git a/src/page/mountable.ts b/src/page/mountable.ts
index e010758..9ab9903 100644
--- a/src/page/mountable.ts
+++ b/src/page/mountable.ts
@@ -1,13 +1,12 @@
import Router from "@koa/router";
import { Context } from "koa";
export abstract class Mountable {
- // eslint-disable-next-line @typescript-eslint/no-empty-function
init(): void {}
abstract mount(router: Router, path: string): void;
abstract canAccess(
ctx: Context
): Promise<{ canAccess: boolean; message: string }>;
}
diff --git a/src/page/page.ts b/src/page/page.ts
index ed32101..508b193 100644
--- a/src/page/page.ts
+++ b/src/page/page.ts
@@ -1,45 +1,44 @@
import Router from "@koa/router";
import { Context } from "koa";
import { FlatTemplatable, tempstream } from "tempstream";
import type { FormDataValue } from "../forms/form-types.js";
import {
Fields,
MountableWithFields,
PageErrorMessage,
} from "./mountable-with-fields.js";
import { AllQueryParams, PagePropsParser } from "./props-parser.js";
export abstract class Page<
- F extends Fields = Record<string, never>
+ F extends Fields = Record<string, never>,
> extends MountableWithFields<F> {
propsParser: PagePropsParser<Record<keyof Fields, unknown>> =
new AllQueryParams();
controls = [];
mount(router: Router, path: string): void {
router.get(path, async (ctx) => {
ctx.body = await this.render(ctx);
});
}
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
async renderError(
_: Context,
error: PageErrorMessage
): Promise<FlatTemplatable> {
- return tempstream/* HTML */ `<div>${error.message}</div>`;
+ return tempstream /* HTML */ `<div>${error.message}</div>`;
}
public abstract render(ctx: Context): Promise<FlatTemplatable>;
async extractRawValues(
ctx: Context
): Promise<Record<string, FormDataValue>> {
return this.propsParser.decode(ctx) || {};
}
}
diff --git a/src/page/props-parser.ts b/src/page/props-parser.ts
index 5a9fcc8..39b4408 100644
--- a/src/page/props-parser.ts
+++ b/src/page/props-parser.ts
@@ -1,38 +1,38 @@
import { Context } from "koa";
import merge from "merge";
import { FormDataValue } from "../forms/form-types.js";
import type { BasePageProps } from "./list.js";
export type EncodedProps = Record<string, unknown>;
// page props parser is only tasked with getting the raw props from *somewhere*
// and being able to put new values back to that somewhere. Parsing to numbers
// or any other exotic types is done by fields logic.
export abstract class PagePropsParser<PropsType> {
abstract decode(ctx: Context): Record<string, FormDataValue>;
abstract encode(props: Record<string, FormData>): EncodedProps;
abstract getHTMLInputName(prop_name: string): string;
overwriteProp(ctx: Context, new_props: Partial<PropsType>): EncodedProps {
const result = {};
merge.recursive(result, this.decode(ctx), new_props);
return result;
}
}
export class AllQueryParams<
- PropsType extends BasePageProps
+ PropsType extends BasePageProps,
> extends PagePropsParser<PropsType> {
decode(ctx: Context): Record<string, FormDataValue> {
return ctx.query;
}
encode(props: PropsType): Record<string, unknown> {
return props;
}
getHTMLInputName(prop_name: string): string {
return prop_name;
}
}
diff --git a/src/page/sealious-list.ts b/src/page/sealious-list.ts
index a5f0925..f7c7316 100644
--- a/src/page/sealious-list.ts
+++ b/src/page/sealious-list.ts
@@ -1,104 +1,104 @@
import { Context } from "koa";
import {
BaseListPageFields,
DEFAULT_ITEMS_PER_PAGE,
ListPage,
} from "./list.js";
import {
Collection,
CollectionItem,
ItemList,
Context as SealiousContext,
CollectionInput,
} from "sealious";
import { FlatTemplatable, Templatable, tempstream } from "tempstream";
import { peopleWhoCan } from "./access-control.js";
import qs from "qs";
import { is, predicates } from "@sealcode/ts-predicates";
export abstract class SealiousItemListPage<
C extends Collection,
- F extends typeof BaseListPageFields
+ F extends typeof BaseListPageFields,
> extends ListPage<CollectionItem<C>, F> {
constructor(public collection: C) {
super();
}
async getContextForList(ctx: Context): Promise<SealiousContext> {
return ctx.$context;
}
async getTotalPages(ctx: Context, itemsPerPage: number): Promise<number> {
const query = this.collection.list(await this.getContextForList(ctx));
await this.addFilter(ctx, query);
const { items } = await query.fetch();
return Math.ceil(items.length / itemsPerPage);
}
protected async addFilter(ctx: Context, list: ItemList<C>): Promise<void> {
const filters = await this.getFilterValues(ctx);
for (const key in filters) {
if (filters[key] === undefined || filters[key] == "") {
delete filters[key];
}
}
if (Object.keys(filters).length) {
list.filter(filters as Partial<CollectionInput<C>>);
}
}
async makeQuery(ctx: Context): Promise<ItemList<C>> {
const query = this.collection.list(await this.getContextForList(ctx));
const sort = await this.getSort(ctx);
if (sort) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument, @typescript-eslint/no-explicit-any
query.sort({ [sort.field]: sort.order } as any);
}
return query;
}
async getItems(
ctx: Context,
page: number,
itemsPerPage: number | null
): Promise<CollectionItem<C>[]> {
const query = await this.makeQuery(ctx);
await this.addFilter(ctx, query);
const { items } = await query
.paginate({ items: itemsPerPage || DEFAULT_ITEMS_PER_PAGE, page })
.fetch();
return items;
}
async getFilterValues(ctx: Context) {
const query_params = qs.parse(ctx.search.slice(1));
const _filter_values = query_params?.filter || {};
const filter_values: Record<string, string | undefined> = is(
_filter_values,
predicates.record(predicates.string, predicates.string)
)
? _filter_values
: {};
for (const key in filter_values) {
if (filter_values[key] == "") {
delete filter_values[key];
}
}
return filter_values;
}
renderListContainer(_: Context, content: Templatable): FlatTemplatable {
return tempstream`<div class="sealgen-sealious-list-container">${content}</div>`;
}
async renderItem(
_: Context,
item: CollectionItem<C>,
_index: number
): Promise<FlatTemplatable> {
return `<div>${item.id}</div>`;
}
canAccess = peopleWhoCan("list", this.collection);
}
diff --git a/src/page/stateful-page.ts b/src/page/stateful-page.ts
index 9fc49c7..2e03832 100644
--- a/src/page/stateful-page.ts
+++ b/src/page/stateful-page.ts
@@ -1,330 +1,326 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import Router from "@koa/router";
import { predicates, hasShape, is } from "@sealcode/ts-predicates";
import deepmerge, { ArrayMergeOptions } from "deepmerge";
import { Context } from "koa";
import { Templatable, tempstream } from "tempstream";
import { from_base64, to_base64 } from "../utils/base64.js";
import { Mountable } from "./mountable.js";
import { isPlainObject } from "is-what";
export type StatefulPageActionDescription<ActionName> =
| {
action: ActionName;
label?: string;
content?: string;
disabled?: boolean;
}
| ActionName;
export type StateAndMetadata<State, Actions> =
| {
state: State;
inputs: Record<string, string>;
action: keyof Actions;
action_args: string;
}
| {
state: State;
inputs: Record<string, string>;
action: null;
action_args: null;
$: Record<string, unknown>;
};
export type StatefulPageActionArgument<
State extends Record<string, unknown>,
- Args extends unknown[] = unknown[]
+ Args extends unknown[] = unknown[],
> = {
ctx: Context;
state: State;
inputs: Record<string, string>;
args: Args;
page: StatefulPage<any, any>;
};
export type StatefulPageAction<
State extends Record<string, unknown>,
- Args extends unknown[] = unknown[]
+ Args extends unknown[] = unknown[],
> = (obj: StatefulPageActionArgument<State, Args>) => State | Promise<State>;
-export type ExtractStatefulPageActionArgs<X> = X extends StatefulPageAction<
- any,
- infer Args
->
- ? Args
- : never;
+export type ExtractStatefulPageActionArgs<X> =
+ X extends StatefulPageAction<any, infer Args> ? Args : never;
export abstract class StatefulPage<
State extends Record<string, unknown>,
- Actions extends Record<string, StatefulPageAction<State>>
+ Actions extends Record<string, StatefulPageAction<State>>,
> extends Mountable {
abstract actions: Actions;
abstract getInitialState(ctx: Context): State | Promise<State>;
abstract render(
ctx: Context,
state: State,
inputs: Record<string, string>
): Templatable | Promise<Templatable>;
async canAccess(
_ctx: Context
): Promise<{ canAccess: boolean; message: string }> {
return <const>{ canAccess: true, message: "" };
}
constructor() {
super();
const original_render = this.render.bind(this) as typeof this.render;
this.render = async (
ctx: Context,
state: State,
inputs: Record<string, string>
) => {
return this.wrapInLayout(
ctx,
await this.wrapInForm(
ctx,
state,
await original_render(ctx, state, inputs)
),
state
);
};
}
abstract wrapInLayout(
ctx: Context,
content: Templatable,
state: State
): Templatable;
async wrapInForm(
context: Context,
state: State,
content: Templatable
): Promise<Templatable> {
- return tempstream/* HTML */ `<form
+ return tempstream /* HTML */ `<form
action="./"
method="POST"
enctype="multipart/form-data"
>
<input
name="state"
type="hidden"
value="${to_base64(await this.serializeState(context, state))}"
/>
${content}
</form>`;
}
extractActionAndLabel<ActionName extends keyof Actions>(
action_description: StatefulPageActionDescription<ActionName>
): { action: string; label: string; content: string; disabled: boolean } {
let label, action, content: string;
let disabled: boolean;
if (is(action_description, predicates.object)) {
action = action_description.action.toString();
label = action_description.label || action;
content = action_description.content || label;
disabled = action_description.disabled || false;
} else {
action = action_description.toString();
label = action;
content = label;
disabled = false;
}
return { action, label, content, disabled };
}
makeActionURL<ActionName extends keyof Actions>(
action_description: StatefulPageActionDescription<ActionName>,
...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
) {
const { action } = this.extractActionAndLabel(action_description);
return `./?action=${action}&action_args=${encodeURIComponent(
// encoding as URI Component because sometimes it can contain a "+" which is treated as a space
to_base64(JSON.stringify(args))
)}`;
}
makeActionButton<ActionName extends keyof Actions>(
_state: State,
action_description: StatefulPageActionDescription<ActionName>,
...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
) {
const { label, content, disabled } =
this.extractActionAndLabel(action_description);
return /* HTML */ `
<button
type="submit"
formaction="${this.makeActionURL(action_description, ...args)}"
title="${label}"
${disabled ? "disabled" : ""}
>
${content}
</button>
`;
}
makeActionCallback<ActionName extends keyof Actions>(
action_description:
| {
action: ActionName;
label?: string;
}
| ActionName,
...args: ExtractStatefulPageActionArgs<Actions[ActionName]>
) {
return `(()=>{const form = this.closest('form'); form.action='${this.makeActionURL(
action_description,
...args
)}'; form.requestSubmit()})()`;
}
rerender() {
return "this.closest('form').requestSubmit()";
}
async preprocessState(values: State): Promise<State> {
return values;
}
async preprocessOverrides(
_context: Context,
_state: State,
values: Record<string, unknown>
): Promise<Record<string, unknown>> {
return values;
}
async serializeState(_context: Context, state: State): Promise<string> {
return JSON.stringify(state);
}
async deserializeState(_context: Context, s: string): Promise<State> {
const deserialized = JSON.parse(s) as unknown;
return deserialized as State;
}
async extractState(
ctx: Context
): Promise<StateAndMetadata<State, Actions>> {
if (
!hasShape(
{
action: predicates.maybe(predicates.string),
state: predicates.string,
action_args: predicates.maybe(predicates.string),
$: predicates.maybe(predicates.object),
},
ctx.$body
)
) {
console.error("Wrong data: ", ctx.$body);
throw new Error("wrong formdata shape");
}
const inputs = Object.fromEntries(
Object.entries(ctx.$body).filter(
([key]) => !["action", "state", "args", "$"].includes(key)
)
) as Record<string, string>;
// the "$" key is parsed as dot notation and overrides the state
const original_state_string = ctx.$body.state;
const original_state = await this.deserializeState(
ctx,
typeof original_state_string == "string"
? from_base64(original_state_string)
: "{}"
);
const $body = ctx.$body;
let state_overrides = $body.$ || {};
state_overrides = await this.preprocessOverrides(
ctx,
original_state,
state_overrides
);
let modified_state = deepmerge(original_state, state_overrides, {
isMergeableObject: (v) => isPlainObject(v) || Array.isArray(v),
arrayMerge: (
target: any[],
source: any[],
options: ArrayMergeOptions
) => {
// https://github.com/TehShrike/deepmerge?tab=readme-ov-file#arraymerge-example-combine-arrays
const destination = target.slice();
/* eslint-disable @typescript-eslint/no-unsafe-argument */
source.forEach((item, index) => {
if (typeof destination[index] === "undefined") {
destination[index] =
options.cloneUnlessOtherwiseSpecified(
item,
options
);
} else if (options.isMergeableObject(item)) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
destination[index] = deepmerge(
target[index],
item,
options
);
} else if (target.indexOf(item) === -1) {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
destination[index] = item;
}
});
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return destination;
},
}) as State;
// giving extending classes a change to modify the state before furhter processing
modified_state = await this.preprocessState(modified_state);
if (ctx.$body.action && ctx.$body.action_args) {
return {
state: modified_state,
action: ctx.$body.action,
inputs,
action_args: ctx.$body.action_args,
};
} else {
return {
state: modified_state,
action: null,
inputs,
action_args: null,
$: ctx.$body.$ || {},
};
}
}
mount(router: Router, path: string) {
router.get(path, async (ctx) => {
ctx.body = this.render(ctx, await this.getInitialState(ctx), {});
});
router.post(path, async (ctx) => {
const { action, state, inputs, action_args } =
await this.extractState(ctx);
if (action) {
const new_state = await this.actions[action]({
ctx,
state,
inputs,
args: JSON.parse(
from_base64(action_args as string)
) as unknown[],
page: this,
});
ctx.body = this.render(ctx, new_state, inputs);
} else {
ctx.body = this.render(ctx, state, inputs);
}
ctx.status = 422;
});
}
}
diff --git a/src/register-external.ts b/src/register-external.ts
index 06a357a..64ed8fb 100644
--- a/src/register-external.ts
+++ b/src/register-external.ts
@@ -1,148 +1,148 @@
import { promises as fs, existsSync, readFileSync } from "fs";
import { resolve, dirname } from "path";
import { formatWithPrettier } from "./utils/prettier.js";
interface PackageJson {
sealgen?: {
controllerDirs?: string[];
styleDirs?: string[];
[key: string]: unknown;
};
[key: string]: unknown;
}
function findParentProjectWithSealgen(): string {
let currentDir = process.cwd();
while (currentDir !== dirname(currentDir)) {
const packageJsonPath = resolve(currentDir, "package.json");
if (existsSync(packageJsonPath)) {
try {
const packageJsonContent = readFileSync(
packageJsonPath,
"utf-8"
);
const packageJson = JSON.parse(
packageJsonContent
) as PackageJson;
// Check if this package.json has a sealgen configuration
if (packageJson.sealgen) {
return currentDir;
}
} catch (error) {
// If we can't read or parse the package.json, continue to parent
console.warn(
`Warning: Could not read package.json at ${packageJsonPath}:`,
error
);
}
}
currentDir = dirname(currentDir);
}
throw new Error(
"Could not find a parent project with sealgen configuration"
);
}
async function updatePackageJson(
projectDir: string,
moduleName: string,
subdirectory: string,
type: "controllerDirs" | "styleDirs"
): Promise<void> {
const packageJsonPath = resolve(projectDir, "package.json");
const packageJsonContent = await fs.readFile(packageJsonPath, "utf-8");
const packageJson = JSON.parse(packageJsonContent) as PackageJson;
// Initialize sealgen configuration if it doesn't exist
if (!packageJson.sealgen) {
packageJson.sealgen = {};
}
// Initialize the specific array if it doesn't exist
if (!packageJson.sealgen[type]) {
packageJson.sealgen[type] = [];
}
const pathToAdd = `node_modules/${moduleName}/${subdirectory}`;
const existingPaths = packageJson.sealgen[type];
// Check if the path is already present
if (existingPaths.includes(pathToAdd)) {
- console.log(`${type} already contains: ${pathToAdd}`);
+ console.warn(`${type} already contains: ${pathToAdd}`);
return;
}
// Add the new path
existingPaths.push(pathToAdd);
// Write back the updated package.json with proper formatting
const updatedContent = await formatWithPrettier(
JSON.stringify(packageJson, null, 2),
"json"
);
await fs.writeFile(packageJsonPath, updatedContent);
- console.log(`Added ${pathToAdd} to ${type} in ${packageJsonPath}`);
+ console.info(`Added ${pathToAdd} to ${type} in ${packageJsonPath}`);
}
export async function registerExternalControllers(
- args: Record<string, string | boolean>
+ _args: Record<string, string | boolean>
): Promise<void> {
// Extract positional arguments from process.argv since yargs doesn't handle them for these commands
const moduleName = process.argv.at(3);
const subdirectory = process.argv.at(4);
if (!moduleName || !subdirectory) {
console.error(
"Usage: npx sealgen register-external-controllers <module-name> <subdirectory>"
);
process.exit(1);
}
try {
const projectDir = findParentProjectWithSealgen();
await updatePackageJson(
projectDir,
moduleName,
subdirectory,
"controllerDirs"
);
} catch (error) {
console.error("Error:", error instanceof Error ? error.message : error);
process.exit(1);
}
}
export async function registerExternalStyles(
- args: Record<string, string | boolean>
+ _args: Record<string, string | boolean>
): Promise<void> {
// Extract positional arguments from process.argv since yargs doesn't handle them for these commands
const moduleName = process.argv.at(3);
const subdirectory = process.argv.at(4);
if (!moduleName || !subdirectory) {
console.error(
"Usage: npx sealgen register-external-styles <module-name> <subdirectory>"
);
process.exit(1);
}
try {
const projectDir = findParentProjectWithSealgen();
await updatePackageJson(
projectDir,
moduleName,
subdirectory,
"styleDirs"
);
} catch (error) {
console.error("Error:", error instanceof Error ? error.message : error);
process.exit(1);
}
}
diff --git a/src/templates/form.ts b/src/templates/form.ts
index 7a4aa9f..3d45792 100644
--- a/src/templates/form.ts
+++ b/src/templates/form.ts
@@ -1,87 +1,86 @@
import { formatWithPrettier } from "../utils/prettier.js";
const defaults = {
postimport: `
import { Fields } from "@sealcode/sealgen";
import type {FormDataValue} from "@sealcode/sealgen";`,
fields: `
password: new Fields.Password(true),`,
controls: `
new Controls.SimpleInput(fields.password, {
label: "Password:",
type: "password",
}),`,
validate_method: `async validateValues(
ctx: Context,
data: Record<string, FormDataValue>
): Promise<{ valid: boolean; error: string }> {
// just a silly example, please remove this with better logic
const { parsed: email } = await this.fields.email.getParsedValue(ctx, data);
const { parsed: password } = await this.fields.password.getParsedValue(ctx, data);
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
if ((password || "").length > ((email as string) || "").length) {
return { valid: false, error: "Password cannot be longer than email" };
} else {
return { valid: true, error: "" };
}
}`,
onsubmit: ` async onSubmit() {
//noop
return;
}`,
can_access: ` // eslint-disable-next-line @typescript-eslint/no-unused-vars
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}`,
render: `async render(ctx: Context, data: FormData, show_field_errors: boolean) {
return html({ctx, title: "Form", description: "", css_clumps: ["admin-forms"], body: await super.render(ctx, data, show_field_errors)});
}`,
get_initial_values: "",
other_methods: "",
success_message: "Success!",
};
export async function formTemplate(
action_name: string,
- newfilefullpath: string,
- _params: Partial<typeof defaults> & { success_message: string } = defaults
+ _params: Partial<typeof defaults> = defaults
): Promise<string> {
const params = { ...defaults, ..._params };
const content = `import type { Context } from "koa";
import type { FormData } from "@sealcode/sealgen";
import { Form, Controls, fieldsToShape } from "@sealcode/sealgen";
import html from "src/back/html.js";
${params.postimport}
export const actionName = "${action_name}";
const fields = {
${params.fields}
};
Form.initFieldNames(fields);
export const ${action_name}Shape = fieldsToShape(fields);
export default new (class ${action_name}Form extends Form<typeof fields, void> {
defaultSuccessMessage = "Formularz wypełniony poprawnie";
fields = fields;
controls = [
${params.controls}
];
${params.other_methods}
${params.get_initial_values}
${params.onsubmit}
${params.can_access}
${params.render}
})();
`;
return formatWithPrettier(content);
}
diff --git a/src/templates/jdd-component.ts b/src/templates/jdd-component.ts
index 82e531c..1583fad 100644
--- a/src/templates/jdd-component.ts
+++ b/src/templates/jdd-component.ts
@@ -1,34 +1,34 @@
import { toKebabCase, toPascalCase } from "js-convert-case";
-export function jddComponentTemplate(component_name: string) {
+export async function jddComponentTemplate(component_name: string) {
return `import { TempstreamJSX } from "tempstream";
import type { ComponentToHTMLArgs } from "@sealcode/jdd";
import { Component, ComponentArguments } from "@sealcode/jdd";
const component_arguments = {
title: new ComponentArguments.ShortText(),
content: new ComponentArguments.Markdown(),
} as const;
export class ${toPascalCase(
component_name
)} extends Component<typeof component_arguments> {
getArguments() {
return component_arguments;
}
async toHTML({
args: { title, content},
classes,
jdd_context: { render_markdown, render_image, language },
}: ComponentToHTMLArgs<typeof component_arguments>): Promise<string> {
return (
<div class={["${toKebabCase(component_name)}", ...classes]}>
<h2>{title} • ${toPascalCase(component_name)} </h2>
<div>{render_markdown(language, content)}</div>
</div>
);
}
}
`;
}
diff --git a/src/templates/jdd-editor.ts b/src/templates/jdd-editor.ts
index a224b82..71aea2b 100644
--- a/src/templates/jdd-editor.ts
+++ b/src/templates/jdd-editor.ts
@@ -1,89 +1,87 @@
import { toPascalCase } from "js-convert-case";
import prompts from "prompts";
import extract_fields_from_collection from "../utils/extract-fields-from-collection.js";
import { formatWithPrettier } from "../utils/prettier.js";
import { listCollections } from "../utils/list-collections.js";
export async function jddEditorTemplate(actionName: string) {
const response = await prompts([
{
type: "autocomplete",
name: "collection",
message:
"Which sealious collection do you like to add CRUD forms for?",
- choices: (
- await listCollections()
- ).map((collection) => ({
+ choices: (await listCollections()).map((collection) => ({
title: collection,
value: collection,
})),
},
]);
const collection_name = response.collection as string;
const jdd_fields = (
await extract_fields_from_collection(collection_name)
).filter((e) => e.type == "jdd");
let field_name = "";
if (jdd_fields.length == 1) {
field_name = jdd_fields[0].name;
- console.log(
+ console.info(
`Only one field of type JDD found: ${field_name}, so skipping the question...`
);
} else if (jdd_fields.length > 1) {
const response = await prompts([
{
type: "autocomplete",
name: "field_name",
message: `Which jdd field from the ${collection_name} do you want to setup the jdd-editor for?`,
choices: jdd_fields.map((field) => ({
title: field.name,
value: field.name,
})),
},
]);
field_name = response.field_name as string;
} else {
console.error(
`Collection ${collection_name} does not have any fields of type JDD. Add such a field and try again.`
);
process.exit(13);
}
const collectionClassName = toPascalCase(collection_name);
return await formatWithPrettier(`import type { Context } from "koa";
import type { FieldNames } from "sealious";
import { TempstreamJSX } from "tempstream";
import type ${collectionClassName} from "src/back/collections/${collection_name}.js";
import { EditJDDField } from "@sealcode/jdd-editor";
import html from "src/back/html.js";
import { registry } from "src/back/jdd-components/registry.js";
import { makeJDDContext } from "src/back/jdd-context.js";
import { defaultHead } from "src/back/defaultHead.js";
export const actionName = "${actionName}";
export default new (class JDDCreatePreviewPage extends EditJDDField<${collectionClassName}> {
getCollection(ctx: Context) {
return ctx.$app.collections["${collection_name}"];
}
getJDDFieldName(): FieldNames<${collectionClassName}["fields"]> {
return "${field_name}";
}
async renderPreParameterButtons(ctx: Context) {
const item = await this.getItem(ctx);
return (
<div>
<h1>Edit ${collection_name}: {item.id}</h1>{" "}
</div>
);
}
})({ html, registry, makeJDDContext, defaultHead });
`);
}
diff --git a/src/templates/list.ts b/src/templates/list.ts
index 6ce694e..27f963e 100644
--- a/src/templates/list.ts
+++ b/src/templates/list.ts
@@ -1,30 +1,29 @@
-import _locreq from "locreq";
import prompts from "prompts";
import { listCollections } from "../utils/list-collections.js";
import { formatWithPrettier } from "../utils/prettier.js";
import { collectionListTemplate } from "./shared/collection-list.js";
export const listTemplate = async (
action_name: string,
newfilefullpath: string
): Promise<string> => {
const response = await prompts({
type: "autocomplete",
name: "collection",
message: "Which sealious collection do you want to list?",
choices: (
await listCollections()
).map((collection) => ({
title: collection,
value: collection,
})),
});
const collection_name = response.collection as string;
const result = await collectionListTemplate(
collection_name,
action_name,
newfilefullpath
);
return formatWithPrettier(result);
};
diff --git a/src/templates/page.ts b/src/templates/page.ts
index b8185b4..4384424 100644
--- a/src/templates/page.ts
+++ b/src/templates/page.ts
@@ -1,23 +1,20 @@
-export async function pageTemplate(
- action_name: string,
- newfilefullpath: string
-): Promise<string> {
+export async function pageTemplate(action_name: string): Promise<string> {
return `import type { Context } from "koa";
import { TempstreamJSX } from "tempstream";
import { Page } from "@sealcode/sealgen";
import html from "src/back/html.js";
export const actionName = "${action_name}";
export default new (class ${action_name}Page extends Page {
// eslint-disable-next-line @typescript-eslint/no-unused-vars
async canAccess(_: Context) {
return { canAccess: true, message: "" };
}
async render(ctx: Context) {
return html({ ctx: ctx, title: "${action_name}", body: <div></div>, description: "" });
}
})();
`;
}
diff --git a/src/templates/shared/collection-create-form.ts b/src/templates/shared/collection-create-form.ts
index 6a3db4c..0e7fd41 100644
--- a/src/templates/shared/collection-create-form.ts
+++ b/src/templates/shared/collection-create-form.ts
@@ -1,89 +1,88 @@
import { toKebabCase, toPascalCase } from "js-convert-case";
import { formTemplate } from "../form.js";
-import _locreq from "locreq";
import extract_fields_from_collection from "../../utils/extract-fields-from-collection.js";
import { wrapAttribute } from "../../utils/wrap-attributes.js";
export async function createItemFormTemplate(
create_action_name: string,
newfilefullpath: string,
collection_name: string,
list_action: string
): Promise<string> {
- const collection_fields = await extract_fields_from_collection(
- collection_name
- );
+ const collection_fields =
+ await extract_fields_from_collection(collection_name);
const formFieldsVar = `${toPascalCase(collection_name)}FormFields`;
- return formTemplate(create_action_name, newfilefullpath, {
+ return formTemplate(create_action_name, {
success_message: "Created!",
postimport: `import {${formFieldsVar}, get${toPascalCase(
collection_name
)}FormControls }from "./shared.js";
import { ${toPascalCase(
collection_name
)} } from "src/back/collections/collections.js";
import { ${list_action}URL } from "src/back/routes/urls.js";
import {tempstream} from "tempstream";
`,
fields: `...${toPascalCase(collection_name)}FormFields`,
controls: `
new Controls.FormHeader("Create ${toPascalCase(
collection_name
)}"),
...get${toPascalCase(collection_name)}FormControls()`,
can_access: `canAccess = async (ctx: Context) => {
const policy = ${toPascalCase(collection_name)}.getPolicy("create");
const response = await policy.check(ctx.$context);
return { canAccess: response?.allowed || false, message: response?.reason || "" };
};`,
get_initial_values: "",
onsubmit: `
async onSubmit(ctx: Context, formData: FormData) {
const fctx = this.makeFormControlContext(ctx, formData, true);
const created = await ctx.$app.collections["${toKebabCase(
collection_name
)}"].createExtraSafe(
ctx.$context,
{
${collection_fields
.map((field_info) =>
field_info.form_field.generateCreateValueGetter(field_info, {
form_field_types: formFieldsVar,
sealious_field: `fields${wrapAttribute(field_info.name)}`,
form_fields: "fields",
})
)
.join(",\n")}
});
- for(const field of Object.values(${formFieldsVar})){
+ for(const field of Object.values(${formFieldsVar})){
+ // eslint-disable-next-line no-await-in-loop
await field.postSealiousCreate(ctx, created, formData)
}
}
`,
render: ` async render(ctx: Context, data: FormData, show_field_errors: boolean) {
return html({
ctx,
title: "Create ${toKebabCase(collection_name)}",
body: tempstream/* HTML */ \` <div class="sealgen-crud-form">
<a class="" href="\${${list_action}URL}"
>← Back to ${collection_name} list</a
>
\${await super.render(ctx, data, show_field_errors)}
</div>\`,
description: "",
css_clumps: ["admin-forms"]
}
);
}`,
});
}
diff --git a/src/templates/shared/collection-edit-form.ts b/src/templates/shared/collection-edit-form.ts
index 8019f27..809388b 100644
--- a/src/templates/shared/collection-edit-form.ts
+++ b/src/templates/shared/collection-edit-form.ts
@@ -1,142 +1,141 @@
import { toKebabCase, toPascalCase } from "js-convert-case";
import { formTemplate } from "../form.js";
-import _locreq from "locreq";
import extract_fields_from_collection from "../../utils/extract-fields-from-collection.js";
import { wrapAttribute } from "../../utils/wrap-attributes.js";
export async function editItemFormTemplate(
edit_action_name: string,
newfilefullpath: string,
collection_name: string,
list_action: string
): Promise<string> {
- const collection_fields = await extract_fields_from_collection(
- collection_name
- );
+ const collection_fields =
+ await extract_fields_from_collection(collection_name);
const formFieldsVar = `${toPascalCase(collection_name)}FormFields`;
const collectionVar = `${toPascalCase(collection_name)}`;
- return formTemplate(edit_action_name, newfilefullpath, {
+ return formTemplate(edit_action_name, {
success_message: "Changes saved!",
postimport: `import {${formFieldsVar}, get${toPascalCase(
collection_name
)}FormControls }from "../shared.js";
import { ${collectionVar} } from "src/back/collections/collections.js";
import { ${list_action}URL } from "src/back/routes/urls.js";
import {tempstream} from "tempstream";
import type { FormDataValue } from "@sealcode/sealgen";
import type { CollectionInputWithAllKeys } from "sealious";
`,
fields: `...${toPascalCase(collection_name)}FormFields`,
controls: `
new Controls.FormHeader("Edit ${toPascalCase(
collection_name
)}"),
...get${toPascalCase(collection_name)}FormControls()`,
can_access: `canAccess = async (ctx: Context) => {
const policy = ${toPascalCase(collection_name)}.getPolicy("edit");
const response = await policy.check(ctx.$context);
return { canAccess: response?.allowed || false, message: response?.reason || "" };
};`,
onsubmit: `
async onSubmit(ctx: Context, formData: FormData) {
const fctx = this.makeFormControlContext(ctx, formData, true);
const id = await this.getID(ctx);
const {items: [item]} = await ctx.$app.collections["${toKebabCase(
collection_name
)}"]
.list(ctx.$context)
.ids([id])
.fetch();
if (!item) {
throw new Error("Unknown id: " + id);
}
item.setMultipleExtraSafe(
{
${collection_fields
.map((field_info) =>
field_info.form_field.generateCreateValueGetter(
field_info,
{
form_field_types: "FormFieldTypes",
sealious_field: `${collectionVar}.fields${wrapAttribute(
field_info.name
)}`,
form_fields: "fields",
}
)
)
.join(",\n")}
} as CollectionInputWithAllKeys<typeof ${collectionVar}>
);
await item.save(ctx.$context);
for(const field of Object.values(${formFieldsVar})){
- await field.postSealiousEdit(ctx, item, formData)
+ // eslint-disable-next-line no-await-in-loop
+ await field.postSealiousEdit(ctx, item, formData)
}
}
`,
other_methods: `
async getID(ctx: Context): Promise<string>{
const param_name = "id";
const id = ctx.params[param_name];
if (!id) {
throw new Error("Missing URL parameter: " + param_name);
}
return id
}
`,
get_initial_values: `async getInitialValues(ctx: Context): Promise<{ [key in keyof typeof fields]: FormDataValue | undefined }> {
const id = await this.getID(ctx);
const {
items: [item],
} = await ctx.$app.collections["${toKebabCase(collection_name)}"]
.list(ctx.$context)
.ids([id])
.attach({})
.fetch();
if (!item) {
throw new Error("Item with given id not found: " + id);
}
return {
${collection_fields
.map((field_info) =>
field_info.form_field.generateInitialValue(field_info, {
form_field_types: "FieldTypes",
form_fields: "fields",
})
)
.join(",\n")}
};
}
`,
render: ` async render(ctx: Context, data: FormData, show_field_errors: boolean) {
return html({
ctx,
title: "Edit ${toPascalCase(collection_name)}",
body: tempstream/* HTML */ \` <div class="sealgen-crud-form">
<a class="" href="\${${list_action}URL}"
>← Back to ${collection_name} list</a
>
\${await super.render(ctx, data, show_field_errors)}
</div>\`,
description: "", css_clumps: ["admin-forms"]}
);
}`,
});
}
diff --git a/src/templates/shared/collection-list.ts b/src/templates/shared/collection-list.ts
index b0c8807..bbc0a2f 100644
--- a/src/templates/shared/collection-list.ts
+++ b/src/templates/shared/collection-list.ts
@@ -1,235 +1,235 @@
import { extractCollectionClassname } from "../../generate-collections.js";
import extract_fields_from_collection, {
ExtractedFieldInfo,
} from "../../utils/extract-fields-from-collection.js";
import _locreq from "locreq";
import { DefaultListFilters } from "../../page/default-list-filters.js";
import { toKebabCase, toPascalCase } from "js-convert-case";
import { formatWithPrettier } from "../../utils/prettier.js";
const target_locreq = _locreq(process.cwd());
function fieldImport({ type }: ExtractedFieldInfo): string {
if (type == "image") {
return `
import type { FilePointer } from "@sealcode/file-manager";
import { imageRouter } from "src/back/image-router.js";
`;
}
return "";
}
export function makeDefaultFilterFields(
collection_fields: { name: string; type: string }[]
) {
return collection_fields
.map((field) => {
const type = field.type;
return `{ field: "${field.name}", ...${
type in DefaultListFilters
? `DefaultListFilters["${field.type}"]`
: `DefaultListFilters.fallback`
} }`;
})
.join(",\n");
}
export function makeDefaultDisplayFields(
collection_fields: { name: string; type: string }[]
) {
return collection_fields
.map((field) => {
if (field.type == "boolean") {
return ` {
field: "${field.name}",
label: "${field.name}",
format: (v: boolean) => (v ? "YES" : "NO"),
}`;
}
if (field.type == "datetime") {
return ` {
field: "${field.name}",
label: "${field.name}",
format: (v: number) => {
const d = new Date();
d.setTime(v);
return d.toString().split(" ").slice(1, 5).join(" ");
},
}`;
}
if (field.type == "image") {
return `{
field: "${field.name}",
label: "${field.name}",
format: async (value: FilePointer|null) => {
return value ? imageRouter.image(await value.getPath(), {
container: { width: 45, height: 45 },
crop: { width: 45, height: 45 },
alt: "",
}): "";
},
}`;
}
return ` { field: "${field.name}", label: "${field.name}" }`;
})
.join(",\n");
}
const default_hooks = {
pre_header_html: "",
post_header_html: "",
post_import_js: "",
render_item: (
collection_name: string
) => ` async renderItem(_ctx: Context, item: CollectionItem<typeof ${toPascalCase(
collection_name
)}>) {
return <tr>
{displayFields.map(({ field, format }) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
const value = item.get(field as any);
return <td>{format ? format(value, item) : value}</td>;
})}
</tr>;
}`,
};
export async function collectionListTemplate(
collection_name: string,
action_name: string,
_: string,
_hooks: Partial<typeof default_hooks> = {}
) {
const hooks = { ...default_hooks, ..._hooks };
const [uppercase_collection, collection_fields] = await Promise.all([
extractCollectionClassname(
target_locreq.resolve(
"src/back/collections/" + collection_name + ".ts"
)
),
extract_fields_from_collection(collection_name),
]);
const field_import_string = Array.from(
new Set(collection_fields.map((field) => fieldImport(field)))
).join("\n");
const result = `import type { Context } from "koa";
import type { CollectionItem } from "sealious";
import type { FlatTemplatable, Templatable } from "tempstream";
import { TempstreamJSX, tempstream } from "tempstream";
import { ${uppercase_collection} } from "src/back/collections/collections.js";
import html from "src/back/html.js";
import type { ListFilterRender, FormDisplayInfo } from "@sealcode/sealgen";
import {
SealiousItemListPage,
BaseListPageFields,
DefaultListFilters,
} from "@sealcode/sealgen";
import qs from "qs";
${hooks.post_import_js}
${field_import_string}
export const actionName = "${action_name}";
const filterFields:{
- field: keyof (typeof HasAllFields)["fields"];
+ field: keyof (typeof ${uppercase_collection})["fields"];
render?: ListFilterRender;
prepareValue?: (filter_value: unknown) => unknown; // set this function to change what filter value is passed to Sealious
}[] = [
${makeDefaultFilterFields(collection_fields)}
];
const displayFields: FormDisplayInfo<typeof ${uppercase_collection}>[] = [
${makeDefaultDisplayFields(collection_fields)}
];
export default new (class ${action_name}Page extends SealiousItemListPage<
typeof ${uppercase_collection},
typeof BaseListPageFields
> {
fields = BaseListPageFields;
async renderFilters(ctx: Context): Promise<FlatTemplatable> {
const query_params = qs.parse(ctx.search.slice(1));
query_params.page = "1";
const filter_values = await super.getFilterValues(ctx);
return <form>
{Object.entries(query_params).map(([key, value]) => {
if (key == "filter") {
return "";
}
// this is necessary to not lose any query params when the user changes the filter values
return <input type="hidden" name={key} value={value}/>;
})}
{filterFields.map(({ field, render }) => {
if (!render) {
render = DefaultListFilters.fallback.render;
}
return (
render(filter_values[field] || "", this.collection.fields[field], ctx) ||
""
);
})}
<input type="submit" />
</form>;
}
async getFilterValues(ctx: Context) {
// adding opportunity to adjust the values for a given field filter before it's sent to Sealious
const values = await super.getFilterValues(ctx);
for (const filterField of filterFields) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
const key = filterField.field as keyof typeof values;
if (key in values) {
const prepare_fn = filterField.prepareValue;
if (prepare_fn) {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-assignment
values[key] = prepare_fn(values[key]) as any;
}
}
}
return values;
}
${hooks.render_item(collection_name)}
renderListContainer(ctx: Context, content: Templatable): FlatTemplatable {
return (
<table class="sealious-list ${toKebabCase(action_name)}-table">
{this.renderTableHead(ctx, displayFields)}
<tbody>{content}</tbody>
</table>
);
}
renderTableHead(
ctx: Context,
fields: { field: string; label?: string }[]
): FlatTemplatable {
- return tempstream/* HTML */ \`<thead>
+ return tempstream /* HTML */ \`<thead>
<tr>
\${fields.map(({ label, field }) => this.renderHeading(ctx, field, label))}
<th>Actions</th>
</tr>
</thead>\`;
}
async render(ctx: Context) {
return html({
ctx,
title: "${action_name}",
description: "",
body: <div class="sealious-list-wrapper ${toKebabCase(action_name)}--wrapper">
${hooks.pre_header_html}
<h2>${action_name} List</h2>
${hooks.post_header_html}
{super.render(ctx)}
</div>
});
}
})(${uppercase_collection});
`;
return await formatWithPrettier(result);
}
diff --git a/src/templates/shared/shared-crud-form-fields.ts b/src/templates/shared/shared-crud-form-fields.ts
index 076c4a2..c20f1dc 100644
--- a/src/templates/shared/shared-crud-form-fields.ts
+++ b/src/templates/shared/shared-crud-form-fields.ts
@@ -1,59 +1,54 @@
import { toPascalCase } from "js-convert-case";
-import _locreq from "locreq";
import extract_fields_from_collection from "../../utils/extract-fields-from-collection.js";
import { formatWithPrettier } from "../../utils/prettier.js";
import { wrapAttribute } from "../../utils/wrap-attributes.js";
-export async function sharedCrudFormFields(
- collection_name: string,
- newfilefullpath: string
-) {
- const collection_fields = await extract_fields_from_collection(
- collection_name
- );
+export async function sharedCrudFormFields(collection_name: string) {
+ const collection_fields =
+ await extract_fields_from_collection(collection_name);
const uppercase_collection = toPascalCase(collection_name);
- const result = `import { Controls, Fields } from "@sealcode/sealgen";
+ const result = `import { type Controls, Fields } from "@sealcode/sealgen";
import { ${uppercase_collection} } from "src/back/collections/collections.js";
${Array.from(
new Set(
collection_fields
.map((field_info) =>
field_info.form_field.generateImportsForFieldList(field_info)
)
.flat()
.map(
({ what, from, as }) =>
`import {${what}${as ? ` as ${as}` : ""} } from "${from}"`
)
).values()
).join(";\n")}
export const ${toPascalCase(collection_name)}FormFields = <const>{
${collection_fields
.map((field_info) => {
return `${
field_info.name
}: ${field_info.form_field.generateFieldDeclaration(field_info, {
form_field_types: "Fields",
sealious_field: `${uppercase_collection}.fields${wrapAttribute(
field_info.name
)}`,
})}`;
})
.join(",\n")}
};
const fields = ${toPascalCase(collection_name)}FormFields
export const get${toPascalCase(
collection_name
)}FormControls: () => Controls.FormControl[] = () => [
${collection_fields
.map(({ name }) => `fields${wrapAttribute(name)}.getControl()`)
.join(",\n")}
];
`;
return formatWithPrettier(result);
}
diff --git a/src/templates/templates.ts b/src/templates/templates.ts
index cc5cacb..48e45c1 100644
--- a/src/templates/templates.ts
+++ b/src/templates/templates.ts
@@ -1,23 +1,27 @@
import { formTemplate } from "./form.js";
import { jddComponentTemplate } from "./jdd-component.js";
import { listTemplate } from "./list.js";
import { LongRunningProcessTemplate } from "./long-running-process.js";
import { multiformTemplate } from "./multiform.js";
import { pageTemplate } from "./page.js";
import { postTemplate } from "./post.js";
import { redirectTemplate } from "./redirect.js";
import { statefulPageTemplate } from "./stateful-page.js";
import { jddEditorTemplate } from "./jdd-editor.js";
-export const Templates = {
+export const Templates: Record<
+ string,
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ (action: string, params: any) => Promise<string>
+> = {
page: pageTemplate,
form: formTemplate,
list: listTemplate,
multiform: multiformTemplate,
redirect: redirectTemplate,
post: postTemplate,
sreact: statefulPageTemplate,
lpr: LongRunningProcessTemplate,
jdd: jddComponentTemplate,
"jdd-editor": jddEditorTemplate,
};
diff --git a/src/test_utils/exec_async.ts b/src/test_utils/exec_async.ts
index ced38e2..1560f3a 100644
--- a/src/test_utils/exec_async.ts
+++ b/src/test_utils/exec_async.ts
@@ -1,26 +1,25 @@
-/* eslint-disable @typescript-eslint/restrict-template-expressions */
import { exec } from "child_process";
export const execAsync = (cmd: string) => {
return new Promise<void>((resolve, reject) => {
const process = exec(cmd);
- console.log("EXECUTING", cmd);
+ console.info("EXECUTING", cmd);
process?.stdout?.on("data", (data) => {
- console.log(`stdout: ${data}`);
+ console.info(`stdout: ${data}`);
});
process?.stderr?.on("data", (data) => {
- console.log(`stdout: ${data}`);
+ console.info(`stdout: ${data}`);
});
process.on("exit", (code) => {
if (code == 0) {
resolve();
} else {
reject();
}
});
});
};
diff --git a/src/test_utils/test-on-real-app.ts b/src/test_utils/test-on-real-app.ts
index 0a1f98d..d4560f0 100644
--- a/src/test_utils/test-on-real-app.ts
+++ b/src/test_utils/test-on-real-app.ts
@@ -1,200 +1,198 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-call */
import { execAsync } from "./exec_async.js";
import { spawn } from "child_process";
import getPort from "get-port";
import waitPort from "wait-port";
import { promises as fs } from "fs";
import path from "node:path";
import chalk from "chalk";
import _locreq from "locreq";
import { module_dirname } from "../utils/module-dirname.js";
import EventEmitter from "events";
const locreq = _locreq(module_dirname(import.meta.url));
export const callSealgenBin = () => `node ${locreq.resolve("lib/cli.js")}`;
const sealious_minimal_url =
"https://hub.sealcode.org/source/sealious-minimal.git";
const sealious_minimal_commit = "77e3794";
export class RealAppTest {
public node_pid: number;
public app_port: number;
public mongo_port: number;
public app_path: string;
public container_name: string;
public emitter = new EventEmitter();
static async init(): Promise<RealAppTest> {
const test_app = new RealAppTest();
test_app.node_pid = 0;
const timestamp = Date.now();
test_app.app_path = `/tmp/sealious-minimal-${timestamp}`;
test_app.container_name = `sealgen-test-mongo-${timestamp}`;
- console.log("\tcloning sealious-minimal...");
+ console.info("\tcloning sealious-minimal...");
await execAsync(
`git clone ${sealious_minimal_url} ${test_app.app_path} && cd ${test_app.app_path} && git checkout ${sealious_minimal_commit}`
);
- console.log("\tinstalling dependencies and sealgen...");
+ console.info("\tinstalling dependencies and sealgen...");
await execAsync(
`cd ${
test_app.app_path
} && npm ci rm -rf node_modules/@sealcode/sealgen && ln -s $OLDPWD node_modules/@sealcode/sealgen && ${callSealgenBin()} make-env`
);
- console.log(
+ console.info(
"\tstarting the database...(if timeouts here, run 'docker pull mongo:4.4-bionic' to solve)"
);
await test_app.runSealgenCommand("build");
test_app.app_port = await getPort();
return test_app;
}
async start() {
this.mongo_port = await getPort();
await execAsync(
`docker run -p ${this.mongo_port}:27017 --name ${this.container_name} -d mongo:4.4-bionic`
);
const env = {
...process.env,
SEALIOUS_MONGO_PORT: this.mongo_port.toString(),
SEALIOUS_PORT: this.app_port.toString(),
};
const node_args = [`${this.app_path}/dist/back/index.js`];
- console.log(
+ console.info(
"EXECUTING APP",
`${Object.entries(env)
.map(([key, value]) => `${key}=${value}`)
.join(" ")} node ${node_args.join(" ")}`
);
const app_start = spawn(`node`, node_args, {
env,
});
app_start.stdout.on("data", (data) =>
- console.log("APP OUTPUT:", data.toString())
+ console.info("APP OUTPUT:", data.toString())
);
- app_start.stderr.on("data", (data) => console.log(data.toString()));
+ app_start.stderr.on("data", (data) => console.info(data.toString()));
app_start.on("exit", (code) => {
this.emitter.emit("exit", code);
this.emitter.emit("process_error");
});
if (app_start.pid == undefined) throw new Error("node failed to start");
this.node_pid = app_start.pid;
await waitPort({
host: "localhost",
port: this.app_port,
output: "silent",
timeout: 6000,
});
- console.log(
+ console.info(
chalk.yellow(
`App is listening on http://localhost:${this.app_port}`
)
);
}
async close() {
try {
if (this.node_pid != 0) await execAsync(`kill -9 ${this.node_pid}`);
- } catch (error) {
+ } catch (_error) {
throw new Error(
"node process exited unexpectedly, please inspect the output"
);
}
await Promise.all([
fs.rm(this.app_path, { recursive: true, force: true }),
execAsync(`docker rm -f ${this.container_name}`),
]);
}
async runSealgenCommand(command: string) {
await execAsync(
`cd ${
this.app_path
} && ${callSealgenBin()} ${command} && ${callSealgenBin()} build`
);
await this.build();
}
async build() {
await execAsync(`cd ${this.app_path} && ${callSealgenBin()} build`);
}
async throwIfItKillsTheApp<T>(cb: () => Promise<T>): Promise<T> {
let finished = false;
// eslint-disable-next-line @typescript-eslint/no-misused-promises, no-async-promise-executor
return new Promise(async (resolve, reject) => {
const error_handler = () => {
if (!finished) {
reject();
}
finished = true;
};
this.emitter.addListener("process_error", error_handler);
try {
const result = await cb();
if (!finished) {
resolve(result);
finished = true;
}
} catch (e) {
if (!finished) {
reject(e);
finished = true;
}
}
this.emitter.removeListener("process_error", error_handler);
});
}
async httpGET(path: string): Promise<{ status: number; response: string }> {
return this.throwIfItKillsTheApp(async () => {
const ret = await fetch(`http://localhost:${this.app_port}${path}`);
const status = ret.status;
const response = await ret.text();
return { status, response };
});
}
async httpPOST(
path: string,
body: Record<string, unknown>
): Promise<{ status: number; response: string }> {
return this.throwIfItKillsTheApp(async () => {
const ret = await fetch(
`http://localhost:${this.app_port}${path}`,
{
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(body),
}
);
const status = ret.status;
const response = await ret.text();
- console.debug("request done!");
- console.debug({ response });
return { status, response };
});
}
async addFile(target_path: string, content: string) {
- console.log(
+ console.info(
chalk.yellow("Inserting file at path"),
chalk.green(target_path),
"with content\n",
content,
"\n\n\n\n=====\n"
);
await fs.writeFile(path.resolve(this.app_path, target_path), content);
await this.build();
}
fullURL(path: string): string {
return `http://localhost:${this.app_port}${
path.startsWith("/") ? "" : "/"
}${path}`;
}
}
diff --git a/src/utils/browser-creator.js b/src/utils/browser-creator.js
index 225253b..d13f18d 100644
--- a/src/utils/browser-creator.js
+++ b/src/utils/browser-creator.js
@@ -1,10 +1,9 @@
import { firefox } from "playwright";
let browser_promise = null;
-// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
export async function getBrowser() {
if (!browser_promise) browser_promise = firefox.launch();
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return browser_promise;
}
diff --git a/src/utils/exec.ts b/src/utils/exec.ts
index 7efcd39..4916fe4 100644
--- a/src/utils/exec.ts
+++ b/src/utils/exec.ts
@@ -1,30 +1,29 @@
-/* eslint-disable no-console */
import { spawn } from "child_process";
export async function exec(
program: string,
args: string[]
): Promise<{ stderr: string; stdout: string; exitCode: number }> {
return new Promise((resolve, reject) => {
let stdout = "";
let stderr = "";
const process = spawn(program, args);
process.stdout.on(
"data",
(data: Buffer) => (stdout += data.toString())
);
process.stderr.on(
"data",
(data: Buffer) => (stderr += data.toString())
);
process.on("close", (exitCode) => {
if (exitCode === 0) {
resolve({ stdout, stderr, exitCode });
} else {
console.error([program, ...args].join(" "));
console.error(stderr);
reject({ stdout, stderr, exitCode });
}
});
});
}
diff --git a/src/utils/input-wrapper.ts b/src/utils/input-wrapper.ts
index 9acf2c2..cf5527e 100644
--- a/src/utils/input-wrapper.ts
+++ b/src/utils/input-wrapper.ts
@@ -1,23 +1,23 @@
import { FlatTemplatable, tempstream } from "tempstream";
export function getRequiredClass(isRequired: boolean): string {
return isRequired ? "required" : "";
}
function getModifierClasses(modifiers: string[]) {
return modifiers.map((m) => "form-input__wrapper--" + m).join(" ");
}
export async function inputWrapper(
type: string,
modifiers: string[],
input: FlatTemplatable
): Promise<string> {
- return tempstream/* HTML */ `<div
+ return tempstream /* HTML */ `<div
class="form-input form-input--type-${type} form-input__wrapper ${getModifierClasses(
modifiers
)}"
>
${input}
</div>`;
}
diff --git a/src/utils/wrap-attributes.ts b/src/utils/wrap-attributes.ts
index 1360076..d9a3b74 100644
--- a/src/utils/wrap-attributes.ts
+++ b/src/utils/wrap-attributes.ts
@@ -1,17 +1,17 @@
export function needsQuotes(str: string) {
try {
- // eslint-disable-next-line @typescript-eslint/no-implied-eval
+ // eslint-disable-next-line @typescript-eslint/no-implied-eval
new Function(`var obj = { ${str}: 1 };`);
return false;
} catch {
return true;
}
}
export function wrapAttribute(name: string) {
return needsQuotes(name) ? `["${name}"]` : `.${name}`;
}
export function wrapKeyName(name: string) {
return needsQuotes(name) ? `["${name}"]` : `${name}`;
}
diff --git a/src/utils/write-file.ts b/src/utils/write-file.ts
index b18057c..150625a 100644
--- a/src/utils/write-file.ts
+++ b/src/utils/write-file.ts
@@ -1,8 +1,8 @@
import { promises as fs } from "node:fs";
import { resolve } from "path";
export async function writeFile(path: string, content: string) {
await fs.mkdir(resolve(path, "../"), { recursive: true });
await fs.writeFile(path, content);
- console.log(`${path} created`);
+ console.info(`${path} created`);
}

File Metadata

Mime Type
text/x-diff
Expires
Sat, Oct 11, 11:09 (9 h, 49 m)
Storage Engine
local-disk
Storage Format
Raw Data
Storage Handle
5b/e5/8e78dc67df991df0109d58245304
Default Alt Text
(833 KB)

Event Timeline