diff --git a/package.json b/package.json index 287d3e4..51984fe 100644 --- a/package.json +++ b/package.json @@ -73,7 +73,7 @@ "build:types": "run-s typecheck", "lint": "eslint .", "lint:fix": "eslint --fix .", - "test": "run-s test:build", + "test": "run-p test:build test:unit", "test:build": "run-p test:build:*", "test:build:react": "pnpm -C ./examples/react run build", "test:build:vanilla": "pnpm -C ./examples/vanilla run build", @@ -81,6 +81,7 @@ "test:dev:react": "pnpm -C ./examples/react run dev", "test:dev:vanilla": "pnpm -C ./examples/vanilla run dev", "test:dev:vue": "pnpm -C ./examples/vue run dev", + "test:unit": "vitest run", "typecheck": "run-p typecheck:*", "typecheck:core": "tsc", "typecheck:react": "pnpm -C ./examples/react run typecheck", @@ -109,7 +110,8 @@ "vite-node": "^0.34.6", "vite-plugin-externalize-deps": "^0.1.5", "vite-plugin-inspect": "^0.7.42", - "vite-plugin-node-polyfills": "workspace:*" + "vite-plugin-node-polyfills": "workspace:*", + "vitest": "^1.1.0" }, "publishConfig": { "access": "public" diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index dc4bf63..55c8db3 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -69,6 +69,9 @@ importers: vite-plugin-node-polyfills: specifier: workspace:* version: 'link:' + vitest: + specifier: ^1.1.0 + version: 1.1.0(@types/node@18.18.8) examples/react: devDependencies: @@ -748,6 +751,13 @@ packages: resolution: {integrity: sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw==} dev: true + /@jest/schemas@29.6.3: + resolution: {integrity: sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@sinclair/typebox': 0.27.8 + dev: true + /@jridgewell/gen-mapping@0.3.3: resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} engines: {node: '>=6.0.0'} @@ -923,6 +933,10 @@ packages: requiresBuild: true optional: true + /@sinclair/typebox@0.27.8: + resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} + dev: true + /@tanstack/match-sorter-utils@8.8.4: resolution: {integrity: sha512-rKH8LjZiszWEvmi01NR72QWZ8m4xmXre0OOwlRGnjU01Eqz/QnN+cqpty2PJ0efHblq09+KilvyR7lsbzmXVEw==} engines: {node: '>=12'} @@ -1224,6 +1238,44 @@ packages: vue: 3.3.7(typescript@5.2.2) dev: true + /@vitest/expect@1.1.0: + resolution: {integrity: sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w==} + dependencies: + '@vitest/spy': 1.1.0 + '@vitest/utils': 1.1.0 + chai: 4.3.10 + dev: true + + /@vitest/runner@1.1.0: + resolution: {integrity: sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw==} + dependencies: + '@vitest/utils': 1.1.0 + p-limit: 5.0.0 + pathe: 1.1.1 + dev: true + + /@vitest/snapshot@1.1.0: + resolution: {integrity: sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ==} + dependencies: + magic-string: 0.30.5 + pathe: 1.1.1 + pretty-format: 29.7.0 + dev: true + + /@vitest/spy@1.1.0: + resolution: {integrity: sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg==} + dependencies: + tinyspy: 2.2.0 + dev: true + + /@vitest/utils@1.1.0: + resolution: {integrity: sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ==} + dependencies: + diff-sequences: 29.6.3 + loupe: 2.3.7 + pretty-format: 29.7.0 + dev: true + /@vue/compiler-core@3.3.7: resolution: {integrity: sha512-pACdY6YnTNVLXsB86YD8OF9ihwpolzhhtdLVHhBL6do/ykr6kKXNYABRtNMGrsQXpEXXyAdwvWWkuTbs4MFtPQ==} dependencies: @@ -1315,6 +1367,11 @@ packages: acorn: 8.11.2 dev: true + /acorn-walk@8.3.1: + resolution: {integrity: sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw==} + engines: {node: '>=0.4.0'} + dev: true + /acorn@8.11.2: resolution: {integrity: sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w==} engines: {node: '>=0.4.0'} @@ -1349,6 +1406,11 @@ packages: color-convert: 2.0.1 dev: true + /ansi-styles@5.2.0: + resolution: {integrity: sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==} + engines: {node: '>=10'} + dev: true + /arg@5.0.2: resolution: {integrity: sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==} dev: true @@ -1443,6 +1505,10 @@ packages: util: 0.12.5 dev: false + /assertion-error@1.1.0: + resolution: {integrity: sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==} + dev: true + /available-typed-arrays@1.0.5: resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} engines: {node: '>= 0.4'} @@ -1623,6 +1689,19 @@ packages: resolution: {integrity: sha512-cPiMKZgqgkg5LY3/ntGeLFUpi6tzddBNS58A4tnTgQw1zON7u2sZMU7SzOeVH4tj20++9ggL+V6FDOFMTaFFYA==} dev: true + /chai@4.3.10: + resolution: {integrity: sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g==} + engines: {node: '>=4'} + dependencies: + assertion-error: 1.1.0 + check-error: 1.0.3 + deep-eql: 4.1.3 + get-func-name: 2.0.2 + loupe: 2.3.7 + pathval: 1.1.1 + type-detect: 4.0.8 + dev: true + /chalk@2.4.2: resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} engines: {node: '>=4'} @@ -1657,6 +1736,12 @@ packages: resolution: {integrity: sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg==} dev: true + /check-error@1.0.3: + resolution: {integrity: sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg==} + dependencies: + get-func-name: 2.0.2 + dev: true + /ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -1821,6 +1906,13 @@ packages: ms: 2.1.2 dev: true + /deep-eql@4.1.3: + resolution: {integrity: sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw==} + engines: {node: '>=6'} + dependencies: + type-detect: 4.0.8 + dev: true + /deep-is@0.1.4: resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==} dev: true @@ -1875,6 +1967,11 @@ packages: resolution: {integrity: sha512-lrbCJwD9saUQrqUfXvl6qoM+QN3W7tLV5pAOs+OqOmopCCz/JkE05MHedJR1xfk4IAnZuJXPVuN5+7jNA2ZCiA==} dev: true + /diff-sequences@29.6.3: + resolution: {integrity: sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dev: true + /diffie-hellman@5.0.3: resolution: {integrity: sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==} dependencies: @@ -2551,6 +2648,21 @@ packages: strip-final-newline: 3.0.0 dev: true + /execa@8.0.1: + resolution: {integrity: sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==} + engines: {node: '>=16.17'} + dependencies: + cross-spawn: 7.0.3 + get-stream: 8.0.1 + human-signals: 5.0.0 + is-stream: 3.0.0 + merge-stream: 2.0.0 + npm-run-path: 5.1.0 + onetime: 6.0.0 + signal-exit: 4.1.0 + strip-final-newline: 3.0.0 + dev: true + /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2681,6 +2793,10 @@ packages: engines: {node: '>=6.9.0'} dev: true + /get-func-name@2.0.2: + resolution: {integrity: sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==} + dev: true + /get-intrinsic@1.2.2: resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} dependencies: @@ -2694,6 +2810,11 @@ packages: engines: {node: '>=10'} dev: true + /get-stream@8.0.1: + resolution: {integrity: sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==} + engines: {node: '>=16'} + dev: true + /get-symbol-description@1.0.0: resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} engines: {node: '>= 0.4'} @@ -2861,6 +2982,11 @@ packages: engines: {node: '>=14.18.0'} dev: true + /human-signals@5.0.0: + resolution: {integrity: sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==} + engines: {node: '>=16.17.0'} + dev: true + /hyperdyperid@1.2.0: resolution: {integrity: sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==} engines: {node: '>=10.18'} @@ -3263,6 +3389,14 @@ packages: engines: {node: '>=14'} dev: true + /local-pkg@0.5.0: + resolution: {integrity: sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg==} + engines: {node: '>=14'} + dependencies: + mlly: 1.4.2 + pkg-types: 1.0.3 + dev: true + /locate-path@5.0.0: resolution: {integrity: sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==} engines: {node: '>=8'} @@ -3303,6 +3437,12 @@ packages: js-tokens: 4.0.0 dev: true + /loupe@2.3.7: + resolution: {integrity: sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA==} + dependencies: + get-func-name: 2.0.2 + dev: true + /lru-cache@5.1.1: resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} dependencies: @@ -3674,6 +3814,13 @@ packages: dependencies: yocto-queue: 0.1.0 + /p-limit@5.0.0: + resolution: {integrity: sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ==} + engines: {node: '>=18'} + dependencies: + yocto-queue: 1.0.0 + dev: true + /p-locate@4.1.0: resolution: {integrity: sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==} engines: {node: '>=8'} @@ -3789,6 +3936,10 @@ packages: resolution: {integrity: sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q==} dev: true + /pathval@1.1.1: + resolution: {integrity: sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ==} + dev: true + /pbkdf2@3.1.2: resolution: {integrity: sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==} engines: {node: '>=0.12'} @@ -3877,6 +4028,15 @@ packages: engines: {node: '>= 0.8.0'} dev: true + /pretty-format@29.7.0: + resolution: {integrity: sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==} + engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} + dependencies: + '@jest/schemas': 29.6.3 + ansi-styles: 5.2.0 + react-is: 18.2.0 + dev: true + /process@0.11.10: resolution: {integrity: sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==} engines: {node: '>= 0.6.0'} @@ -3949,6 +4109,10 @@ packages: scheduler: 0.23.0 dev: true + /react-is@18.2.0: + resolution: {integrity: sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==} + dev: true + /react-refresh@0.14.0: resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} engines: {node: '>=0.10.0'} @@ -4219,10 +4383,19 @@ packages: get-intrinsic: 1.2.2 object-inspect: 1.13.1 + /siginfo@2.0.0: + resolution: {integrity: sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g==} + dev: true + /signal-exit@3.0.7: resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} dev: true + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: true + /sirv@2.0.3: resolution: {integrity: sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==} engines: {node: '>= 10'} @@ -4264,6 +4437,14 @@ packages: resolution: {integrity: sha512-eWN+LnM3GR6gPu35WxNgbGl8rmY1AEmoMDvL/QD6zYmPWgywxWqJWNdLGT+ke8dKNWrcYgYjPpG5gbTfghP8rw==} dev: true + /stackback@0.0.2: + resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} + dev: true + + /std-env@3.7.0: + resolution: {integrity: sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg==} + dev: true + /stream-browserify@3.0.0: resolution: {integrity: sha512-H73RAHsVBapbim0tU2JwwOiXUj+fikfiaoYAKHF3VJfA0pe2BCzkhAHBlLG6REzE+2WNZcxOXjK7lkso+9euLA==} dependencies: @@ -4354,6 +4535,12 @@ packages: engines: {node: '>=8'} dev: true + /strip-literal@1.3.0: + resolution: {integrity: sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg==} + dependencies: + acorn: 8.11.2 + dev: true + /superjson@1.13.3: resolution: {integrity: sha512-mJiVjfd2vokfDxsQPOwJ/PtanO87LhpYY88ubI5dUB1Ab58Txbyje3+jpm+/83R/fevaq/107NNhtYBLuoTrFg==} engines: {node: '>=10'} @@ -4399,6 +4586,20 @@ packages: setimmediate: 1.0.5 dev: false + /tinybench@2.5.1: + resolution: {integrity: sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg==} + dev: true + + /tinypool@0.8.1: + resolution: {integrity: sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg==} + engines: {node: '>=14.0.0'} + dev: true + + /tinyspy@2.2.0: + resolution: {integrity: sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg==} + engines: {node: '>=14.0.0'} + dev: true + /titleize@3.0.0: resolution: {integrity: sha512-KxVu8EYHDPBdUYdKZdKtU2aj2XfEx9AfjXxE/Aj0vT06w2icA09Vus1rh6eSu1y01akYg6BjIK/hxyLJINoMLQ==} engines: {node: '>=12'} @@ -4459,6 +4660,11 @@ packages: prelude-ls: 1.2.1 dev: true + /type-detect@4.0.8: + resolution: {integrity: sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==} + engines: {node: '>=4'} + dev: true + /type-fest@0.20.2: resolution: {integrity: sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==} engines: {node: '>=10'} @@ -4642,6 +4848,27 @@ packages: - terser dev: true + /vite-node@1.1.0(@types/node@18.18.8): + resolution: {integrity: sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + dependencies: + cac: 6.7.14 + debug: 4.3.4 + pathe: 1.1.1 + picocolors: 1.0.0 + vite: 5.0.2(@types/node@18.18.8) + transitivePeerDependencies: + - '@types/node' + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vite-plugin-externalize-deps@0.1.5: resolution: {integrity: sha512-bXISkCGFW0JowXgfVv/FzKJAy20a3qNHjlcfrfI31pW2oZuSDAoaVeK7DqtGTFeQDn6VafQNHvlpJpdksZPbgg==} dependencies: @@ -4708,6 +4935,63 @@ packages: fsevents: 2.3.3 dev: true + /vitest@1.1.0(@types/node@18.18.8): + resolution: {integrity: sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A==} + engines: {node: ^18.0.0 || >=20.0.0} + hasBin: true + peerDependencies: + '@edge-runtime/vm': '*' + '@types/node': ^18.0.0 || >=20.0.0 + '@vitest/browser': ^1.0.0 + '@vitest/ui': ^1.0.0 + happy-dom: '*' + jsdom: '*' + peerDependenciesMeta: + '@edge-runtime/vm': + optional: true + '@types/node': + optional: true + '@vitest/browser': + optional: true + '@vitest/ui': + optional: true + happy-dom: + optional: true + jsdom: + optional: true + dependencies: + '@types/node': 18.18.8 + '@vitest/expect': 1.1.0 + '@vitest/runner': 1.1.0 + '@vitest/snapshot': 1.1.0 + '@vitest/spy': 1.1.0 + '@vitest/utils': 1.1.0 + acorn-walk: 8.3.1 + cac: 6.7.14 + chai: 4.3.10 + debug: 4.3.4 + execa: 8.0.1 + local-pkg: 0.5.0 + magic-string: 0.30.5 + pathe: 1.1.1 + picocolors: 1.0.0 + std-env: 3.7.0 + strip-literal: 1.3.0 + tinybench: 2.5.1 + tinypool: 0.8.1 + vite: 5.0.2(@types/node@18.18.8) + vite-node: 1.1.0(@types/node@18.18.8) + why-is-node-running: 2.2.2 + transitivePeerDependencies: + - less + - lightningcss + - sass + - stylus + - sugarss + - supports-color + - terser + dev: true + /vm-browserify@1.1.2: resolution: {integrity: sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==} dev: false @@ -4781,6 +5065,15 @@ packages: isexe: 2.0.0 dev: true + /why-is-node-running@2.2.2: + resolution: {integrity: sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA==} + engines: {node: '>=8'} + hasBin: true + dependencies: + siginfo: 2.0.0 + stackback: 0.0.2 + dev: true + /wrappy@1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} dev: true @@ -4820,3 +5113,8 @@ packages: /yocto-queue@0.1.0: resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} engines: {node: '>=10'} + + /yocto-queue@1.0.0: + resolution: {integrity: sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g==} + engines: {node: '>=12.20'} + dev: true diff --git a/test/integration/global-references/index.test.ts b/test/integration/global-references/index.test.ts new file mode 100644 index 0000000..e12333b --- /dev/null +++ b/test/integration/global-references/index.test.ts @@ -0,0 +1,58 @@ +import { describe, expect, it } from 'vitest' +import { formatWhitespace, transformDev } from '../../../test/utils' + +describe('import globals', () => { + describe('buffer', () => { + it('injects Buffer', async () => { + const result = await transformDev(`Buffer.from('test')`) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + Buffer.from("test"); + `)) + }) + }) + + describe('global', () => { + it('injects global', async () => { + const result = await transformDev(`console.log(global)`) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + console.log(global); + `)) + }) + }) + + describe('process', () => { + it('injects process', async () => { + const result = await transformDev(`console.log(process)`) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + console.log(process); + `)) + }) + }) +}) diff --git a/test/integration/import-globals/index.test.ts b/test/integration/import-globals/index.test.ts new file mode 100644 index 0000000..8871c76 --- /dev/null +++ b/test/integration/import-globals/index.test.ts @@ -0,0 +1,168 @@ +import { describe, expect, it } from 'vitest' +import { formatWhitespace, transformDev } from '../../../test/utils' + +describe('import globals', () => { + describe('buffer', () => { + it('resolves normally', async () => { + const result = await transformDev(` + import Buffer from 'buffer' + console.log(Buffer) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import Buffer from "/shims/buffer/dist/index.js"; + console.log(Buffer); + `)) + }) + + it('resolves with a `node:` prefix', async () => { + const result = await transformDev(` + import Buffer from 'node:buffer' + console.log(Buffer) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import Buffer from "/shims/buffer/dist/index.js"; + console.log(Buffer); + `)) + }) + + it('resolves with a trailing slash', async () => { + const result = await transformDev(` + import Buffer from 'buffer/' + console.log(Buffer) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import Buffer from "/shims/buffer/dist/index.js"; + console.log(Buffer); + `)) + }) + + it('resolves with a `node:` prefix and a trailing slash', async () => { + const result = await transformDev(` + import Buffer from 'node:buffer/' + console.log(Buffer) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import Buffer from "/shims/buffer/dist/index.js"; + console.log(Buffer); + `)) + }) + }) + + describe('process', () => { + it('resolves normally', async () => { + const result = await transformDev(` + import process from 'process' + console.log(process) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import process from "/shims/process/dist/index.js"; + console.log(process); + `)) + }) + + it('resolves with a `node:` prefix', async () => { + const result = await transformDev(` + import process from 'node:process' + console.log(process) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import process from "/shims/process/dist/index.js"; + console.log(process); + `)) + }) + + it('resolves with a trailing slash', async () => { + const result = await transformDev(` + import process from 'process/' + console.log(process) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import process from "/shims/process/dist/index.js"; + console.log(process); + `)) + }) + + it('resolves with a `node:` prefix and a trailing slash', async () => { + const result = await transformDev(` + import process from 'node:process/' + console.log(process) + `) + + expect(result?.code).toEqual(formatWhitespace(` + import __buffer_polyfill from "/shims/buffer/dist/index.js" + import __global_polyfill from "/shims/global/dist/index.js" + import __process_polyfill from "/shims/process/dist/index.js" + + globalThis.Buffer = globalThis.Buffer || __buffer_polyfill + globalThis.global = globalThis.global || __global_polyfill + globalThis.process = globalThis.process || __process_polyfill + + import process from "/shims/process/dist/index.js"; + console.log(process); + `)) + }) + }) +}) diff --git a/test/utils/index.ts b/test/utils/index.ts new file mode 100644 index 0000000..5df25e1 --- /dev/null +++ b/test/utils/index.ts @@ -0,0 +1,52 @@ +import { createServer } from 'vite' +import { nodePolyfills } from 'vite-plugin-node-polyfills' + +/** + * Format code by removing the smallest indentation from each line. + */ +export const formatWhitespace = (code: string) => { + const lines = code.split('\n') + const smallestIndentation = lines.reduce((currentIndentation, line) => { + if (line.trim() === '') { + return currentIndentation + } + + const lineIndentation = line.match(/^\s*/)?.at(0)?.length ?? 0 + + if (currentIndentation < 0) { + return lineIndentation + } + + return Math.min(currentIndentation, lineIndentation) + }, -1) + + const formatted = lines.map((line) => line.slice(smallestIndentation)).join('\n').trim() + + return `${formatted}\n` +} + +export const transformDev = async (code: string) => { + const server = await createServer({ + configFile: false, + esbuild: { + format: 'esm', + }, + plugins: [ + nodePolyfills(), + { + name: 'test-code-loader', + load(id) { + if (id === 'virtual:test.ts') { + return code + } + }, + }, + ], + }) + + try { + return await server.transformRequest('virtual:test.ts') + } finally { + await server.close() + } +}