From e4725c23eb17d5d5a2752d4ded69ba13cc55a02f Mon Sep 17 00:00:00 2001 From: William Will <10997562+willwill96@users.noreply.github.com> Date: Thu, 30 Mar 2023 02:45:43 -0600 Subject: [PATCH 1/6] feat: add vitest testing --- package.json | 7 +- vitest.config.ts | 11 + yarn.lock | 548 ++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 560 insertions(+), 6 deletions(-) create mode 100644 vitest.config.ts diff --git a/package.json b/package.json index a53c49ca..8f38ac39 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "prepare": "yarn generate-i18n-messages", "build": "rimraf dist/ && tsc -p src/bin && tsc -p src/tsconfig.json && tsc-alias -p src/tsconfig.json && yarn grant-exec-perms && yarn copy-files dist/", "build:watch": "tsc -p src/tsconfig.json && (concurrently \"tsc -p src/tsconfig.json -w\" \"tsc-alias -p src/tsconfig.json\")", - "build:test": "rimraf dist_test/ && tsc -p test/tsconfig.json && tsc-alias -p test/tsconfig.json && yarn copy-files dist_test/src", + "test:types": "tsc -p test/tsconfig.json --noEmit", "grant-exec-perms": "node dist/bin/tools/grant-exec-perms.js", "copy-files": "copyfiles -u 1 src/**/*.ftl", - "test": "yarn build:test && node dist_test/test/bin && node dist_test/test/lib", + "test": "yarn test:types && vitest run", "test:sample-app": "yarn build:test && node dist_test/test/bin/main.js", "_format": "prettier '**/*.{ts,tsx,json,md}'", "format": "yarn _format --write", @@ -80,7 +80,8 @@ "scripting-tools": "^0.19.13", "ts-node": "^10.9.1", "tsc-alias": "^1.8.3", - "typescript": "^5.0.1-rc" + "typescript": "^5.0.1-rc", + "vitest": "^0.29.8" }, "dependencies": { "@octokit/rest": "^18.12.0", diff --git a/vitest.config.ts b/vitest.config.ts new file mode 100644 index 00000000..f372a9c9 --- /dev/null +++ b/vitest.config.ts @@ -0,0 +1,11 @@ +/// +import { defineConfig } from "vite"; +import path from "path"; + +export default defineConfig({ + test: { + alias: { + "keycloakify": path.resolve(__dirname, "./src") + } + } +}); diff --git a/yarn.lock b/yarn.lock index 1aa0dc72..c1518ac1 100644 --- a/yarn.lock +++ b/yarn.lock @@ -198,6 +198,116 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@esbuild/android-arm64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.17.14.tgz#4624cea3c8941c91f9e9c1228f550d23f1cef037" + integrity sha512-eLOpPO1RvtsP71afiFTvS7tVFShJBCT0txiv/xjFBo5a7R7Gjw7X0IgIaFoLKhqXYAXhahoXm7qAmRXhY4guJg== + +"@esbuild/android-arm@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.17.14.tgz#74fae60fcab34c3f0e15cb56473a6091ba2b53a6" + integrity sha512-0CnlwnjDU8cks0yJLXfkaU/uoLyRf9VZJs4p1PskBr2AlAHeEsFEwJEo0of/Z3g+ilw5mpyDwThlxzNEIxOE4g== + +"@esbuild/android-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.17.14.tgz#f002fbc08d5e939d8314bd23bcfb1e95d029491f" + integrity sha512-nrfQYWBfLGfSGLvRVlt6xi63B5IbfHm3tZCdu/82zuFPQ7zez4XjmRtF/wIRYbJQ/DsZrxJdEvYFE67avYXyng== + +"@esbuild/darwin-arm64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.17.14.tgz#b8dcd79a1dd19564950b4ca51d62999011e2e168" + integrity sha512-eoSjEuDsU1ROwgBH/c+fZzuSyJUVXQTOIN9xuLs9dE/9HbV/A5IqdXHU1p2OfIMwBwOYJ9SFVGGldxeRCUJFyw== + +"@esbuild/darwin-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.17.14.tgz#4b49f195d9473625efc3c773fc757018f2c0d979" + integrity sha512-zN0U8RWfrDttdFNkHqFYZtOH8hdi22z0pFm0aIJPsNC4QQZv7je8DWCX5iA4Zx6tRhS0CCc0XC2m7wKsbWEo5g== + +"@esbuild/freebsd-arm64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.17.14.tgz#480923fd38f644c6342c55e916cc7c231a85eeb7" + integrity sha512-z0VcD4ibeZWVQCW1O7szaLxGsx54gcCnajEJMdYoYjLiq4g1jrP2lMq6pk71dbS5+7op/L2Aod+erw+EUr28/A== + +"@esbuild/freebsd-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.17.14.tgz#a6b6b01954ad8562461cb8a5e40e8a860af69cbe" + integrity sha512-hd9mPcxfTgJlolrPlcXkQk9BMwNBvNBsVaUe5eNUqXut6weDQH8whcNaKNF2RO8NbpT6GY8rHOK2A9y++s+ehw== + +"@esbuild/linux-arm64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.17.14.tgz#1fe2f39f78183b59f75a4ad9c48d079916d92418" + integrity sha512-FhAMNYOq3Iblcj9i+K0l1Fp/MHt+zBeRu/Qkf0LtrcFu3T45jcwB6A1iMsemQ42vR3GBhjNZJZTaCe3VFPbn9g== + +"@esbuild/linux-arm@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.17.14.tgz#18d594a49b64e4a3a05022c005cb384a58056a2a" + integrity sha512-BNTl+wSJ1omsH8s3TkQmIIIQHwvwJrU9u1ggb9XU2KTVM4TmthRIVyxSp2qxROJHhZuW/r8fht46/QE8hU8Qvg== + +"@esbuild/linux-ia32@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.17.14.tgz#f7f0182a9cfc0159e0922ed66c805c9c6ef1b654" + integrity sha512-91OK/lQ5y2v7AsmnFT+0EyxdPTNhov3y2CWMdizyMfxSxRqHazXdzgBKtlmkU2KYIc+9ZK3Vwp2KyXogEATYxQ== + +"@esbuild/linux-loong64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.17.14.tgz#5f5305fdffe2d71dd9a97aa77d0c99c99409066f" + integrity sha512-vp15H+5NR6hubNgMluqqKza85HcGJgq7t6rMH7O3Y6ApiOWPkvW2AJfNojUQimfTp6OUrACUXfR4hmpcENXoMQ== + +"@esbuild/linux-mips64el@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.17.14.tgz#a602e85c51b2f71d2aedfe7f4143b2f92f97f3f5" + integrity sha512-90TOdFV7N+fgi6c2+GO9ochEkmm9kBAKnuD5e08GQMgMINOdOFHuYLPQ91RYVrnWwQ5683sJKuLi9l4SsbJ7Hg== + +"@esbuild/linux-ppc64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.17.14.tgz#32d918d782105cbd9345dbfba14ee018b9c7afdf" + integrity sha512-NnBGeoqKkTugpBOBZZoktQQ1Yqb7aHKmHxsw43NddPB2YWLAlpb7THZIzsRsTr0Xw3nqiPxbA1H31ZMOG+VVPQ== + +"@esbuild/linux-riscv64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.17.14.tgz#38612e7b6c037dff7022c33f49ca17f85c5dec58" + integrity sha512-0qdlKScLXA8MGVy21JUKvMzCYWovctuP8KKqhtE5A6IVPq4onxXhSuhwDd2g5sRCzNDlDjitc5sX31BzDoL5Fw== + +"@esbuild/linux-s390x@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.17.14.tgz#4397dff354f899e72fd035d72af59a700c465ccb" + integrity sha512-Hdm2Jo1yaaOro4v3+6/zJk6ygCqIZuSDJHdHaf8nVH/tfOuoEX5Riv03Ka15LmQBYJObUTNS1UdyoMk0WUn9Ww== + +"@esbuild/linux-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.17.14.tgz#6c5cb99891b6c3e0c08369da3ef465e8038ad9c2" + integrity sha512-8KHF17OstlK4DuzeF/KmSgzrTWQrkWj5boluiiq7kvJCiQVzUrmSkaBvcLB2UgHpKENO2i6BthPkmUhNDaJsVw== + +"@esbuild/netbsd-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.17.14.tgz#5fa5255a64e9bf3947c1b3bef5e458b50b211994" + integrity sha512-nVwpqvb3yyXztxIT2+VsxJhB5GCgzPdk1n0HHSnchRAcxqKO6ghXwHhJnr0j/B+5FSyEqSxF4q03rbA2fKXtUQ== + +"@esbuild/openbsd-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.17.14.tgz#74d14c79dcb6faf446878cc64284aa4e02f5ca6f" + integrity sha512-1RZ7uQQ9zcy/GSAJL1xPdN7NDdOOtNEGiJalg/MOzeakZeTrgH/DoCkbq7TaPDiPhWqnDF+4bnydxRqQD7il6g== + +"@esbuild/sunos-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.17.14.tgz#5c7d1c7203781d86c2a9b2ff77bd2f8036d24cfa" + integrity sha512-nqMjDsFwv7vp7msrwWRysnM38Sd44PKmW8EzV01YzDBTcTWUpczQg6mGao9VLicXSgW/iookNK6AxeogNVNDZA== + +"@esbuild/win32-arm64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.17.14.tgz#dc36ed84f1390e73b6019ccf0566c80045e5ca3d" + integrity sha512-xrD0mccTKRBBIotrITV7WVQAwNJ5+1va6L0H9zN92v2yEdjfAN7864cUaZwJS7JPEs53bDTzKFbfqVlG2HhyKQ== + +"@esbuild/win32-ia32@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.17.14.tgz#0802a107afa9193c13e35de15a94fe347c588767" + integrity sha512-nXpkz9bbJrLLyUTYtRotSS3t5b+FOuljg8LgLdINWFs3FfqZMtbnBCZFUmBzQPyxqU87F8Av+3Nco/M3hEcu1w== + +"@esbuild/win32-x64@0.17.14": + version "0.17.14" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.17.14.tgz#e81fb49de05fed91bf74251c9ca0343f4fc77d31" + integrity sha512-gPQmsi2DKTaEgG14hc3CHXHp62k8g6qr0Pas+I4lUxRMugGSATh/Bi8Dgusoz9IQ0IfdrvLpco6kujEIBoaogA== + "@jridgewell/gen-mapping@^0.1.0": version "0.1.1" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz#e5d2e450306a9491e3bd77e323e38d7aff315996" @@ -400,6 +510,18 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.3.tgz#472eaab5f15c1ffdd7f8628bd4c4f753995ec79e" integrity sha512-yOlFc+7UtL/89t2ZhjPvvB/DeAr3r+Dq58IgzsFkOAvVC6NMJXmCGjbptdXdR9qsX7pKcTL+s87FtYREi2dEEQ== +"@types/chai-subset@^1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@types/chai-subset/-/chai-subset-1.3.3.tgz#97893814e92abd2c534de422cb377e0e0bdaac94" + integrity sha512-frBecisrNGz+F4T6bcc+NLeolfiojh5FxW2klu669+8BARtyQv2C/GkNW6FUodVe4BroGMP/wER/YDGc7rEllw== + dependencies: + "@types/chai" "*" + +"@types/chai@*", "@types/chai@^4.3.4": + version "4.3.4" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.4.tgz#e913e8175db8307d78b4e8fa690408ba6b65dee4" + integrity sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw== + "@types/make-fetch-happen@^10.0.1": version "10.0.1" resolved "https://registry.yarnpkg.com/@types/make-fetch-happen/-/make-fetch-happen-10.0.1.tgz#9e718d8f5f6ed388e2020bb9b4fbd2dc23009b38" @@ -480,12 +602,47 @@ resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.6.tgz#250a7b16c3b91f672a24552ec64678eeb1d3a08d" integrity sha512-PBjIUxZHOuj0R15/xuwJYjFi+KZdNFrehocChv4g5hu6aFroHue8m0lBP0POdK2nKzbw0cgV1mws8+V/JAcEkQ== -acorn-walk@^8.1.1: +"@vitest/expect@0.29.8": + version "0.29.8" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-0.29.8.tgz#6ecdd031b4ea8414717d10b65ccd800908384612" + integrity sha512-xlcVXn5I5oTq6NiZSY3ykyWixBxr5mG8HYtjvpgg6KaqHm0mvhX18xuwl5YGxIRNt/A5jidd7CWcNHrSvgaQqQ== + dependencies: + "@vitest/spy" "0.29.8" + "@vitest/utils" "0.29.8" + chai "^4.3.7" + +"@vitest/runner@0.29.8": + version "0.29.8" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-0.29.8.tgz#ede8a7be8a074ea1180bc1d1595bd879ed15971c" + integrity sha512-FzdhnRDwEr/A3Oo1jtIk/B952BBvP32n1ObMEb23oEJNO+qO5cBet6M2XWIDQmA7BDKGKvmhUf2naXyp/2JEwQ== + dependencies: + "@vitest/utils" "0.29.8" + p-limit "^4.0.0" + pathe "^1.1.0" + +"@vitest/spy@0.29.8": + version "0.29.8" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-0.29.8.tgz#2e0c3b30e04d317b2197e3356234448aa432e131" + integrity sha512-VdjBe9w34vOMl5I5mYEzNX8inTxrZ+tYUVk9jxaZJmHFwmDFC/GV3KBFTA/JKswr3XHvZL+FE/yq5EVhb6pSAw== + dependencies: + tinyspy "^1.0.2" + +"@vitest/utils@0.29.8": + version "0.29.8" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-0.29.8.tgz#423da85fd0c6633f3ab496cf7d2fc0119b850df8" + integrity sha512-qGzuf3vrTbnoY+RjjVVIBYfuWMjn3UMUqyQtdGNZ6ZIIyte7B37exj6LaVkrZiUTvzSadVvO/tJm8AEgbGCBPg== + dependencies: + cli-truncate "^3.1.0" + diff "^5.1.0" + loupe "^2.3.6" + pretty-format "^27.5.1" + +acorn-walk@^8.1.1, acorn-walk@^8.2.0: version "8.2.0" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.2.0.tgz#741210f2e2426454508853a2f44d0ab83b7f69c1" integrity sha512-k+iyHEuPgSw6SbuDpGQM+06HQUa04DZ3o+F6CSzXMvvI5KMvnaEqXe+YVe555R9nn6GPt404fos4wcgpw12SDA== -acorn@^8.4.1: +acorn@^8.4.1, acorn@^8.8.1, acorn@^8.8.2: version "8.8.2" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== @@ -536,6 +693,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.0.1.tgz#3183e38fae9a65d7cb5e53945cd5897d0260a06a" + integrity sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA== + ansi-styles@^3.2.1: version "3.2.1" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" @@ -550,6 +712,16 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +ansi-styles@^6.0.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -568,6 +740,11 @@ array-union@^2.1.0: resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + astral-regex@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/astral-regex/-/astral-regex-2.0.0.tgz#483143c567aeed4785759c0865786dc77d7d2e31" @@ -635,6 +812,11 @@ browserslist@^4.21.3: node-releases "^2.0.8" update-browserslist-db "^1.0.10" +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + cacache@^17.0.0: version "17.0.4" resolved "https://registry.yarnpkg.com/cacache/-/cacache-17.0.4.tgz#5023ed892ba8843e3b7361c26d0ada37e146290c" @@ -664,6 +846,19 @@ caniuse-lite@^1.0.30001449: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001457.tgz#6af34bb5d720074e2099432aa522c21555a18301" integrity sha512-SDIV6bgE1aVbK6XyxdURbUE89zY7+k1BBBaOwYwkNCglXlel/E7mELiHC64HQ+W0xSKlqWhV9Wh7iHxUjMs4fA== +chai@^4.3.7: + version "4.3.7" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.7.tgz#ec63f6df01829088e8bf55fca839bcd464a8ec51" + integrity sha512-HLnAzZ2iupm25PlN0xFreAlBA5zaBSv3og0DdeGA4Ar6h6rJ3A0rolRUKJhSF2V10GZKDgWF/VmAEsNWjCRB+A== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.2" + deep-eql "^4.1.2" + get-func-name "^2.0.0" + loupe "^2.3.1" + pathval "^1.1.1" + type-detect "^4.0.5" + chalk@^2.0.0: version "2.4.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" @@ -696,6 +891,11 @@ character-reference-invalid@^1.0.0: resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== +check-error@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.2.tgz#574d312edd88bb5dd8912e9286dd6c0aed4aac82" + integrity sha512-BrgHpW9NURQgzoNyjfq0Wu6VFO6D7IZEmJNdtgNqpzGG8RuNFHt2jQxWlAs4HMe119chBnv+34syEZtc6IhLtA== + cheerio-select@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/cheerio-select/-/cheerio-select-2.1.0.tgz#4d8673286b8126ca2a8e42740d5e3c4884ae21b4" @@ -773,6 +973,14 @@ cli-truncate@2.1.0, cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" +cli-truncate@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/cli-truncate/-/cli-truncate-3.1.0.tgz#3f23ab12535e3d73e839bb43e73c9de487db1389" + integrity sha512-wfOBkjXteqSnI59oPcJkcPl/ZmwvMMOj340qUIY1SKZCv0B9Cf4D4fAucRkIKQmsIuYK3x1rrgU7MeGRruiuiA== + dependencies: + slice-ansi "^5.0.0" + string-width "^5.0.0" + cliui@^7.0.2: version "7.0.4" resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" @@ -941,13 +1149,20 @@ date-fns@^2.29.1: resolved "https://registry.yarnpkg.com/date-fns/-/date-fns-2.29.3.tgz#27402d2fc67eb442b511b70bbdf98e6411cd68a8" integrity sha512-dDCnyH2WnnKusqvZZ6+jA1O51Ibt8ZMRNkDZdyAyK4YfbDwa/cEmuztzG5pk6hqlp9aSBPYcjOlktquahGwGeA== -debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.3.2, debug@^4.3.3: +debug@4, debug@^4.0.0, debug@^4.1.0, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== dependencies: ms "2.1.2" +deep-eql@^4.1.2: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + delayed-stream@~1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" @@ -968,6 +1183,11 @@ diff@^4.0.1: resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== +diff@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.1.0.tgz#bc52d298c5ea8df9194800224445ed43ffc87e40" + integrity sha512-D+mk+qE8VC/PAUrlAU34N+VfXev0ghe5ywmpqrawphmVZc1bEfn56uo9qpyGp1p4xpzOHkSW4ztBd6L7Xx4ACw== + dir-glob@^3.0.1: version "3.0.1" resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" @@ -1005,6 +1225,11 @@ domutils@^3.0.1: domelementtype "^2.3.0" domhandler "^5.0.1" +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.4.284: version "1.4.311" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.311.tgz#953bc9a4767f5ce8ec125f9a1ad8e00e8f67e479" @@ -1015,6 +1240,11 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -1046,6 +1276,34 @@ error-ex@^1.3.1: dependencies: is-arrayish "^0.2.1" +esbuild@^0.17.5: + version "0.17.14" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.17.14.tgz#d61a22de751a3133f3c6c7f9c1c3e231e91a3245" + integrity sha512-vOO5XhmVj/1XQR9NQ1UPq6qvMYL7QFJU57J5fKBKBKxp17uDt5PgxFDb4A2nEiXhr1qQs4x0F5+66hVVw4ruNw== + optionalDependencies: + "@esbuild/android-arm" "0.17.14" + "@esbuild/android-arm64" "0.17.14" + "@esbuild/android-x64" "0.17.14" + "@esbuild/darwin-arm64" "0.17.14" + "@esbuild/darwin-x64" "0.17.14" + "@esbuild/freebsd-arm64" "0.17.14" + "@esbuild/freebsd-x64" "0.17.14" + "@esbuild/linux-arm" "0.17.14" + "@esbuild/linux-arm64" "0.17.14" + "@esbuild/linux-ia32" "0.17.14" + "@esbuild/linux-loong64" "0.17.14" + "@esbuild/linux-mips64el" "0.17.14" + "@esbuild/linux-ppc64" "0.17.14" + "@esbuild/linux-riscv64" "0.17.14" + "@esbuild/linux-s390x" "0.17.14" + "@esbuild/linux-x64" "0.17.14" + "@esbuild/netbsd-x64" "0.17.14" + "@esbuild/openbsd-x64" "0.17.14" + "@esbuild/sunos-x64" "0.17.14" + "@esbuild/win32-arm64" "0.17.14" + "@esbuild/win32-ia32" "0.17.14" + "@esbuild/win32-x64" "0.17.14" + escalade@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" @@ -1158,6 +1416,11 @@ fsevents@~2.3.2: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -1168,6 +1431,11 @@ get-caller-file@^2.0.5: resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + get-own-enumerable-property-symbols@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/get-own-enumerable-property-symbols/-/get-own-enumerable-property-symbols-3.0.2.tgz#b5fde77f22cbe35f390b4e089922c50bce6ef664" @@ -1235,6 +1503,13 @@ has-flag@^4.0.0: resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + html-to-react@^1.3.4: version "1.5.0" resolved "https://registry.yarnpkg.com/html-to-react/-/html-to-react-1.5.0.tgz#6e0cf47ae1b091ba2f28a3832389fbce4d199ccc" @@ -1382,6 +1657,13 @@ is-buffer@^2.0.0: resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-2.0.5.tgz#ebc252e400d22ff8d77fa09888821a24a658c191" integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ== +is-core-module@^2.9.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.11.0.tgz#ad4cb3e3863e814523c96f3f58d26cc570ff0144" + integrity sha512-RRjxlvLDkD1YJwDbroBHMb+cukurkDWNyHx7D3oNB5x9rb5ogcksMC5wHCadcXoo67gVr/+3GFySh3134zi6rw== + dependencies: + has "^1.0.3" + is-decimal@^1.0.0: version "1.0.4" resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" @@ -1397,6 +1679,11 @@ is-fullwidth-code-point@^3.0.0: resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== +is-fullwidth-code-point@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz#fae3167c729e7463f8461ce512b080a49268aa88" + integrity sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ== + is-glob@^4.0.1, is-glob@~4.0.1: version "4.0.3" resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" @@ -1479,6 +1766,11 @@ json5@^2.2.2: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + lines-and-columns@^1.1.6: version "1.2.4" resolved "https://registry.yarnpkg.com/lines-and-columns/-/lines-and-columns-1.2.4.tgz#eca284f75d2965079309dc0ad9255abb2ebc1632" @@ -1518,6 +1810,11 @@ listr2@^3.12.2: through "^2.3.8" wrap-ansi "^7.0.0" +local-pkg@^0.4.2: + version "0.4.3" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.4.3.tgz#0ff361ab3ae7f1c19113d9bb97b98b905dbc4963" + integrity sha512-SFppqq5p42fe2qcZQqqEOiVRXl+WCP1MdT6k7BDEW1j++sp5fIY+/fdRQitvKgB5BrBcmrs5m/L0v2FrU5MY1g== + locate-path@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" @@ -1552,6 +1849,13 @@ loose-envify@^1.1.0, loose-envify@^1.4.0: dependencies: js-tokens "^3.0.0 || ^4.0.0" +loupe@^2.3.1, loupe@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -1751,6 +2055,16 @@ mkdirp@^1.0.3, mkdirp@^1.0.4: resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e" integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw== +mlly@^1.1.0, mlly@^1.1.1: + version "1.2.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.2.0.tgz#f0f6c2fc8d2d12ea6907cd869066689b5031b613" + integrity sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww== + dependencies: + acorn "^8.8.2" + pathe "^1.1.0" + pkg-types "^1.0.2" + ufo "^1.1.1" + ms@2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" @@ -1766,6 +2080,11 @@ mylas@^2.1.9: resolved "https://registry.yarnpkg.com/mylas/-/mylas-2.1.13.tgz#1e23b37d58fdcc76e15d8a5ed23f9ae9fc0cbdf4" integrity sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg== +nanoid@^3.3.4: + version "3.3.6" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.6.tgz#443380c856d6e9f9824267d960b4236ad583ea4c" + integrity sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA== + negotiator@^0.6.3: version "0.6.3" resolved "https://registry.yarnpkg.com/negotiator/-/negotiator-0.6.3.tgz#58e323a72fedc0d6f9cd4d31fe49f51479590ccd" @@ -1841,6 +2160,13 @@ p-limit@^3.0.2: dependencies: yocto-queue "^0.1.0" +p-limit@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-4.0.0.tgz#914af6544ed32bfa54670b061cafcbd04984b644" + integrity sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ== + dependencies: + yocto-queue "^1.0.0" + p-locate@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" @@ -1919,11 +2245,26 @@ path-key@^3.0.0, path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + path-type@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== +pathe@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.0.tgz#e2e13f6c62b31a3289af4ba19886c230f295ec03" + integrity sha512-ODbEPR0KKHqECXW1GoxdDb+AZvULmXjVPy4rt+pGo2+TnjJTIPJQSVS6N63n8T2Ip+syHhbn52OewKicV0373w== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + picocolors@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" @@ -1941,6 +2282,15 @@ pkg-dir@^5.0.0: dependencies: find-up "^5.0.0" +pkg-types@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.2.tgz#c233efc5210a781e160e0cafd60c0d0510a4b12e" + integrity sha512-hM58GKXOcj8WTqUXnsQyJYXdeAPbythQgEF3nTcEo+nkD49chjQ9IKm/QJy9xf6JakXptz86h7ecP2024rrLaQ== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.1.1" + pathe "^1.1.0" + please-upgrade-node@^3.2.0: version "3.2.0" resolved "https://registry.yarnpkg.com/please-upgrade-node/-/please-upgrade-node-3.2.0.tgz#aeddd3f994c933e4ad98b99d9a556efa0e2fe942" @@ -1955,11 +2305,29 @@ plimit-lit@^1.2.6: dependencies: queue-lit "^1.5.0" +postcss@^8.4.21: + version "8.4.21" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.21.tgz#c639b719a57efc3187b13a1d765675485f4134f4" + integrity sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg== + dependencies: + nanoid "^3.3.4" + picocolors "^1.0.0" + source-map-js "^1.0.2" + prettier@^2.3.0: version "2.8.4" resolved "https://registry.yarnpkg.com/prettier/-/prettier-2.8.4.tgz#34dd2595629bfbb79d344ac4a91ff948694463c3" integrity sha512-vIS4Rlc2FNh0BySk3Wkd6xmwxB0FpOndW5fisM5H8hsZSxU2VWVB5CWIkIjWvrHjIhxk2g3bfMKM87zNTrZddw== +pretty-format@^27.5.1: + version "27.5.1" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-27.5.1.tgz#2181879fdea51a7a5851fb39d920faa63f01d88e" + integrity sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ== + dependencies: + ansi-regex "^5.0.1" + ansi-styles "^5.0.0" + react-is "^17.0.1" + process-nextick-args@~2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" @@ -2009,6 +2377,11 @@ react-is@^16.13.1, react-is@^16.8.6: resolved "https://registry.yarnpkg.com/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== +react-is@^17.0.1: + version "17.0.2" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" + integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== + react-markdown@^5.0.3: version "5.0.3" resolved "https://registry.yarnpkg.com/react-markdown/-/react-markdown-5.0.3.tgz#41040ea7a9324b564b328fb81dd6c04f2a5373ac" @@ -2079,6 +2452,15 @@ resolve-from@^4.0.0: resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== +resolve@^1.22.1: + version "1.22.1" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.1.tgz#27cb2ebb53f91abb49470a928bba7558066ac177" + integrity sha512-nBpuuYuY5jFsli/JIs1oldw6fOQCBioohqWZg/2hiaOybXOft4lonv85uDOKXdf8rhyK159cxU5cDcK/NKk8zw== + dependencies: + is-core-module "^2.9.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + restore-cursor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/restore-cursor/-/restore-cursor-3.1.0.tgz#39f67c54b3a7a58cea5236d95cf0034239631f7e" @@ -2114,6 +2496,13 @@ rimraf@^3.0.2: dependencies: glob "^7.1.3" +rollup@^3.18.0: + version "3.20.2" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-3.20.2.tgz#f798c600317f216de2e4ad9f4d9ab30a89b690ff" + integrity sha512-3zwkBQl7Ai7MFYQE0y1MeQ15+9jsi7XxfrqwTb/9EK8D9C9+//EBR4M+CuA1KODRaNbFez/lWxA5vhEGZp4MUg== + optionalDependencies: + fsevents "~2.3.2" + run-exclusive@^2.2.18: version "2.2.18" resolved "https://registry.yarnpkg.com/run-exclusive/-/run-exclusive-2.2.18.tgz#ec930edc3a7044750dc827df9372bde8f610f586" @@ -2189,6 +2578,11 @@ shell-quote@^1.7.3: resolved "https://registry.yarnpkg.com/shell-quote/-/shell-quote-1.8.0.tgz#20d078d0eaf71d54f43bd2ba14a1b5b9bfa5c8ba" integrity sha512-QHsz8GgQIGKlRi24yFc6a6lN69Idnx634w49ay6+jA5yFh7a1UY+4Rp6HPx/L/1zcEDPEij8cIsiqR6bQsE5VQ== +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.7" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" @@ -2217,6 +2611,14 @@ slice-ansi@^4.0.0: astral-regex "^2.0.0" is-fullwidth-code-point "^3.0.0" +slice-ansi@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/slice-ansi/-/slice-ansi-5.0.0.tgz#b73063c57aa96f9cd881654b15294d95d285c42a" + integrity sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ== + dependencies: + ansi-styles "^6.0.0" + is-fullwidth-code-point "^4.0.0" + smart-buffer@^4.2.0: version "4.2.0" resolved "https://registry.yarnpkg.com/smart-buffer/-/smart-buffer-4.2.0.tgz#6e1d71fa4f18c05f7d0ff216dd16a481d0e8d9ae" @@ -2239,6 +2641,16 @@ socks@^2.6.2: ip "^2.0.0" smart-buffer "^4.2.0" +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + spawn-command@^0.0.2-1: version "0.0.2-1" resolved "https://registry.yarnpkg.com/spawn-command/-/spawn-command-0.0.2-1.tgz#62f5e9466981c1b796dc5929937e11c9c6921bd0" @@ -2251,6 +2663,16 @@ ssri@^10.0.0: dependencies: minipass "^4.0.0" +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +std-env@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.3.2.tgz#af27343b001616015534292178327b202b9ee955" + integrity sha512-uUZI65yrV2Qva5gqE0+A7uVAvO40iPo6jGhs7s8keRfHCmtg+uB2X6EiLGCI9IgL1J17xGhvoOqSz79lzICPTA== + string-argv@0.3.1: version "0.3.1" resolved "https://registry.yarnpkg.com/string-argv/-/string-argv-0.3.1.tgz#95e2fbec0427ae19184935f816d74aaa4c5c19da" @@ -2265,6 +2687,15 @@ string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^5.0.0: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + string.prototype.codepointat@^0.2.0: version "0.2.1" resolved "https://registry.yarnpkg.com/string.prototype.codepointat/-/string.prototype.codepointat-0.2.1.tgz#004ad44c8afc727527b108cd462b4d971cd469bc" @@ -2298,11 +2729,25 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.0.1.tgz#61740a08ce36b61e50e65653f07060d000975fb2" + integrity sha512-cXNxvT8dFNRVfhVME3JAe98mkXDYN2O1l7jmcwMnOslDeESg1rF/OZMtK0nRAhiari1unG5cD4jG3rapUAkLbw== + dependencies: + ansi-regex "^6.0.1" + strip-final-newline@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-2.0.0.tgz#89b852fb2fcbe936f6f4b3187afb0a12c1ab58ad" integrity sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA== +strip-literal@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-1.0.1.tgz#0115a332710c849b4e46497891fb8d585e404bd2" + integrity sha512-QZTsipNpa2Ppr6v1AmJHESqJ3Uz247MUS0OjrnnZjFAvEoWqxuyFuXn2xLgMtRnijJShAa1HL0gtJyUs7u7n3Q== + dependencies: + acorn "^8.8.2" + supports-color@8.1.1, supports-color@^8.1.0: version "8.1.1" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" @@ -2324,6 +2769,11 @@ supports-color@^7.1.0: dependencies: has-flag "^4.0.0" +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + tar@^6.1.11: version "6.1.13" resolved "https://registry.yarnpkg.com/tar/-/tar-6.1.13.tgz#46e22529000f612180601a6fe0680e7da508847b" @@ -2349,6 +2799,21 @@ through@^2.3.8: resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" integrity sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg== +tinybench@^2.3.1: + version "2.4.0" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.4.0.tgz#83f60d9e5545353610fe7993bd783120bc20c7a7" + integrity sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg== + +tinypool@^0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.4.0.tgz#3cf3ebd066717f9f837e8d7d31af3c127fdb5446" + integrity sha512-2ksntHOKf893wSAH4z/+JbPpi92esw8Gn9N2deXX+B0EO92hexAVI9GIZZPx7P5aYo5KULfeOSt3kMOmSOy6uA== + +tinyspy@^1.0.2: + version "1.1.1" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-1.1.1.tgz#0cb91d5157892af38cb2d217f5c7e8507a5bf092" + integrity sha512-UVq5AXt/gQlti7oxoIg5oi/9r0WpF7DGEVwXgqWSMmyN16+e3tl5lIvTaOpJ3TAtu5xFzWccFRM4R5NaWHF+4g== + to-fast-properties@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" @@ -2417,6 +2882,11 @@ tslib@^2.1.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.0.tgz#42bfed86f5787aeb41d031866c8f402429e0fddf" integrity sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg== +type-detect@^4.0.0, type-detect@^4.0.5: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + type-fest@^0.21.3: version "0.21.3" resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" @@ -2427,6 +2897,11 @@ typescript@^5.0.1-rc: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.2.tgz#891e1a90c5189d8506af64b9ef929fca99ba1ee5" integrity sha512-wVORMBGO/FAs/++blGNeAVdbNKtIh1rbBL2EyQ1+J9lClJ93KiiKe8PmFIVdXhHcyv44SL9oglmfeSsndo0jRw== +ufo@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.1.tgz#e70265e7152f3aba425bd013d150b2cdf4056d7c" + integrity sha512-MvlCc4GHrmZdAllBc0iUDowff36Q9Ndw/UzqmEKyrfSzokTd9ZCy1i+IIk5hrYKkjoYVQyNbrw7/F8XJ2rEwTg== + unified@^9.0.0: version "9.2.2" resolved "https://registry.yarnpkg.com/unified/-/unified-9.2.2.tgz#67649a1abfc3ab85d2969502902775eb03146975" @@ -2533,6 +3008,60 @@ vfile@^4.0.0: unist-util-stringify-position "^2.0.0" vfile-message "^2.0.0" +vite-node@0.29.8: + version "0.29.8" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-0.29.8.tgz#6a1c9d4fb31e7b4e0f825d3a37abe3404e52bd8e" + integrity sha512-b6OtCXfk65L6SElVM20q5G546yu10/kNrhg08afEoWlFRJXFq9/6glsvSVY+aI6YeC1tu2TtAqI2jHEQmOmsFw== + dependencies: + cac "^6.7.14" + debug "^4.3.4" + mlly "^1.1.0" + pathe "^1.1.0" + picocolors "^1.0.0" + vite "^3.0.0 || ^4.0.0" + +"vite@^3.0.0 || ^4.0.0": + version "4.2.1" + resolved "https://registry.yarnpkg.com/vite/-/vite-4.2.1.tgz#6c2eb337b0dfd80a9ded5922163b94949d7fc254" + integrity sha512-7MKhqdy0ISo4wnvwtqZkjke6XN4taqQ2TBaTccLIpOKv7Vp2h4Y+NpmWCnGDeSvvn45KxvWgGyb0MkHvY1vgbg== + dependencies: + esbuild "^0.17.5" + postcss "^8.4.21" + resolve "^1.22.1" + rollup "^3.18.0" + optionalDependencies: + fsevents "~2.3.2" + +vitest@^0.29.8: + version "0.29.8" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-0.29.8.tgz#9c13cfa007c3511e86c26e1fe9a686bb4dbaec80" + integrity sha512-JIAVi2GK5cvA6awGpH0HvH/gEG9PZ0a/WoxdiV3PmqK+3CjQMf8c+J/Vhv4mdZ2nRyXFw66sAg6qz7VNkaHfDQ== + dependencies: + "@types/chai" "^4.3.4" + "@types/chai-subset" "^1.3.3" + "@types/node" "*" + "@vitest/expect" "0.29.8" + "@vitest/runner" "0.29.8" + "@vitest/spy" "0.29.8" + "@vitest/utils" "0.29.8" + acorn "^8.8.1" + acorn-walk "^8.2.0" + cac "^6.7.14" + chai "^4.3.7" + debug "^4.3.4" + local-pkg "^0.4.2" + pathe "^1.1.0" + picocolors "^1.0.0" + source-map "^0.6.1" + std-env "^3.3.1" + strip-literal "^1.0.0" + tinybench "^2.3.1" + tinypool "^0.4.0" + tinyspy "^1.0.2" + vite "^3.0.0 || ^4.0.0" + vite-node "0.29.8" + why-is-node-running "^2.2.2" + webidl-conversions@^3.0.0: version "3.0.1" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" @@ -2558,6 +3087,14 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +why-is-node-running@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e" + integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -2652,6 +3189,11 @@ yocto-queue@^0.1.0: resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== +yocto-queue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== + zod@^3.17.10: version "3.20.6" resolved "https://registry.yarnpkg.com/zod/-/zod-3.20.6.tgz#2f2f08ff81291d47d99e86140fedb4e0db08361a" From 58bb4037870ac3e5f778cd4c268d8380d2b4c14c Mon Sep 17 00:00:00 2001 From: William Will <10997562+willwill96@users.noreply.github.com> Date: Thu, 30 Mar 2023 02:46:25 -0600 Subject: [PATCH 2/6] test: refactor existing tests to vitest --- test/bin/index.ts | 1 - test/bin/main.ts | 1 - ...tic.ts => replaceImportFromStatic.spec.ts} | 460 +++++++++--------- .../{getKcContext.ts => getKcContext.spec.ts} | 99 ++-- test/lib/index.ts | 1 - .../tools/AndByDiscriminatingKey.type.spec.ts | 94 ++++ test/lib/tools/AndByDiscriminatingKey.type.ts | 91 ---- test/tools/assertIsSameCode.ts | 7 - test/tools/isSameCode.ts | 5 + 9 files changed, 367 insertions(+), 392 deletions(-) delete mode 100644 test/bin/index.ts rename test/bin/{replaceImportFromStatic.ts => replaceImportFromStatic.spec.ts} (55%) rename test/lib/{getKcContext.ts => getKcContext.spec.ts} (77%) delete mode 100644 test/lib/index.ts create mode 100644 test/lib/tools/AndByDiscriminatingKey.type.spec.ts delete mode 100644 test/lib/tools/AndByDiscriminatingKey.type.ts delete mode 100644 test/tools/assertIsSameCode.ts create mode 100644 test/tools/isSameCode.ts diff --git a/test/bin/index.ts b/test/bin/index.ts deleted file mode 100644 index 6cbf91c6..00000000 --- a/test/bin/index.ts +++ /dev/null @@ -1 +0,0 @@ -import "./replaceImportFromStatic"; diff --git a/test/bin/main.ts b/test/bin/main.ts index 08be679b..531d4b3d 100644 --- a/test/bin/main.ts +++ b/test/bin/main.ts @@ -1,4 +1,3 @@ -import "./replaceImportFromStatic"; import { setupSampleReactProject, sampleReactProjectDirPath } from "./setupSampleReactProject"; import * as st from "scripting-tools"; import * as fs from "fs"; diff --git a/test/bin/replaceImportFromStatic.ts b/test/bin/replaceImportFromStatic.spec.ts similarity index 55% rename from test/bin/replaceImportFromStatic.ts rename to test/bin/replaceImportFromStatic.spec.ts index e66d97a3..c7894aca 100644 --- a/test/bin/replaceImportFromStatic.ts +++ b/test/bin/replaceImportFromStatic.spec.ts @@ -1,11 +1,12 @@ import { replaceImportsFromStaticInJsCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsFromStaticInJsCode"; import { generateCssCodeToDefineGlobals, replaceImportsInCssCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsInCssCode"; import { replaceImportsInInlineCssCode } from "keycloakify/bin/keycloakify/replacers/replaceImportsInInlineCssCode"; -import { assert } from "tsafe/assert"; import { same } from "evt/tools/inDepth/same"; -import { assetIsSameCode } from "../tools/assertIsSameCode"; +import { expect, it, describe } from "vitest"; -{ +import { isSameCode } from "../tools/isSameCode"; + +describe("bin/js-transforms", () => { const jsCodeUntransformed = ` function f() { return a.p+"static/js/" + ({}[e] || e) + "." + { @@ -32,8 +33,7 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; }[e]+".chunk.css" } `; - - { + it("transforms standalone code properly", () => { const { fixedJsCode } = replaceImportsFromStaticInJsCode({ "jsCode": jsCodeUntransformed, "buildOptions": { @@ -89,10 +89,9 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; `; - assetIsSameCode(fixedJsCode, fixedJsCodeExpected); - } - - { + expect(isSameCode(fixedJsCode, fixedJsCodeExpected)).toBe(true); + }); + it("transforms external app code properly", () => { const { fixedJsCode } = replaceImportsFromStaticInJsCode({ "jsCode": jsCodeUntransformed, "buildOptions": { @@ -150,126 +149,128 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; } `; - assetIsSameCode(fixedJsCode, fixedJsCodeExpected); - } -} + expect(isSameCode(fixedJsCode, fixedJsCodeExpected)).toBe(true); + }); +}); -{ - const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({ - "cssCode": ` +describe("bin/css-transforms", () => { + it("transforms absolute urls to css globals properly with no urlPathname", () => { + const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({ + "cssCode": ` + .my-div { + background: url(/logo192.png) no-repeat center center; + } + + .my-div2 { + background: url(/logo192.png) no-repeat center center; + } + + .my-div { + background-image: url(/static/media/something.svg); + } + ` + }); + + const fixedCssCodeExpected = ` .my-div { - background: url(/logo192.png) no-repeat center center; + background: var(--url1f9ef5a892c104c); } - + .my-div2 { - background: url(/logo192.png) no-repeat center center; + background: var(--url1f9ef5a892c104c); } - + .my-div { - background-image: url(/static/media/something.svg); + background-image: var(--urldd75cab58377c19); } - ` + `; + + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); + + const cssGlobalsToDefineExpected = { + "url1f9ef5a892c104c": "url(/logo192.png) no-repeat center center", + "urldd75cab58377c19": "url(/static/media/something.svg)" + }; + + expect(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)).toBe(true); + + const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({ + cssGlobalsToDefine, + "buildOptions": { + "urlPathname": undefined + } + }); + + const cssCodeToPrependInHeadExpected = ` + :root { + --url1f9ef5a892c104c: url(\${url.resourcesPath}/build/logo192.png) no-repeat center center; + --urldd75cab58377c19: url(\${url.resourcesPath}/build/static/media/something.svg); + } + `; + + expect(isSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected)).toBe(true); }); + it("transforms absolute urls to css globals properly with custom urlPathname", () => { + const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({ + "cssCode": ` + .my-div { + background: url(/x/y/z/logo192.png) no-repeat center center; + } + + .my-div2 { + background: url(/x/y/z/logo192.png) no-repeat center center; + } + + .my-div { + background-image: url(/x/y/z/static/media/something.svg); + } + ` + }); - const fixedCssCodeExpected = ` - .my-div { - background: var(--url1f9ef5a892c104c); - } - - .my-div2 { - background: var(--url1f9ef5a892c104c); - } - - .my-div { - background-image: var(--urldd75cab58377c19); - } - `; - - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - - const cssGlobalsToDefineExpected = { - "url1f9ef5a892c104c": "url(/logo192.png) no-repeat center center", - "urldd75cab58377c19": "url(/static/media/something.svg)" - }; - - assert(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)); - - const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({ - cssGlobalsToDefine, - "buildOptions": { - "urlPathname": undefined - } - }); - - const cssCodeToPrependInHeadExpected = ` - :root { - --url1f9ef5a892c104c: url(\${url.resourcesPath}/build/logo192.png) no-repeat center center; - --urldd75cab58377c19: url(\${url.resourcesPath}/build/static/media/something.svg); - } - `; - - assetIsSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected); -} - -{ - const { fixedCssCode, cssGlobalsToDefine } = replaceImportsInCssCode({ - "cssCode": ` + const fixedCssCodeExpected = ` .my-div { - background: url(/x/y/z/logo192.png) no-repeat center center; + background: var(--urlf8277cddaa2be78); } - + .my-div2 { - background: url(/x/y/z/logo192.png) no-repeat center center; + background: var(--urlf8277cddaa2be78); } - + .my-div { - background-image: url(/x/y/z/static/media/something.svg); + background-image: var(--url8bdc0887b97ac9a); } - ` + `; + + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); + + const cssGlobalsToDefineExpected = { + "urlf8277cddaa2be78": "url(/x/y/z/logo192.png) no-repeat center center", + "url8bdc0887b97ac9a": "url(/x/y/z/static/media/something.svg)" + }; + + expect(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)).toBe(true); + + const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({ + cssGlobalsToDefine, + "buildOptions": { + "urlPathname": "/x/y/z/" + } + }); + + const cssCodeToPrependInHeadExpected = ` + :root { + --urlf8277cddaa2be78: url(\${url.resourcesPath}/build/logo192.png) no-repeat center center; + --url8bdc0887b97ac9a: url(\${url.resourcesPath}/build/static/media/something.svg); + } + `; + + expect(isSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected)).toBe(true); }); +}); - const fixedCssCodeExpected = ` - .my-div { - background: var(--urlf8277cddaa2be78); - } - - .my-div2 { - background: var(--urlf8277cddaa2be78); - } - - .my-div { - background-image: var(--url8bdc0887b97ac9a); - } - `; - - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - - const cssGlobalsToDefineExpected = { - "urlf8277cddaa2be78": "url(/x/y/z/logo192.png) no-repeat center center", - "url8bdc0887b97ac9a": "url(/x/y/z/static/media/something.svg)" - }; - - assert(same(cssGlobalsToDefine, cssGlobalsToDefineExpected)); - - const { cssCodeToPrependInHead } = generateCssCodeToDefineGlobals({ - cssGlobalsToDefine, - "buildOptions": { - "urlPathname": "/x/y/z/" - } - }); - - const cssCodeToPrependInHeadExpected = ` - :root { - --urlf8277cddaa2be78: url(\${url.resourcesPath}/build/logo192.png) no-repeat center center; - --url8bdc0887b97ac9a: url(\${url.resourcesPath}/build/static/media/something.svg); - } - `; - - assetIsSameCode(cssCodeToPrependInHead, cssCodeToPrependInHeadExpected); -} - -{ - const cssCode = ` +describe("bin/css-inline-transforms", () => { + describe("no url pathName", () => { + const cssCode = ` @font-face { font-family: "Work Sans"; font-style: normal; @@ -299,17 +300,16 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; src: url("/fonts/WorkSans/worksans-bold-webfont.woff2") format("woff2"); } `; + it("transforms css for standalone app properly", () => { + const { fixedCssCode } = replaceImportsInInlineCssCode({ + cssCode, + "buildOptions": { + "isStandalone": true, + "urlPathname": undefined + } + }); - { - const { fixedCssCode } = replaceImportsInInlineCssCode({ - cssCode, - "buildOptions": { - "isStandalone": true, - "urlPathname": undefined - } - }); - - const fixedCssCodeExpected = ` + const fixedCssCodeExpected = ` @font-face { font-family: "Work Sans"; font-style: normal; @@ -344,20 +344,19 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; } `; - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - } - - { - const { fixedCssCode } = replaceImportsInInlineCssCode({ - cssCode, - "buildOptions": { - "isStandalone": false, - "urlOrigin": "https://demo-app.keycloakify.dev", - "urlPathname": undefined - } + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); }); + it("transforms css for external app properly", () => { + const { fixedCssCode } = replaceImportsInInlineCssCode({ + cssCode, + "buildOptions": { + "isStandalone": false, + "urlOrigin": "https://demo-app.keycloakify.dev", + "urlPathname": undefined + } + }); - const fixedCssCodeExpected = ` + const fixedCssCodeExpected = ` @font-face { font-family: "Work Sans"; font-style: normal; @@ -392,12 +391,12 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; } `; - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - } -} + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); + }); + }); -{ - const cssCode = ` + describe("with url pathName", () => { + const cssCode = ` @font-face { font-family: "Work Sans"; font-style: normal; @@ -427,101 +426,98 @@ import { assetIsSameCode } from "../tools/assertIsSameCode"; src: url("/x/y/z/fonts/WorkSans/worksans-bold-webfont.woff2") format("woff2"); } `; + it("transforms css for standalone app properly", () => { + const { fixedCssCode } = replaceImportsInInlineCssCode({ + cssCode, + "buildOptions": { + "isStandalone": true, + "urlPathname": "/x/y/z/" + } + }); - { - const { fixedCssCode } = replaceImportsInInlineCssCode({ - cssCode, - "buildOptions": { - "isStandalone": true, - "urlPathname": "/x/y/z/" - } + const fixedCssCodeExpected = ` + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-regular-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-medium-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-semibold-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-bold-webfont.woff2) + format("woff2"); + } + `; + + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); }); + it("transforms css for external app properly", () => { + const { fixedCssCode } = replaceImportsInInlineCssCode({ + cssCode, + "buildOptions": { + "isStandalone": false, + "urlOrigin": "https://demo-app.keycloakify.dev", + "urlPathname": "/x/y/z/" + } + }); - const fixedCssCodeExpected = ` - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-regular-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-medium-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-semibold-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(\${url.resourcesPath}/build/fonts/WorkSans/worksans-bold-webfont.woff2) - format("woff2"); - } - `; + const fixedCssCodeExpected = ` + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 400; + font-display: swap; + src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-regular-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 500; + font-display: swap; + src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-medium-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 600; + font-display: swap; + src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-semibold-webfont.woff2) + format("woff2"); + } + @font-face { + font-family: "Work Sans"; + font-style: normal; + font-weight: 700; + font-display: swap; + src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-bold-webfont.woff2) + format("woff2"); + } + `; - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - } - - { - const { fixedCssCode } = replaceImportsInInlineCssCode({ - cssCode, - "buildOptions": { - "isStandalone": false, - "urlOrigin": "https://demo-app.keycloakify.dev", - "urlPathname": "/x/y/z/" - } + expect(isSameCode(fixedCssCode, fixedCssCodeExpected)).toBe(true); }); - - const fixedCssCodeExpected = ` - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 400; - font-display: swap; - src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-regular-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 500; - font-display: swap; - src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-medium-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 600; - font-display: swap; - src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-semibold-webfont.woff2) - format("woff2"); - } - @font-face { - font-family: "Work Sans"; - font-style: normal; - font-weight: 700; - font-display: swap; - src: url(https://demo-app.keycloakify.dev/x/y/z/fonts/WorkSans/worksans-bold-webfont.woff2) - format("woff2"); - } - `; - - assetIsSameCode(fixedCssCode, fixedCssCodeExpected); - } -} - -console.log("PASS replace import from static"); + }); +}); diff --git a/test/lib/getKcContext.ts b/test/lib/getKcContext.spec.ts similarity index 77% rename from test/lib/getKcContext.ts rename to test/lib/getKcContext.spec.ts index f52364aa..20023fff 100644 --- a/test/lib/getKcContext.ts +++ b/test/lib/getKcContext.spec.ts @@ -1,13 +1,14 @@ -import { getKcContext } from "../../src/login/kcContext/getKcContext"; -import type { ExtendKcContext } from "../../src/login/kcContext/getKcContextFromWindow"; -import type { KcContext } from "../../src/login/kcContext"; +import { getKcContext } from "keycloakify/login/kcContext/getKcContext"; +import type { ExtendKcContext } from "keycloakify/login/kcContext/getKcContextFromWindow"; +import type { KcContext } from "keycloakify/login/kcContext"; import { same } from "evt/tools/inDepth"; import { assert } from "tsafe/assert"; import type { Equals } from "tsafe"; -import { kcContextMocks, kcContextCommonMock } from "../../src/login/kcContext/kcContextMocks"; -import { deepClone } from "../../src/tools/deepClone"; +import { kcContextMocks, kcContextCommonMock } from "keycloakify/login/kcContext/kcContextMocks"; +import { deepClone } from "keycloakify/tools/deepClone"; +import { expect, it, describe } from "vitest"; -{ +describe("getKcContext", () => { const authorizedMailDomains = ["example.com", "another-example.com", "*.yet-another-example.com", "*.example.com", "hello-world.com"]; const displayName = "this is an overwritten common value"; @@ -59,8 +60,7 @@ import { deepClone } from "../../src/tools/deepClone"; return { kcContext }; }; - - { + it("has proper API for login.ftl", () => { const pageId = "login.ftl"; const { kcContext } = getKcContextProxy({ "mockPageId": pageId }); @@ -69,7 +69,7 @@ import { deepClone } from "../../src/tools/deepClone"; assert>(); - assert( + expect( same( //NOTE: deepClone for printIfExists or other functions... deepClone(kcContext), @@ -81,12 +81,10 @@ import { deepClone } from "../../src/tools/deepClone"; return mock; })() ) - ); + ).toBe(true); + }); - console.log(`PASS ${pageId}`); - } - - { + it("has a proper API for info.ftl", () => { const pageId = "info.ftl"; const { kcContext } = getKcContextProxy({ "mockPageId": pageId }); @@ -104,7 +102,7 @@ import { deepClone } from "../../src/tools/deepClone"; > >(); - assert( + expect( same( deepClone(kcContext), (() => { @@ -115,12 +113,9 @@ import { deepClone } from "../../src/tools/deepClone"; return mock; })() ) - ); - - console.log(`PASS ${pageId}`); - } - - { + ).toBe(true); + }); + it("has a proper API for register.ftl", () => { const pageId = "register.ftl"; const { kcContext } = getKcContextProxy({ "mockPageId": pageId }); @@ -138,7 +133,7 @@ import { deepClone } from "../../src/tools/deepClone"; > >(); - assert( + expect( same( deepClone(kcContext), (() => { @@ -149,12 +144,9 @@ import { deepClone } from "../../src/tools/deepClone"; return mock; })() ) - ); - - console.log(`PASS ${pageId}`); - } - - { + ).toBe(true); + }); + it("has a proper API for my-extra-page-2.ftl", () => { const pageId = "my-extra-page-2.ftl"; const { kcContext } = getKcContextProxy({ "mockPageId": pageId }); @@ -173,7 +165,7 @@ import { deepClone } from "../../src/tools/deepClone"; kcContext.aNonStandardValue2; - assert( + expect( same( deepClone(kcContext), (() => { @@ -184,12 +176,9 @@ import { deepClone } from "../../src/tools/deepClone"; return mock; })() ) - ); - - console.log(`PASS ${pageId}`); - } - - { + ).toBe(true); + }); + it("has a proper API for my-extra-page-1.ftl", () => { const pageId = "my-extra-page-1.ftl"; console.log("We expect a warning here =>"); @@ -200,7 +189,7 @@ import { deepClone } from "../../src/tools/deepClone"; assert>(); - assert( + expect( same( deepClone(kcContext), (() => { @@ -211,32 +200,24 @@ import { deepClone } from "../../src/tools/deepClone"; return mock; })() ) - ); - - console.log(`PASS ${pageId}`); - } -} - -{ - const pageId = "login.ftl"; - - const { kcContext } = getKcContext({ - "mockPageId": pageId + ).toBe(true); }); + it("returns the proper mock for login.ftl", () => { + const pageId = "login.ftl"; - assert>(); + const { kcContext } = getKcContext({ + "mockPageId": pageId + }); - assert(same(deepClone(kcContext), deepClone(kcContextMocks.find(({ pageId: pageId_i }) => pageId_i === pageId)!))); + assert>(); - console.log("PASS no extension"); -} + assert(same(deepClone(kcContext), deepClone(kcContextMocks.find(({ pageId: pageId_i }) => pageId_i === pageId)!))); + }); + it("returns the proper mock for login.ftl", () => { + const { kcContext } = getKcContext(); -{ - const { kcContext } = getKcContext(); + assert>(); - assert>(); - - assert(kcContext === undefined); - - console.log("PASS no extension, no mock"); -} + assert(kcContext === undefined); + }); +}); diff --git a/test/lib/index.ts b/test/lib/index.ts deleted file mode 100644 index 8df0b5d4..00000000 --- a/test/lib/index.ts +++ /dev/null @@ -1 +0,0 @@ -import "./getKcContext"; diff --git a/test/lib/tools/AndByDiscriminatingKey.type.spec.ts b/test/lib/tools/AndByDiscriminatingKey.type.spec.ts new file mode 100644 index 00000000..8edb9f87 --- /dev/null +++ b/test/lib/tools/AndByDiscriminatingKey.type.spec.ts @@ -0,0 +1,94 @@ +import { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey"; +import { assert } from "tsafe/assert"; +import type { Equals } from "tsafe"; +import { it, describe } from "vitest"; + +// These test case names are intentionally vague, because I'm not sure what each are testing individually +describe("AndByDiscriminatingKey", () => { + it("Test Case 1", () => { + type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; + + type Extension = { pageId: "a"; onlyExtA: string } | { pageId: "b"; onlyExtB: string } | { pageId: "only ext"; onlyExt: string }; + + type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; + + type Expected = + | { pageId: "a"; onlyA: string; onlyExtA: string } + | { pageId: "b"; onlyB: string; onlyExtB: string } + | { pageId: "only base"; onlyBase: string } + | { pageId: "only ext"; onlyExt: string }; + + assert>(); + + const x: Got = {} as any; + + if (x.pageId === "a") { + x.onlyA; + x.onlyExtA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyBase; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "b") { + x.onlyB; + x.onlyExtB; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyBase; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "only base") { + x.onlyBase; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "only ext") { + x.onlyExt; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyBase; + } + }); + it("Test Case 2", () => { + type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; + + type Extension = { pageId: "only ext"; onlyExt: string }; + + type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; + + type Expected = + | { pageId: "a"; onlyA: string } + | { pageId: "b"; onlyB: string } + | { pageId: "only base"; onlyBase: string } + | { pageId: "only ext"; onlyExt: string }; + + assert>(); + }); +}); diff --git a/test/lib/tools/AndByDiscriminatingKey.type.ts b/test/lib/tools/AndByDiscriminatingKey.type.ts deleted file mode 100644 index f45e897f..00000000 --- a/test/lib/tools/AndByDiscriminatingKey.type.ts +++ /dev/null @@ -1,91 +0,0 @@ -import { AndByDiscriminatingKey } from "../../../src/tools/AndByDiscriminatingKey"; -import { assert } from "tsafe/assert"; -import type { Equals } from "tsafe"; - -{ - type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; - - type Extension = { pageId: "a"; onlyExtA: string } | { pageId: "b"; onlyExtB: string } | { pageId: "only ext"; onlyExt: string }; - - type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; - - type Expected = - | { pageId: "a"; onlyA: string; onlyExtA: string } - | { pageId: "b"; onlyB: string; onlyExtB: string } - | { pageId: "only base"; onlyBase: string } - | { pageId: "only ext"; onlyExt: string }; - - assert>(); - - const x: Got = null as any; - - if (x.pageId === "a") { - x.onlyA; - x.onlyExtA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyBase; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "b") { - x.onlyB; - x.onlyExtB; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyBase; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "only base") { - x.onlyBase; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "only ext") { - x.onlyExt; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyBase; - } -} - -{ - type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; - - type Extension = { pageId: "only ext"; onlyExt: string }; - - type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; - - type Expected = - | { pageId: "a"; onlyA: string } - | { pageId: "b"; onlyB: string } - | { pageId: "only base"; onlyBase: string } - | { pageId: "only ext"; onlyExt: string }; - - assert>(); -} diff --git a/test/tools/assertIsSameCode.ts b/test/tools/assertIsSameCode.ts deleted file mode 100644 index b63cb822..00000000 --- a/test/tools/assertIsSameCode.ts +++ /dev/null @@ -1,7 +0,0 @@ -import { assert } from "tsafe/assert"; - -export function assetIsSameCode(code1: string, code2: string, message?: string): void { - const removeSpacesAndNewLines = (code: string) => code.replace(/\s/g, "").replace(/\n/g, ""); - - assert(removeSpacesAndNewLines(code1) === removeSpacesAndNewLines(code2), message); -} diff --git a/test/tools/isSameCode.ts b/test/tools/isSameCode.ts new file mode 100644 index 00000000..6d62a225 --- /dev/null +++ b/test/tools/isSameCode.ts @@ -0,0 +1,5 @@ +export function isSameCode(code1: string, code2: string): boolean { + const removeSpacesAndNewLines = (code: string) => code.replace(/\s/g, "").replace(/\n/g, ""); + + return removeSpacesAndNewLines(code1) === removeSpacesAndNewLines(code2); +} From e527f043b08c4090b6dae56c7025a0dc0a10b5df Mon Sep 17 00:00:00 2001 From: William Will <10997562+willwill96@users.noreply.github.com> Date: Thu, 30 Mar 2023 02:46:44 -0600 Subject: [PATCH 3/6] test: add test for valid jar artifacts --- test/bin/jar.spec.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 test/bin/jar.spec.ts diff --git a/test/bin/jar.spec.ts b/test/bin/jar.spec.ts new file mode 100644 index 00000000..7f19b3d3 --- /dev/null +++ b/test/bin/jar.spec.ts @@ -0,0 +1,26 @@ +import jar from "keycloakify/bin/tools/jar"; +import { it, describe, vi } from "vitest"; + +vi.mock("fs", () => ({ promises: { mkdir: () => {} }, createWriteStream: () => {} })); +vi.mock("stream", async () => { + const readableMock = () => { + const mockDecorators = { + on: () => mockDecorators, + pipe: () => mockDecorators + }; + return { + from: () => mockDecorators + }; + }; + + return { + // @ts-ignore + ...(await vi.importActual("stream")), + Readable: readableMock() + }; +}); +describe("jar", () => { + it("creates jar artifacts without error", () => { + jar({ artifactId: "artifactId", groupId: "groupId", rootPath: "rootPath", targetPath: "targetPath", version: "1.0.0" }); + }); +}); From b863d9feb334c40ca373425de86d3f67de51eb44 Mon Sep 17 00:00:00 2001 From: William Will <10997562+willwill96@users.noreply.github.com> Date: Thu, 30 Mar 2023 02:47:54 -0600 Subject: [PATCH 4/6] chore: add .devcontainer file --- .gitignore | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 604525fa..c28b34d0 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,7 @@ jspm_packages /keycloak_email /build_keycloak /src/login/i18n/baseMessages/ -/src/account/i18n/baseMessages/ \ No newline at end of file +/src/account/i18n/baseMessages/ + +# VS Code devcontainers +.devcontainer \ No newline at end of file From 4ebc1e671f0d6228ef043845eec3990e3b4d286d Mon Sep 17 00:00:00 2001 From: William Will <10997562+willwill96@users.noreply.github.com> Date: Thu, 30 Mar 2023 22:09:27 +0000 Subject: [PATCH 5/6] feat(config): add ability to customize input/output directory --- .gitignore | 4 +- .prettierignore | 7 ++- package.json | 4 +- scripts/test-keycloakify-starter.ts | 29 +++++++++ src/bin/download-builtin-keycloak-theme.ts | 7 +-- src/bin/eject-keycloak-page.ts | 2 +- src/bin/getThemeSrcDirPath.ts | 33 ---------- src/bin/initialize-email-theme.ts | 12 +--- src/bin/keycloakify/BuildOptions.ts | 64 ++++--------------- src/bin/keycloakify/build-paths.ts | 72 ++++++++++++++++++++++ src/bin/keycloakify/index.ts | 2 +- src/bin/keycloakify/keycloakify.ts | 28 ++++----- src/bin/keycloakify/parsed-package-json.ts | 58 +++++++++++++++++ test/bin/generateKeycloakThemeResources.ts | 20 ------ test/bin/main.ts | 25 -------- test/bin/setupCustomReactProject.spec.ts | 62 +++++++++++++++++++ test/bin/setupSampleReactProject.spec.ts | 59 ++++++++++++++++++ test/bin/setupSampleReactProject.ts | 8 +-- vitest.config.ts | 3 +- 19 files changed, 325 insertions(+), 174 deletions(-) create mode 100644 scripts/test-keycloakify-starter.ts delete mode 100644 src/bin/getThemeSrcDirPath.ts create mode 100644 src/bin/keycloakify/build-paths.ts create mode 100644 src/bin/keycloakify/parsed-package-json.ts delete mode 100644 test/bin/generateKeycloakThemeResources.ts delete mode 100644 test/bin/main.ts create mode 100644 test/bin/setupCustomReactProject.spec.ts create mode 100644 test/bin/setupSampleReactProject.spec.ts diff --git a/.gitignore b/.gitignore index c28b34d0..1c905308 100644 --- a/.gitignore +++ b/.gitignore @@ -41,9 +41,11 @@ jspm_packages .DS_Store /dist +# Test Build Directories /dist_test - /sample_react_project/ +/sample_custom_react_project/ +/keycloakify_starter_test/ /.yarn_home/ .idea diff --git a/.prettierignore b/.prettierignore index 896a774d..48693ecf 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,12 +1,15 @@ node_modules/ /dist/ -/dist_test/ /CHANGELOG.md /.yarn_home/ /src/test/apps/ /src/tools/types/ -/sample_react_project /build_keycloak/ /.vscode/ /src/login/i18n/baseMessages/ /src/account/i18n/baseMessages/ +# Test Build Directories +/dist_test +/sample_react_project/ +/sample_custom_react_project/ +/keycloakify_starter_test/ \ No newline at end of file diff --git a/package.json b/package.json index 8f38ac39..e7a16dda 100644 --- a/package.json +++ b/package.json @@ -12,11 +12,11 @@ "prepare": "yarn generate-i18n-messages", "build": "rimraf dist/ && tsc -p src/bin && tsc -p src/tsconfig.json && tsc-alias -p src/tsconfig.json && yarn grant-exec-perms && yarn copy-files dist/", "build:watch": "tsc -p src/tsconfig.json && (concurrently \"tsc -p src/tsconfig.json -w\" \"tsc-alias -p src/tsconfig.json\")", - "test:types": "tsc -p test/tsconfig.json --noEmit", "grant-exec-perms": "node dist/bin/tools/grant-exec-perms.js", "copy-files": "copyfiles -u 1 src/**/*.ftl", "test": "yarn test:types && vitest run", - "test:sample-app": "yarn build:test && node dist_test/test/bin/main.js", + "test:keycloakify-starter": "ts-node scripts/test-keycloakify-starter", + "test:types": "tsc -p test/tsconfig.json --noEmit", "_format": "prettier '**/*.{ts,tsx,json,md}'", "format": "yarn _format --write", "format:check": "yarn _format --list-different", diff --git a/scripts/test-keycloakify-starter.ts b/scripts/test-keycloakify-starter.ts new file mode 100644 index 00000000..f443fa39 --- /dev/null +++ b/scripts/test-keycloakify-starter.ts @@ -0,0 +1,29 @@ +import { execSync } from "child_process"; +import { existsSync, readFileSync, rmSync, writeFileSync } from "fs"; +import path from "path"; + +const testDir = "keycloakify_starter_test"; + +if (existsSync(path.join(process.cwd(), testDir))) { + rmSync(path.join(process.cwd(), testDir), { recursive: true }); +} +// Build and link package +execSync("yarn build"); +const pkgJSON = JSON.parse(readFileSync(path.join(process.cwd(), "package.json")).toString("utf8")); +pkgJSON.main = "./index.js"; +pkgJSON.types = "./index.d.ts"; +pkgJSON.scripts.prepare = undefined; +writeFileSync(path.join(process.cwd(), "dist", "package.json"), JSON.stringify(pkgJSON)); +// Wrapped in a try/catch because unlink errors if the package isn't linked +try { + execSync("yarn unlink"); +} catch {} +execSync("yarn link", { cwd: path.join(process.cwd(), "dist") }); + +// Clone latest keycloakify-starter and link to keycloakify output +execSync(`git clone https://github.com/keycloakify/keycloakify-starter.git ${testDir}`); +execSync("yarn install", { cwd: path.join(process.cwd(), testDir) }); +execSync("yarn link keycloakify", { cwd: path.join(process.cwd(), testDir) }); + +//Ensure keycloak theme can be built +execSync("yarn build-keycloak-theme", { cwd: path.join(process.cwd(), testDir) }); diff --git a/src/bin/download-builtin-keycloak-theme.ts b/src/bin/download-builtin-keycloak-theme.ts index d09188b3..e3ac6ba3 100644 --- a/src/bin/download-builtin-keycloak-theme.ts +++ b/src/bin/download-builtin-keycloak-theme.ts @@ -1,11 +1,10 @@ #!/usr/bin/env node - -import { keycloakThemeBuildingDirPath } from "./keycloakify"; import { join as pathJoin } from "path"; import { downloadAndUnzip } from "./tools/downloadAndUnzip"; import { promptKeycloakVersion } from "./promptKeycloakVersion"; import { getCliOptions } from "./tools/cliOptions"; import { getLogger } from "./tools/logger"; +import { getKeycloakBuildPath } from "./keycloakify/build-paths"; export async function downloadBuiltinKeycloakTheme(params: { keycloakVersion: string; destDirPath: string; isSilent: boolean }) { const { keycloakVersion, destDirPath } = params; @@ -26,7 +25,7 @@ async function main() { const logger = getLogger({ isSilent }); const { keycloakVersion } = await promptKeycloakVersion(); - const destDirPath = pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources", "theme"); + const destDirPath = pathJoin(getKeycloakBuildPath(), "src", "main", "resources", "theme"); logger.log(`Downloading builtins theme of Keycloak ${keycloakVersion} here ${destDirPath}`); @@ -38,5 +37,5 @@ async function main() { } if (require.main === module) { - main().catch(e => console.error(e)); + main(); } diff --git a/src/bin/eject-keycloak-page.ts b/src/bin/eject-keycloak-page.ts index 1d221f92..f6094c54 100644 --- a/src/bin/eject-keycloak-page.ts +++ b/src/bin/eject-keycloak-page.ts @@ -16,7 +16,7 @@ import { existsSync } from "fs"; import { join as pathJoin, relative as pathRelative } from "path"; import { kebabCaseToCamelCase } from "./tools/kebabCaseToSnakeCase"; import { assert, Equals } from "tsafe/assert"; -import { getThemeSrcDirPath } from "./getThemeSrcDirPath"; +import { getThemeSrcDirPath } from "./keycloakify/build-paths"; (async () => { const projectRootDir = getProjectRoot(); diff --git a/src/bin/getThemeSrcDirPath.ts b/src/bin/getThemeSrcDirPath.ts deleted file mode 100644 index ee9db95b..00000000 --- a/src/bin/getThemeSrcDirPath.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { join as pathJoin } from "path"; -import * as fs from "fs"; -import { crawl } from "./tools/crawl"; -import { exclude } from "tsafe/exclude"; - -const reactProjectDirPath = process.cwd(); - -const themeSrcDirBasename = "keycloak-theme"; - -export function getThemeSrcDirPath() { - const srcDirPath = pathJoin(reactProjectDirPath, "src"); - - const themeSrcDirPath: string | undefined = crawl(srcDirPath) - .map(fileRelativePath => { - const split = fileRelativePath.split(themeSrcDirBasename); - - if (split.length !== 2) { - return undefined; - } - - return pathJoin(srcDirPath, split[0] + themeSrcDirBasename); - }) - .filter(exclude(undefined))[0]; - - if (themeSrcDirPath === undefined) { - if (fs.existsSync(pathJoin(srcDirPath, "login")) || fs.existsSync(pathJoin(srcDirPath, "account"))) { - return { "themeSrcDirPath": srcDirPath }; - } - return { "themeSrcDirPath": undefined }; - } - - return { themeSrcDirPath }; -} diff --git a/src/bin/initialize-email-theme.ts b/src/bin/initialize-email-theme.ts index 44207026..5f08f811 100644 --- a/src/bin/initialize-email-theme.ts +++ b/src/bin/initialize-email-theme.ts @@ -7,17 +7,9 @@ import { promptKeycloakVersion } from "./promptKeycloakVersion"; import * as fs from "fs"; import { getCliOptions } from "./tools/cliOptions"; import { getLogger } from "./tools/logger"; -import { getThemeSrcDirPath } from "./getThemeSrcDirPath"; +import { getEmailThemeSrcDirPath } from "./keycloakify/build-paths"; -export function getEmailThemeSrcDirPath() { - const { themeSrcDirPath } = getThemeSrcDirPath(); - - const emailThemeSrcDirPath = themeSrcDirPath === undefined ? undefined : pathJoin(themeSrcDirPath, "email"); - - return { emailThemeSrcDirPath }; -} - -async function main() { +export async function main() { const { isSilent } = getCliOptions(process.argv.slice(2)); const logger = getLogger({ isSilent }); diff --git a/src/bin/keycloakify/BuildOptions.ts b/src/bin/keycloakify/BuildOptions.ts index 6450f766..f0972b8b 100644 --- a/src/bin/keycloakify/BuildOptions.ts +++ b/src/bin/keycloakify/BuildOptions.ts @@ -1,51 +1,10 @@ -import { z } from "zod"; import { assert } from "tsafe/assert"; -import type { Equals } from "tsafe"; import { id } from "tsafe/id"; import { parse as urlParse } from "url"; import { typeGuard } from "tsafe/typeGuard"; import { symToStr } from "tsafe/symToStr"; - -const bundlers = ["mvn", "keycloakify", "none"] as const; -type Bundler = (typeof bundlers)[number]; -type ParsedPackageJson = { - name: string; - version: string; - homepage?: string; - keycloakify?: { - /** @deprecated: use extraLoginPages instead */ - extraPages?: string[]; - extraLoginPages?: string[]; - extraAccountPages?: string[]; - extraThemeProperties?: string[]; - areAppAndKeycloakServerSharingSameDomain?: boolean; - artifactId?: string; - groupId?: string; - bundler?: Bundler; - keycloakVersionDefaultAssets?: string; - }; -}; - -const zParsedPackageJson = z.object({ - "name": z.string(), - "version": z.string(), - "homepage": z.string().optional(), - "keycloakify": z - .object({ - "extraPages": z.array(z.string()).optional(), - "extraLoginPages": z.array(z.string()).optional(), - "extraAccountPages": z.array(z.string()).optional(), - "extraThemeProperties": z.array(z.string()).optional(), - "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(), - "artifactId": z.string().optional(), - "groupId": z.string().optional(), - "bundler": z.enum(bundlers).optional(), - "keycloakVersionDefaultAssets": z.string().optional() - }) - .optional() -}); - -assert, ParsedPackageJson>>(); +import { Bundler, bundlers, getParsedPackageJson } from "./parsed-package-json"; +import { getAppInputPath, getKeycloakBuildPath } from "./build-paths"; /** Consolidated build option gathered form CLI arguments and config in package.json */ export type BuildOptions = BuildOptions.Standalone | BuildOptions.ExternalAssets; @@ -62,6 +21,10 @@ export namespace BuildOptions { artifactId: string; bundler: Bundler; keycloakVersionDefaultAssets: string; + // Directory of your built react project. Defaults to {cwd}/build + appInputPath: string; + // Directory that keycloakify outputs to. Defaults to {cwd}/build_keycloak + keycloakBuildPath: string; }; export type Standalone = Common & { @@ -88,15 +51,10 @@ export namespace BuildOptions { } } -export function readBuildOptions(params: { - packageJson: string; - CNAME: string | undefined; - isExternalAssetsCliParamProvided: boolean; - isSilent: boolean; -}): BuildOptions { - const { packageJson, CNAME, isExternalAssetsCliParamProvided, isSilent } = params; +export function readBuildOptions(params: { CNAME: string | undefined; isExternalAssetsCliParamProvided: boolean; isSilent: boolean }): BuildOptions { + const { CNAME, isExternalAssetsCliParamProvided, isSilent } = params; - const parsedPackageJson = zParsedPackageJson.parse(JSON.parse(packageJson)); + const parsedPackageJson = getParsedPackageJson(); const url = (() => { const { homepage } = parsedPackageJson; @@ -172,7 +130,9 @@ export function readBuildOptions(params: { extraAccountPages, extraThemeProperties, isSilent, - "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? "11.0.3" + "keycloakVersionDefaultAssets": keycloakVersionDefaultAssets ?? "11.0.3", + appInputPath: getAppInputPath(), + keycloakBuildPath: getKeycloakBuildPath() }; })(); diff --git a/src/bin/keycloakify/build-paths.ts b/src/bin/keycloakify/build-paths.ts new file mode 100644 index 00000000..200139f1 --- /dev/null +++ b/src/bin/keycloakify/build-paths.ts @@ -0,0 +1,72 @@ +import * as fs from "fs"; +import { exclude } from "tsafe"; +import { crawl } from "../tools/crawl"; +import { pathJoin } from "../tools/pathJoin"; +import { getParsedPackageJson } from "./parsed-package-json"; + +const DEFAULT_APP_INPUT_PATH = "build"; + +const DEFAULT_KEYCLOAK_BUILD_PATH = "build_keycloak"; + +const THEME_SRC_DIR_BASENAME = "keycloak-theme"; + +export const getReactProjectDirPath = () => process.cwd(); + +export const getCnamePath = () => pathJoin(getReactProjectDirPath(), "public", "CNAME"); + +const parseAppInputPath = (path?: string) => { + if (!path) { + return pathJoin(process.cwd(), DEFAULT_APP_INPUT_PATH); + } else if (path.startsWith("./")) { + return pathJoin(process.cwd(), path.replace("./", "")); + } + return path; +}; + +const parseKeycloakBuildPath = (path?: string) => { + if (!path) { + return pathJoin(process.cwd(), DEFAULT_KEYCLOAK_BUILD_PATH); + } else if (path.startsWith("./")) { + return pathJoin(process.cwd(), path.replace("./", "")); + } + return path; +}; + +export const getAppInputPath = () => { + return parseAppInputPath(getParsedPackageJson().keycloakify?.appInputPath); +}; + +export const getKeycloakBuildPath = () => { + return parseKeycloakBuildPath(getParsedPackageJson().keycloakify?.keycloakBuildPath); +}; +export const getThemeSrcDirPath = () => { + const srcDirPath = pathJoin(getReactProjectDirPath(), "src"); + + const themeSrcDirPath: string | undefined = crawl(srcDirPath) + .map(fileRelativePath => { + const split = fileRelativePath.split(THEME_SRC_DIR_BASENAME); + + if (split.length !== 2) { + return undefined; + } + + return pathJoin(srcDirPath, split[0] + THEME_SRC_DIR_BASENAME); + }) + .filter(exclude(undefined))[0]; + if (themeSrcDirPath === undefined) { + if (fs.existsSync(pathJoin(srcDirPath, "login")) || fs.existsSync(pathJoin(srcDirPath, "account"))) { + return { "themeSrcDirPath": srcDirPath }; + } + return { "themeSrcDirPath": undefined }; + } + + return { themeSrcDirPath }; +}; + +export const getEmailThemeSrcDirPath = () => { + const { themeSrcDirPath } = getThemeSrcDirPath(); + + const emailThemeSrcDirPath = themeSrcDirPath === undefined ? undefined : pathJoin(themeSrcDirPath, "email"); + + return { emailThemeSrcDirPath }; +}; diff --git a/src/bin/keycloakify/index.ts b/src/bin/keycloakify/index.ts index 13d73c75..258b6e23 100644 --- a/src/bin/keycloakify/index.ts +++ b/src/bin/keycloakify/index.ts @@ -4,5 +4,5 @@ export * from "./keycloakify"; import { main } from "./keycloakify"; if (require.main === module) { - main().catch(e => console.error(e)); + main(); } diff --git a/src/bin/keycloakify/keycloakify.ts b/src/bin/keycloakify/keycloakify.ts index 7d2f6334..b06f51d5 100644 --- a/src/bin/keycloakify/keycloakify.ts +++ b/src/bin/keycloakify/keycloakify.ts @@ -10,11 +10,8 @@ import { getCliOptions } from "../tools/cliOptions"; import jar from "../tools/jar"; import { assert } from "tsafe/assert"; import { Equals } from "tsafe"; -import { getEmailThemeSrcDirPath } from "../initialize-email-theme"; - -const reactProjectDirPath = process.cwd(); - -export const keycloakThemeBuildingDirPath = pathJoin(reactProjectDirPath, "build_keycloak"); +import { getEmailThemeSrcDirPath } from "./build-paths"; +import { getCnamePath, getAppInputPath, getKeycloakBuildPath, getReactProjectDirPath } from "./build-paths"; export async function main() { const { isSilent, hasExternalAssets } = getCliOptions(process.argv.slice(2)); @@ -22,9 +19,8 @@ export async function main() { logger.log("🔏 Building the keycloak theme...⌚"); const buildOptions = readBuildOptions({ - "packageJson": fs.readFileSync(pathJoin(reactProjectDirPath, "package.json")).toString("utf8"), "CNAME": (() => { - const cnameFilePath = pathJoin(reactProjectDirPath, "public", "CNAME"); + const cnameFilePath = getCnamePath(); if (!fs.existsSync(cnameFilePath)) { return undefined; @@ -37,7 +33,7 @@ export async function main() { }); const { doBundlesEmailTemplate } = await generateKeycloakThemeResources({ - keycloakThemeBuildingDirPath, + keycloakThemeBuildingDirPath: buildOptions.keycloakBuildPath, "emailThemeSrcDirPath": (() => { const { emailThemeSrcDirPath } = getEmailThemeSrcDirPath(); @@ -47,13 +43,13 @@ export async function main() { return emailThemeSrcDirPath; })(), - "reactAppBuildDirPath": pathJoin(reactProjectDirPath, "build"), + "reactAppBuildDirPath": getAppInputPath(), buildOptions, "keycloakVersion": buildOptions.keycloakVersionDefaultAssets }); const { jarFilePath } = generateJavaStackFiles({ - keycloakThemeBuildingDirPath, + keycloakThemeBuildingDirPath: buildOptions.keycloakBuildPath, doBundlesEmailTemplate, buildOptions }); @@ -65,7 +61,7 @@ export async function main() { case "keycloakify": logger.log("🫶 Let keycloakify do its thang"); await jar({ - "rootPath": pathJoin(keycloakThemeBuildingDirPath, "src", "main", "resources"), + "rootPath": pathJoin(buildOptions.keycloakBuildPath, "src", "main", "resources"), "version": buildOptions.version, "groupId": buildOptions.groupId, "artifactId": buildOptions.artifactId, @@ -74,7 +70,7 @@ export async function main() { break; case "mvn": logger.log("🫙 Run maven to deliver a jar"); - child_process.execSync("mvn package", { "cwd": keycloakThemeBuildingDirPath }); + child_process.execSync("mvn package", { "cwd": buildOptions.keycloakBuildPath }); break; default: assert>(false); @@ -84,7 +80,7 @@ export async function main() { const containerKeycloakVersion = "20.0.1"; generateStartKeycloakTestingContainer({ - keycloakThemeBuildingDirPath, + keycloakThemeBuildingDirPath: buildOptions.keycloakBuildPath, "keycloakVersion": containerKeycloakVersion, buildOptions }); @@ -92,7 +88,7 @@ export async function main() { logger.log( [ "", - `✅ Your keycloak theme has been generated and bundled into ./${pathRelative(reactProjectDirPath, jarFilePath)} 🚀`, + `✅ Your keycloak theme has been generated and bundled into ./${pathRelative(getReactProjectDirPath(), jarFilePath)} 🚀`, `It is to be placed in "/opt/keycloak/providers" in the container running a quay.io/keycloak/keycloak Docker image.`, "", //TODO: Restore when we find a good Helm chart for Keycloak. @@ -127,8 +123,8 @@ export async function main() { `To test your theme locally you can spin up a Keycloak ${containerKeycloakVersion} container image with the theme pre loaded by running:`, "", `👉 $ .${pathSep}${pathRelative( - reactProjectDirPath, - pathJoin(keycloakThemeBuildingDirPath, generateStartKeycloakTestingContainer.basename) + getReactProjectDirPath(), + pathJoin(getKeycloakBuildPath(), generateStartKeycloakTestingContainer.basename) )} 👈`, "", `Test with different Keycloak versions by editing the .sh file. see available versions here: https://quay.io/repository/keycloak/keycloak?tab=tags`, diff --git a/src/bin/keycloakify/parsed-package-json.ts b/src/bin/keycloakify/parsed-package-json.ts new file mode 100644 index 00000000..6f69e970 --- /dev/null +++ b/src/bin/keycloakify/parsed-package-json.ts @@ -0,0 +1,58 @@ +import * as fs from "fs"; +import { assert } from "tsafe"; +import type { Equals } from "tsafe"; +import { z } from "zod"; +import { pathJoin } from "../tools/pathJoin"; + +const reactProjectDirPath = process.cwd(); +export const bundlers = ["mvn", "keycloakify", "none"] as const; +export type Bundler = (typeof bundlers)[number]; +type ParsedPackageJson = { + name: string; + version: string; + homepage?: string; + keycloakify?: { + /** @deprecated: use extraLoginPages instead */ + extraPages?: string[]; + extraLoginPages?: string[]; + extraAccountPages?: string[]; + extraThemeProperties?: string[]; + areAppAndKeycloakServerSharingSameDomain?: boolean; + artifactId?: string; + groupId?: string; + bundler?: Bundler; + keycloakVersionDefaultAssets?: string; + appInputPath?: string; + keycloakBuildPath?: string; + }; +}; + +const zParsedPackageJson = z.object({ + "name": z.string(), + "version": z.string(), + "homepage": z.string().optional(), + "keycloakify": z + .object({ + "extraPages": z.array(z.string()).optional(), + "extraLoginPages": z.array(z.string()).optional(), + "extraAccountPages": z.array(z.string()).optional(), + "extraThemeProperties": z.array(z.string()).optional(), + "areAppAndKeycloakServerSharingSameDomain": z.boolean().optional(), + "artifactId": z.string().optional(), + "groupId": z.string().optional(), + "bundler": z.enum(bundlers).optional(), + "keycloakVersionDefaultAssets": z.string().optional(), + "appInputPath": z.string().optional(), + "keycloakBuildPath": z.string().optional() + }) + .optional() +}); + +assert, ParsedPackageJson>>(); + +let parsedPackageJson: undefined | ReturnType<(typeof zParsedPackageJson)["parse"]>; +export const getParsedPackageJson = () => { + if (parsedPackageJson) return parsedPackageJson; + parsedPackageJson = zParsedPackageJson.parse(JSON.parse(fs.readFileSync(pathJoin(reactProjectDirPath, "package.json")).toString("utf8"))); + return parsedPackageJson; +}; diff --git a/test/bin/generateKeycloakThemeResources.ts b/test/bin/generateKeycloakThemeResources.ts deleted file mode 100644 index f76e7bfd..00000000 --- a/test/bin/generateKeycloakThemeResources.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { join as pathJoin } from "path"; -import { generateKeycloakThemeResources } from "keycloakify/bin/keycloakify/generateKeycloakThemeResources"; -import { setupSampleReactProject, sampleReactProjectDirPath } from "./setupSampleReactProject"; - -setupSampleReactProject(); - -generateKeycloakThemeResources({ - "reactAppBuildDirPath": pathJoin(sampleReactProjectDirPath, "build"), - "keycloakThemeBuildingDirPath": pathJoin(sampleReactProjectDirPath, "build_keycloak_theme"), - "emailThemeSrcDirPath": undefined, - "keycloakVersion": "11.0.3", - "buildOptions": { - "themeName": "keycloakify-demo-app", - "extraLoginPages": ["my-custom-page.ftl"], - "extraThemeProperties": ["env=test"], - "isStandalone": true, - "urlPathname": "/keycloakify-demo-app/", - "isSilent": false - } -}); diff --git a/test/bin/main.ts b/test/bin/main.ts deleted file mode 100644 index 531d4b3d..00000000 --- a/test/bin/main.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { setupSampleReactProject, sampleReactProjectDirPath } from "./setupSampleReactProject"; -import * as st from "scripting-tools"; -import * as fs from "fs"; -import { join as pathJoin } from "path"; -import { getProjectRoot } from "keycloakify/bin/tools/getProjectRoot.js"; - -(async () => { - fs.rmSync(sampleReactProjectDirPath, { "recursive": true }); - - await setupSampleReactProject(); - - const binDirPath = pathJoin(getProjectRoot(), "dist_test", "src", "bin"); - - fs.mkdirSync(pathJoin(sampleReactProjectDirPath, "src", "keycloak-theme"), { "recursive": true }); - - st.execSyncTrace(`node ${pathJoin(binDirPath, "initialize-email-theme")}`, { "cwd": sampleReactProjectDirPath }); - - st.execSyncTrace(`node ${pathJoin(binDirPath, "download-builtin-keycloak-theme")}`, { "cwd": sampleReactProjectDirPath }); - - st.execSyncTrace( - //`node ${pathJoin(binDirPath, "keycloakify")} --external-assets`, - `node ${pathJoin(binDirPath, "keycloakify")}`, - { "cwd": sampleReactProjectDirPath } - ); -})(); diff --git a/test/bin/setupCustomReactProject.spec.ts b/test/bin/setupCustomReactProject.spec.ts new file mode 100644 index 00000000..3a4dc069 --- /dev/null +++ b/test/bin/setupCustomReactProject.spec.ts @@ -0,0 +1,62 @@ +import * as fs from "fs"; +import { getProjectRoot } from "keycloakify/bin/tools/getProjectRoot.js"; +import { join as pathJoin } from "path"; +import { downloadAndUnzip } from "keycloakify/bin/tools/downloadAndUnzip"; +import { main as initializeEmailTheme } from "keycloakify/bin/initialize-email-theme"; +import { it, describe, afterAll, beforeAll, beforeEach, vi } from "vitest"; +import { getKeycloakBuildPath } from "keycloakify/bin/keycloakify/build-paths"; +import { downloadBuiltinKeycloakTheme } from "keycloakify/bin/download-builtin-keycloak-theme"; + +export const sampleReactProjectDirPath = pathJoin(getProjectRoot(), "sample_custom_react_project"); + +async function setupSampleReactProject(destDir: string) { + await downloadAndUnzip({ + "url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip", + "destDirPath": destDir + }); +} +const nativeCwd = process.cwd; +vi.mock("keycloakify/bin/keycloakify/parsed-package-json", async () => ({ + ...((await vi.importActual("keycloakify/bin/keycloakify/parsed-package-json")) as Record), + getParsedPackageJson: () => ({ + keycloakify: { + appInputPath: "./custom_input/build", + keycloakBuildDir: "./custom_output" + } + }) +})); + +vi.mock("keycloakify/bin/promptKeycloakVersion", async () => ({ + ...((await vi.importActual("keycloakify/bin/promptKeycloakVersion")) as Record), + promptKeycloakVersion: () => ({ keycloakVersion: "11.0.3" }) +})); + +describe("Sample Project", () => { + beforeAll(() => { + // Monkey patching the cwd to the app location for the duration of this testv + process.cwd = () => sampleReactProjectDirPath; + }); + + afterAll(() => { + process.cwd = nativeCwd; + }); + beforeEach(() => { + if (fs.existsSync(sampleReactProjectDirPath)) { + fs.rmSync(sampleReactProjectDirPath, { "recursive": true }); + } + + fs.mkdirSync(pathJoin(sampleReactProjectDirPath, "src", "keycloak-theme"), { "recursive": true }); + fs.mkdirSync(pathJoin(sampleReactProjectDirPath, "src", "login"), { "recursive": true }); + }); + it( + "Sets up the project with a custom input and output directory without error", + async () => { + await setupSampleReactProject(pathJoin(sampleReactProjectDirPath, "custom_input")); + await initializeEmailTheme(); + + const destDirPath = pathJoin(getKeycloakBuildPath(), "src", "main", "resources", "theme"); + await downloadBuiltinKeycloakTheme({ destDirPath, keycloakVersion: "11.0.3", isSilent: false }); + }, + { timeout: 30000 } + ); +}); diff --git a/test/bin/setupSampleReactProject.spec.ts b/test/bin/setupSampleReactProject.spec.ts new file mode 100644 index 00000000..5d85993a --- /dev/null +++ b/test/bin/setupSampleReactProject.spec.ts @@ -0,0 +1,59 @@ +import * as fs from "fs"; +import { getProjectRoot } from "keycloakify/bin/tools/getProjectRoot.js"; +import { join as pathJoin } from "path"; +import { downloadAndUnzip } from "keycloakify/bin/tools/downloadAndUnzip"; +import { main as initializeEmailTheme } from "keycloakify/bin/initialize-email-theme"; +import { it, describe, afterAll, beforeAll, beforeEach, vi } from "vitest"; +import { getKeycloakBuildPath } from "keycloakify/bin/keycloakify/build-paths"; +import { downloadBuiltinKeycloakTheme } from "keycloakify/bin/download-builtin-keycloak-theme"; + +export const sampleReactProjectDirPath = pathJoin(getProjectRoot(), "sample_react_project"); + +async function setupSampleReactProject(destDir: string) { + await downloadAndUnzip({ + "url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip", + "destDirPath": destDir + }); +} + +vi.mock("keycloakify/bin/keycloakify/parsed-package-json", async () => ({ + ...((await vi.importActual("keycloakify/bin/keycloakify/parsed-package-json")) as Record), + getParsedPackageJson: () => ({}) +})); + +vi.mock("keycloakify/bin/promptKeycloakVersion", async () => ({ + ...((await vi.importActual("keycloakify/bin/promptKeycloakVersion")) as Record), + promptKeycloakVersion: () => ({ keycloakVersion: "11.0.3" }) +})); + +const nativeCwd = process.cwd; + +describe("Sample Project", () => { + beforeAll(() => { + // Monkey patching the cwd to the app location for the duration of this test + process.cwd = () => sampleReactProjectDirPath; + }); + + afterAll(() => { + process.cwd = nativeCwd; + }); + beforeEach(() => { + if (fs.existsSync(sampleReactProjectDirPath)) { + fs.rmSync(sampleReactProjectDirPath, { "recursive": true }); + } + + fs.mkdirSync(pathJoin(sampleReactProjectDirPath, "src", "keycloak-theme"), { "recursive": true }); + fs.mkdirSync(pathJoin(sampleReactProjectDirPath, "src", "login"), { "recursive": true }); + }); + it( + "Sets up the project without error", + async () => { + await setupSampleReactProject(sampleReactProjectDirPath); + await initializeEmailTheme(); + + const destDirPath = pathJoin(getKeycloakBuildPath(), "src", "main", "resources", "theme"); + await downloadBuiltinKeycloakTheme({ destDirPath, keycloakVersion: "11.0.3", isSilent: false }); + }, + { timeout: 30000 } + ); +}); diff --git a/test/bin/setupSampleReactProject.ts b/test/bin/setupSampleReactProject.ts index 7b8308e8..12061e68 100644 --- a/test/bin/setupSampleReactProject.ts +++ b/test/bin/setupSampleReactProject.ts @@ -1,12 +1,8 @@ -import { getProjectRoot } from "keycloakify/bin/tools/getProjectRoot.js"; -import { join as pathJoin } from "path"; import { downloadAndUnzip } from "keycloakify/bin/tools/downloadAndUnzip"; -export const sampleReactProjectDirPath = pathJoin(getProjectRoot(), "sample_react_project"); - -export async function setupSampleReactProject() { +export async function setupSampleReactProject(destDirPath: string) { await downloadAndUnzip({ "url": "https://github.com/keycloakify/keycloakify/releases/download/v0.0.1/sample_build_dir_and_package_json.zip", - "destDirPath": sampleReactProjectDirPath + "destDirPath": destDirPath }); } diff --git a/vitest.config.ts b/vitest.config.ts index f372a9c9..aec1da63 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -6,6 +6,7 @@ export default defineConfig({ test: { alias: { "keycloakify": path.resolve(__dirname, "./src") - } + }, + watchExclude: ["**/node_modules/**", "**/dist/**", "**/sample_react_project/**", "**/sample_custom_react_project/**"] } }); From 83b0838c94f0f73b380743a70a258f622a22478b Mon Sep 17 00:00:00 2001 From: garronej Date: Fri, 31 Mar 2023 11:49:06 +0200 Subject: [PATCH 6/6] Minor fixes to the Vitest setup --- .gitignore | 8 +- scripts/test-keycloakify-starter.ts | 8 +- test/bin/setupCustomReactProject.spec.ts | 9 +- test/bin/setupSampleReactProject.spec.ts | 1 + test/lib/tools/AndByDiscriminatingKey.ts | 91 ++++++++++++++++++ .../tools/AndByDiscriminatingKey.type.spec.ts | 94 ------------------- test/tsconfig.json | 2 +- vitest.config.ts | 6 +- 8 files changed, 107 insertions(+), 112 deletions(-) create mode 100644 test/lib/tools/AndByDiscriminatingKey.ts delete mode 100644 test/lib/tools/AndByDiscriminatingKey.type.spec.ts diff --git a/.gitignore b/.gitignore index 1c905308..1bee3e4c 100644 --- a/.gitignore +++ b/.gitignore @@ -41,17 +41,13 @@ jspm_packages .DS_Store /dist -# Test Build Directories -/dist_test -/sample_react_project/ -/sample_custom_react_project/ /keycloakify_starter_test/ +/sample_custom_react_project/ +/sample_react_project/ /.yarn_home/ .idea -/keycloak_email -/build_keycloak /src/login/i18n/baseMessages/ /src/account/i18n/baseMessages/ diff --git a/scripts/test-keycloakify-starter.ts b/scripts/test-keycloakify-starter.ts index f443fa39..af512083 100644 --- a/scripts/test-keycloakify-starter.ts +++ b/scripts/test-keycloakify-starter.ts @@ -18,12 +18,12 @@ writeFileSync(path.join(process.cwd(), "dist", "package.json"), JSON.stringify(p try { execSync("yarn unlink"); } catch {} -execSync("yarn link", { cwd: path.join(process.cwd(), "dist") }); +execSync("yarn link", { "cwd": path.join(process.cwd(), "dist") }); // Clone latest keycloakify-starter and link to keycloakify output execSync(`git clone https://github.com/keycloakify/keycloakify-starter.git ${testDir}`); -execSync("yarn install", { cwd: path.join(process.cwd(), testDir) }); -execSync("yarn link keycloakify", { cwd: path.join(process.cwd(), testDir) }); +execSync("yarn install", { "cwd": path.join(process.cwd(), testDir) }); +execSync("yarn link keycloakify", { "cwd": path.join(process.cwd(), testDir) }); //Ensure keycloak theme can be built -execSync("yarn build-keycloak-theme", { cwd: path.join(process.cwd(), testDir) }); +execSync("yarn build-keycloak-theme", { "cwd": path.join(process.cwd(), testDir) }); diff --git a/test/bin/setupCustomReactProject.spec.ts b/test/bin/setupCustomReactProject.spec.ts index 3a4dc069..9d14c6e0 100644 --- a/test/bin/setupCustomReactProject.spec.ts +++ b/test/bin/setupCustomReactProject.spec.ts @@ -19,16 +19,16 @@ const nativeCwd = process.cwd; vi.mock("keycloakify/bin/keycloakify/parsed-package-json", async () => ({ ...((await vi.importActual("keycloakify/bin/keycloakify/parsed-package-json")) as Record), getParsedPackageJson: () => ({ - keycloakify: { - appInputPath: "./custom_input/build", - keycloakBuildDir: "./custom_output" + "keycloakify": { + "appInputPath": "./custom_input/build", + "keycloakBuildDir": "./custom_output" } }) })); vi.mock("keycloakify/bin/promptKeycloakVersion", async () => ({ ...((await vi.importActual("keycloakify/bin/promptKeycloakVersion")) as Record), - promptKeycloakVersion: () => ({ keycloakVersion: "11.0.3" }) + promptKeycloakVersion: () => ({ "keycloakVersion": "11.0.3" }) })); describe("Sample Project", () => { @@ -38,6 +38,7 @@ describe("Sample Project", () => { }); afterAll(() => { + fs.rmSync(sampleReactProjectDirPath, { "recursive": true }); process.cwd = nativeCwd; }); beforeEach(() => { diff --git a/test/bin/setupSampleReactProject.spec.ts b/test/bin/setupSampleReactProject.spec.ts index 5d85993a..7c6143a4 100644 --- a/test/bin/setupSampleReactProject.spec.ts +++ b/test/bin/setupSampleReactProject.spec.ts @@ -35,6 +35,7 @@ describe("Sample Project", () => { }); afterAll(() => { + fs.rmSync(sampleReactProjectDirPath, { "recursive": true }); process.cwd = nativeCwd; }); beforeEach(() => { diff --git a/test/lib/tools/AndByDiscriminatingKey.ts b/test/lib/tools/AndByDiscriminatingKey.ts new file mode 100644 index 00000000..3c3f73a0 --- /dev/null +++ b/test/lib/tools/AndByDiscriminatingKey.ts @@ -0,0 +1,91 @@ +import { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey"; +import { assert } from "tsafe/assert"; +import type { Equals } from "tsafe"; + +{ + type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; + + type Extension = { pageId: "a"; onlyExtA: string } | { pageId: "b"; onlyExtB: string } | { pageId: "only ext"; onlyExt: string }; + + type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; + + type Expected = + | { pageId: "a"; onlyA: string; onlyExtA: string } + | { pageId: "b"; onlyB: string; onlyExtB: string } + | { pageId: "only base"; onlyBase: string } + | { pageId: "only ext"; onlyExt: string }; + + assert>(); + + const x: Got = null as any; + + if (x.pageId === "a") { + x.onlyA; + x.onlyExtA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyBase; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "b") { + x.onlyB; + x.onlyExtB; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyBase; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "only base") { + x.onlyBase; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyExt; + } + + if (x.pageId === "only ext") { + x.onlyExt; + + //@ts-expect-error + x.onlyA; + + //@ts-expect-error + x.onlyB; + + //@ts-expect-error + x.onlyBase; + } +} + +{ + type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; + + type Extension = { pageId: "only ext"; onlyExt: string }; + + type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; + + type Expected = + | { pageId: "a"; onlyA: string } + | { pageId: "b"; onlyB: string } + | { pageId: "only base"; onlyBase: string } + | { pageId: "only ext"; onlyExt: string }; + + assert>(); +} diff --git a/test/lib/tools/AndByDiscriminatingKey.type.spec.ts b/test/lib/tools/AndByDiscriminatingKey.type.spec.ts deleted file mode 100644 index 8edb9f87..00000000 --- a/test/lib/tools/AndByDiscriminatingKey.type.spec.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { AndByDiscriminatingKey } from "keycloakify/tools/AndByDiscriminatingKey"; -import { assert } from "tsafe/assert"; -import type { Equals } from "tsafe"; -import { it, describe } from "vitest"; - -// These test case names are intentionally vague, because I'm not sure what each are testing individually -describe("AndByDiscriminatingKey", () => { - it("Test Case 1", () => { - type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; - - type Extension = { pageId: "a"; onlyExtA: string } | { pageId: "b"; onlyExtB: string } | { pageId: "only ext"; onlyExt: string }; - - type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; - - type Expected = - | { pageId: "a"; onlyA: string; onlyExtA: string } - | { pageId: "b"; onlyB: string; onlyExtB: string } - | { pageId: "only base"; onlyBase: string } - | { pageId: "only ext"; onlyExt: string }; - - assert>(); - - const x: Got = {} as any; - - if (x.pageId === "a") { - x.onlyA; - x.onlyExtA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyBase; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "b") { - x.onlyB; - x.onlyExtB; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyBase; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "only base") { - x.onlyBase; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyExt; - } - - if (x.pageId === "only ext") { - x.onlyExt; - - //@ts-expect-error - x.onlyA; - - //@ts-expect-error - x.onlyB; - - //@ts-expect-error - x.onlyBase; - } - }); - it("Test Case 2", () => { - type Base = { pageId: "a"; onlyA: string } | { pageId: "b"; onlyB: string } | { pageId: "only base"; onlyBase: string }; - - type Extension = { pageId: "only ext"; onlyExt: string }; - - type Got = AndByDiscriminatingKey<"pageId", Extension, Base>; - - type Expected = - | { pageId: "a"; onlyA: string } - | { pageId: "b"; onlyB: string } - | { pageId: "only base"; onlyBase: string } - | { pageId: "only ext"; onlyExt: string }; - - assert>(); - }); -}); diff --git a/test/tsconfig.json b/test/tsconfig.json index 7239f999..8c6c685d 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -10,7 +10,7 @@ "newLine": "LF", "noUnusedLocals": true, "noUnusedParameters": true, - "incremental": true, + "incremental": false, "strict": true, "downlevelIteration": true, "jsx": "react-jsx", diff --git a/vitest.config.ts b/vitest.config.ts index aec1da63..1af3eb95 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -3,10 +3,10 @@ import { defineConfig } from "vite"; import path from "path"; export default defineConfig({ - test: { - alias: { + "test": { + "alias": { "keycloakify": path.resolve(__dirname, "./src") }, - watchExclude: ["**/node_modules/**", "**/dist/**", "**/sample_react_project/**", "**/sample_custom_react_project/**"] + "watchExclude": ["**/node_modules/**", "**/dist/**", "**/sample_react_project/**", "**/sample_custom_react_project/**"] } });