diff --git a/solidjs-tailwind/.env.example b/solidjs-tailwind/.env.example new file mode 100644 index 000000000..511841197 --- /dev/null +++ b/solidjs-tailwind/.env.example @@ -0,0 +1,3 @@ +VITE_API_URL=https://api.starter.dev/api +VITE_GITHUB_URL=https://api.github.com +VITE_BASE_URL=http://localhost:3000 diff --git a/solidjs-tailwind/.gitignore b/solidjs-tailwind/.gitignore index ae51d0111..1c2db3da9 100644 --- a/solidjs-tailwind/.gitignore +++ b/solidjs-tailwind/.gitignore @@ -1,5 +1,10 @@ node_modules dist +# env file +.env.development +.env.production +.env.local + # .vscode .vscode/* diff --git a/solidjs-tailwind/index.html b/solidjs-tailwind/index.html index ad397b420..ce4d3c8b0 100644 --- a/solidjs-tailwind/index.html +++ b/solidjs-tailwind/index.html @@ -1,16 +1,16 @@ - - - - - - solidjs-tailwindcss starter kit - - - -
+ + + + + + solidjs-tailwindcss starter kit + + + +
- - + + diff --git a/solidjs-tailwind/package.json b/solidjs-tailwind/package.json index 6939178b6..63b9adc35 100644 --- a/solidjs-tailwind/package.json +++ b/solidjs-tailwind/package.json @@ -50,6 +50,8 @@ "@heroicons/react": "1.0.5" }, "dependencies": { + "@octokit/rest": "^19.0.5", + "isomorphic-fetch": "^3.0.0", "solid-heroicons": "^3.1.0", "solid-js": "1.6.0" }, diff --git a/solidjs-tailwind/pnpm-lock.yaml b/solidjs-tailwind/pnpm-lock.yaml index e4401d8b1..d1e87167a 100644 --- a/solidjs-tailwind/pnpm-lock.yaml +++ b/solidjs-tailwind/pnpm-lock.yaml @@ -1,6 +1,8 @@ lockfileVersion: 5.4 specifiers: + '@heroicons/react': 1.0.5 + '@octokit/rest': ^19.0.5 '@solidjs/router': 0.5.0 '@storybook/addon-actions': 6.5.13 '@storybook/addon-backgrounds': 6.5.13 @@ -21,6 +23,7 @@ specifiers: eslint: 8.26.0 eslint-plugin-solid: 0.7.4 eslint-plugin-unused-imports: 2.0.0 + isomorphic-fetch: ^3.0.0 jsdom: 20.0.1 postcss: 8.4.18 prettier: 2.7.1 @@ -36,10 +39,13 @@ specifiers: vitest: 0.24.3 dependencies: + '@octokit/rest': 19.0.5 + isomorphic-fetch: 3.0.0 solid-heroicons: 3.1.0_solid-js@1.6.0 solid-js: 1.6.0 devDependencies: + '@heroicons/react': 1.0.5 '@solidjs/router': 0.5.0_solid-js@1.6.0 '@storybook/addon-actions': 6.5.13 '@storybook/addon-backgrounds': 6.5.13 @@ -2899,6 +2905,15 @@ packages: resolution: {integrity: sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==} dev: true + /@heroicons/react/1.0.5: + resolution: {integrity: sha512-UDMyLM2KavIu2vlWfMspapw9yii7aoLwzI2Hudx4fyoPwfKfxU8r3cL8dEBXOjcLG0/oOONZzbT14M1HoNtEcg==} + peerDependencies: + react: '>= 16' + peerDependenciesMeta: + react: + optional: true + dev: true + /@humanwhocodes/config-array/0.11.6: resolution: {integrity: sha512-jJr+hPTJYKyDILJfhNSHsjiwXYf26Flsz8DvNndOsHs5pwSnpGUEy8yzF0JYhCEvTDdV2vuOK5tt8BVhwO5/hg==} engines: {node: '>=10.10.0'} @@ -3154,6 +3169,122 @@ packages: rimraf: 3.0.2 dev: true + /@octokit/auth-token/3.0.2: + resolution: {integrity: sha512-pq7CwIMV1kmzkFTimdwjAINCXKTajZErLB4wMLYapR2nuB/Jpr66+05wOTZMSCBXP6n4DdDWT2W19Bm17vU69Q==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 8.0.0 + dev: false + + /@octokit/core/4.1.0: + resolution: {integrity: sha512-Czz/59VefU+kKDy+ZfDwtOIYIkFjExOKf+HA92aiTZJ6EfWpFzYQWw0l54ji8bVmyhc+mGaLUbSUmXazG7z5OQ==} + engines: {node: '>= 14'} + dependencies: + '@octokit/auth-token': 3.0.2 + '@octokit/graphql': 5.0.4 + '@octokit/request': 6.2.2 + '@octokit/request-error': 3.0.2 + '@octokit/types': 8.0.0 + before-after-hook: 2.2.3 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/endpoint/7.0.3: + resolution: {integrity: sha512-57gRlb28bwTsdNXq+O3JTQ7ERmBTuik9+LelgcLIVfYwf235VHbN9QNo4kXExtp/h8T423cR5iJThKtFYxC7Lw==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 8.0.0 + is-plain-object: 5.0.0 + universal-user-agent: 6.0.0 + dev: false + + /@octokit/graphql/5.0.4: + resolution: {integrity: sha512-amO1M5QUQgYQo09aStR/XO7KAl13xpigcy/kI8/N1PnZYSS69fgte+xA4+c2DISKqUZfsh0wwjc2FaCt99L41A==} + engines: {node: '>= 14'} + dependencies: + '@octokit/request': 6.2.2 + '@octokit/types': 8.0.0 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/openapi-types/14.0.0: + resolution: {integrity: sha512-HNWisMYlR8VCnNurDU6os2ikx0s0VyEjDYHNS/h4cgb8DeOxQ0n72HyinUtdDVxJhFy3FWLGl0DJhfEWk3P5Iw==} + dev: false + + /@octokit/plugin-paginate-rest/5.0.1_@octokit+core@4.1.0: + resolution: {integrity: sha512-7A+rEkS70pH36Z6JivSlR7Zqepz3KVucEFVDnSrgHXzG7WLAzYwcHZbKdfTXHwuTHbkT1vKvz7dHl1+HNf6Qyw==} + engines: {node: '>= 14'} + peerDependencies: + '@octokit/core': '>=4' + dependencies: + '@octokit/core': 4.1.0 + '@octokit/types': 8.0.0 + dev: false + + /@octokit/plugin-request-log/1.0.4_@octokit+core@4.1.0: + resolution: {integrity: sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 4.1.0 + dev: false + + /@octokit/plugin-rest-endpoint-methods/6.7.0_@octokit+core@4.1.0: + resolution: {integrity: sha512-orxQ0fAHA7IpYhG2flD2AygztPlGYNAdlzYz8yrD8NDgelPfOYoRPROfEyIe035PlxvbYrgkfUZIhSBKju/Cvw==} + engines: {node: '>= 14'} + peerDependencies: + '@octokit/core': '>=3' + dependencies: + '@octokit/core': 4.1.0 + '@octokit/types': 8.0.0 + deprecation: 2.3.1 + dev: false + + /@octokit/request-error/3.0.2: + resolution: {integrity: sha512-WMNOFYrSaX8zXWoJg9u/pKgWPo94JXilMLb2VManNOby9EZxrQaBe/QSC4a1TzpAlpxofg2X/jMnCyZgL6y7eg==} + engines: {node: '>= 14'} + dependencies: + '@octokit/types': 8.0.0 + deprecation: 2.3.1 + once: 1.4.0 + dev: false + + /@octokit/request/6.2.2: + resolution: {integrity: sha512-6VDqgj0HMc2FUX2awIs+sM6OwLgwHvAi4KCK3mT2H2IKRt6oH9d0fej5LluF5mck1lRR/rFWN0YIDSYXYSylbw==} + engines: {node: '>= 14'} + dependencies: + '@octokit/endpoint': 7.0.3 + '@octokit/request-error': 3.0.2 + '@octokit/types': 8.0.0 + is-plain-object: 5.0.0 + node-fetch: 2.6.7 + universal-user-agent: 6.0.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/rest/19.0.5: + resolution: {integrity: sha512-+4qdrUFq2lk7Va+Qff3ofREQWGBeoTKNqlJO+FGjFP35ZahP+nBenhZiGdu8USSgmq4Ky3IJ/i4u0xbLqHaeow==} + engines: {node: '>= 14'} + dependencies: + '@octokit/core': 4.1.0 + '@octokit/plugin-paginate-rest': 5.0.1_@octokit+core@4.1.0 + '@octokit/plugin-request-log': 1.0.4_@octokit+core@4.1.0 + '@octokit/plugin-rest-endpoint-methods': 6.7.0_@octokit+core@4.1.0 + transitivePeerDependencies: + - encoding + dev: false + + /@octokit/types/8.0.0: + resolution: {integrity: sha512-65/TPpOJP1i3K4lBJMnWqPUJ6zuOtzhtagDvydAWbEXpbFYA0oMKKyLb95NFZZP0lSh/4b6K+DQlzvYQJQQePg==} + dependencies: + '@octokit/openapi-types': 14.0.0 + dev: false + /@rollup/pluginutils/4.2.1: resolution: {integrity: sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==} engines: {node: '>= 8.0.0'} @@ -6066,6 +6197,10 @@ packages: resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} dev: true + /before-after-hook/2.2.3: + resolution: {integrity: sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==} + dev: false + /better-opn/2.1.1: resolution: {integrity: sha512-kIPXZS5qwyKiX/HcRvDYfmBQUa8XP17I0mYZZ0y4UhpYOSvtsLHDYqmomS+Mj20aDvD3knEiQ0ecQy2nhio3yA==} engines: {node: '>8.0.0'} @@ -7158,6 +7293,10 @@ packages: engines: {node: '>= 0.8'} dev: true + /deprecation/2.3.1: + resolution: {integrity: sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==} + dev: false + /des.js/1.0.1: resolution: {integrity: sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==} dependencies: @@ -9456,6 +9595,11 @@ packages: isobject: 3.0.1 dev: true + /is-plain-object/5.0.0: + resolution: {integrity: sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==} + engines: {node: '>=0.10.0'} + dev: false + /is-potential-custom-element-name/1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} dev: true @@ -9602,6 +9746,15 @@ packages: engines: {node: '>=0.10.0'} dev: true + /isomorphic-fetch/3.0.0: + resolution: {integrity: sha512-qvUtwJ3j6qwsF3jLxkZ72qCgjMysPzDfeV240JHiGZsANBYd+EEuu35v7dfrJ9Up0Ak07D7GGSkGhCHTqg/5wA==} + dependencies: + node-fetch: 2.6.7 + whatwg-fetch: 3.6.2 + transitivePeerDependencies: + - encoding + dev: false + /isomorphic-unfetch/3.1.0: resolution: {integrity: sha512-geDJjpoZ8N0kWexiwkX8F9NkTsXhetLPVbZFQ+JTW239QNOwvB0gniuR1Wc6f0AMTn7/mFGyXvHTifrCp/GH8Q==} dependencies: @@ -10562,7 +10715,6 @@ packages: optional: true dependencies: whatwg-url: 5.0.0 - dev: true /node-int64/0.4.0: resolution: {integrity: sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==} @@ -10776,7 +10928,6 @@ packages: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} dependencies: wrappy: 1.0.2 - dev: true /onetime/5.1.2: resolution: {integrity: sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==} @@ -13037,7 +13188,6 @@ packages: /tr46/0.0.3: resolution: {integrity: sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==} - dev: true /tr46/3.0.0: resolution: {integrity: sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==} @@ -13299,6 +13449,10 @@ packages: unist-util-visit-parents: 3.1.1 dev: true + /universal-user-agent/6.0.0: + resolution: {integrity: sha512-isyNax3wXoKaulPDZWHQqbmIx1k2tb9fb3GGDBRxCscfYV2Ch7WxPArBsFEG8s/safwXTT7H4QGhaIkTp9447w==} + dev: false + /universalify/0.2.0: resolution: {integrity: sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==} engines: {node: '>= 4.0.0'} @@ -13622,7 +13776,6 @@ packages: /webidl-conversions/3.0.1: resolution: {integrity: sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==} - dev: true /webidl-conversions/7.0.0: resolution: {integrity: sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==} @@ -13781,6 +13934,10 @@ packages: iconv-lite: 0.6.3 dev: true + /whatwg-fetch/3.6.2: + resolution: {integrity: sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==} + dev: false + /whatwg-mimetype/3.0.0: resolution: {integrity: sha512-nt+N2dzIutVRxARx1nghPKGv1xHikU7HKdfafKkLNLindmPU/ch3U31NOCGGA/dmPcmb1VlofO0vnKAcsm0o/Q==} engines: {node: '>=12'} @@ -13799,7 +13956,6 @@ packages: dependencies: tr46: 0.0.3 webidl-conversions: 3.0.1 - dev: true /which-boxed-primitive/1.0.2: resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} @@ -13892,7 +14048,6 @@ packages: /wrappy/1.0.2: resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} - dev: true /write-file-atomic/3.0.3: resolution: {integrity: sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q==} diff --git a/solidjs-tailwind/src/App.jsx b/solidjs-tailwind/src/App.jsx index 262f4cf16..6a9bf9f5d 100644 --- a/solidjs-tailwind/src/App.jsx +++ b/solidjs-tailwind/src/App.jsx @@ -1,19 +1,14 @@ -import { Routes, Route } from '@solidjs/router'; -import { Header} from './components/'; -import { Home, Counter, ApiExample } from './pages'; +import { Route, Routes } from '@solidjs/router'; +import { Home, RedirectPage, SigninPage } from './pages'; +import ROUTES from './routes'; function App() { return ( - <> -
-
- - - - - -
- + + + + + ); } diff --git a/solidjs-tailwind/src/auth/AuthStore.js b/solidjs-tailwind/src/auth/AuthStore.js new file mode 100644 index 000000000..89782e896 --- /dev/null +++ b/solidjs-tailwind/src/auth/AuthStore.js @@ -0,0 +1,11 @@ +import { createStore } from 'solid-js/store'; + +const createAuthStore = () => + createStore({ + token: null, + get isAuthenticated() { + return !!this.token; + }, + }); + +export default createAuthStore; diff --git a/solidjs-tailwind/src/auth/index.js b/solidjs-tailwind/src/auth/index.js new file mode 100644 index 000000000..f127f28fd --- /dev/null +++ b/solidjs-tailwind/src/auth/index.js @@ -0,0 +1,11 @@ +import createAuthStore from './AuthStore'; +import ROUTES from '../routes'; +import createPreventUnauthorised from './preventUnauthorised'; + +const [authStore, setAuth] = createAuthStore(); +const preventUnauthorised = createPreventUnauthorised(authStore, ROUTES.SIGNIN); +export const useAuth = () => ({ + authStore, + preventUnauthorised, + setAuth, +}); diff --git a/solidjs-tailwind/src/auth/preventUnauthorised.js b/solidjs-tailwind/src/auth/preventUnauthorised.js new file mode 100644 index 000000000..8553e9abc --- /dev/null +++ b/solidjs-tailwind/src/auth/preventUnauthorised.js @@ -0,0 +1,13 @@ +import { useLocation, useNavigate } from '@solidjs/router'; + +const preventUnauthorised = (authStore, redirectPath) => () => { + const navigate = useNavigate(); + const location = useLocation(); + + if (!authStore.isAuthenticated) { + sessionStorage.setItem('auth_return_path', location.pathname); + navigate(redirectPath, { replace: true }); + } +}; + +export default preventUnauthorised; diff --git a/solidjs-tailwind/src/components/CounterExample/Counter.spec.jsx b/solidjs-tailwind/src/components/CounterExample/Counter.spec.jsx deleted file mode 100644 index 5e0a172ff..000000000 --- a/solidjs-tailwind/src/components/CounterExample/Counter.spec.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { fireEvent, render, screen } from 'solid-testing-library'; -import { describe, expect, it } from 'vitest'; -import { CounterExample } from '.'; - -describe('CounterExample', () => { - it('should mount', async () => { - const wrapper = await render(() => ); - expect(wrapper).toBeTruthy(); - }); - - it('should mount and increment', async () => { - await render(() => ); - const button = await screen.getByText('Increment'); - expect(button).toBeVisible(); - fireEvent.click(button); - const countText = await screen.getByText('Count: 1'); - expect(countText).toBeVisible(); - }); -}); diff --git a/solidjs-tailwind/src/components/CounterExample/CounterButton.jsx b/solidjs-tailwind/src/components/CounterExample/CounterButton.jsx deleted file mode 100644 index e0b037725..000000000 --- a/solidjs-tailwind/src/components/CounterExample/CounterButton.jsx +++ /dev/null @@ -1,19 +0,0 @@ -import { children, splitProps } from 'solid-js'; - -const CounterButton = (props) => { - const [local, others] = splitProps(props, ['onClick']); - const c = children(() => props.children); - - return ( - - ); -}; - -export default CounterButton; diff --git a/solidjs-tailwind/src/components/CounterExample/CounterDisplay.jsx b/solidjs-tailwind/src/components/CounterExample/CounterDisplay.jsx deleted file mode 100644 index 1ddd12144..000000000 --- a/solidjs-tailwind/src/components/CounterExample/CounterDisplay.jsx +++ /dev/null @@ -1,9 +0,0 @@ -import { count } from './CounterStore'; - -const CounterDisplay = () => ( - - Count: {count()} - -); - -export default CounterDisplay; diff --git a/solidjs-tailwind/src/components/CounterExample/CounterExample.stories.jsx b/solidjs-tailwind/src/components/CounterExample/CounterExample.stories.jsx deleted file mode 100644 index 4e956f5b7..000000000 --- a/solidjs-tailwind/src/components/CounterExample/CounterExample.stories.jsx +++ /dev/null @@ -1,10 +0,0 @@ -import { CounterExample } from '.'; - -export default { - title: 'Example/ Counter Example', - argTypes: {}, -}; - -const Template = (args) => ; - -export const Default = Template.bind({}); diff --git a/solidjs-tailwind/src/components/CounterExample/CounterStore.js b/solidjs-tailwind/src/components/CounterExample/CounterStore.js deleted file mode 100644 index fcb410b08..000000000 --- a/solidjs-tailwind/src/components/CounterExample/CounterStore.js +++ /dev/null @@ -1,9 +0,0 @@ -import { createSignal } from 'solid-js'; - -const [count, setCount] = createSignal(0); - -const increase = () => setCount(count() + 1); -const decrease = () => setCount(count() > 0 ? count() - 1 : 0); -const reset = () => setCount(0); - -export { count, increase, decrease, reset }; diff --git a/solidjs-tailwind/src/components/CounterExample/index.jsx b/solidjs-tailwind/src/components/CounterExample/index.jsx deleted file mode 100644 index a477a8fa6..000000000 --- a/solidjs-tailwind/src/components/CounterExample/index.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import CounterButton from './CounterButton'; -import CounterDisplay from './CounterDisplay'; -import { decrease, increase, reset } from './CounterStore'; - -export const CounterExample = () => { - return ( -
- -
- - Increment - - - Decrement - - - Reset - -
-
- ); -}; diff --git a/solidjs-tailwind/src/components/FetchExample/Greeting.jsx b/solidjs-tailwind/src/components/FetchExample/Greeting.jsx deleted file mode 100644 index 1e8d0a108..000000000 --- a/solidjs-tailwind/src/components/FetchExample/Greeting.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import { createResource, Match, Switch } from 'solid-js'; -import greetingFetcher from './GreetingFetcher'; - -const Greeting = () => { - const [message] = createResource(greetingFetcher()); - return ( - - -

There was an error loading your greeting :(

-
- -

Message: {message()}

-
- -
- - - ); -}; - -export default Greeting; diff --git a/solidjs-tailwind/src/components/FetchExample/Greeting.spec.jsx b/solidjs-tailwind/src/components/FetchExample/Greeting.spec.jsx deleted file mode 100644 index fc6ab0308..000000000 --- a/solidjs-tailwind/src/components/FetchExample/Greeting.spec.jsx +++ /dev/null @@ -1,30 +0,0 @@ -import { render, screen } from 'solid-testing-library'; -import { describe, expect, it, vi } from 'vitest'; - -import Greeting from './Greeting'; -import greetingFetcher from './GreetingFetcher'; - -vi.mock('./GreetingFetcher', () => ({ - default: vi.fn(() => () => Promise.resolve('Hi tester!')), -})); - -describe('Greeting', () => { - it('should mount', async () => { - const wrapper = await render(() => ); - expect(wrapper).toBeTruthy(); - }); - - it('should show the mocked greeting', async () => { - await render(() => ); - const text = await screen.getByText('Message: Hi tester!'); - expect(text).toBeVisible(); - }); - it("should show an error when api doesn't respond", async () => { - greetingFetcher.mockImplementationOnce(() => () => Promise.reject()); - await render(() => ); - const text = await screen.getByText( - 'There was an error loading your greeting :(' - ); - expect(text).toBeVisible(); - }); -}); diff --git a/solidjs-tailwind/src/components/FetchExample/Greeting.stories.jsx b/solidjs-tailwind/src/components/FetchExample/Greeting.stories.jsx deleted file mode 100644 index 692e28685..000000000 --- a/solidjs-tailwind/src/components/FetchExample/Greeting.stories.jsx +++ /dev/null @@ -1,20 +0,0 @@ -import { Greeting } from '.'; - -export default { - title: 'Example/Fetch Example', - component: Greeting, - argTypes: {}, - parameters: { - mockData: [ - { - url: 'https://api.starter.dev/hello?greeting=', - method: 'GET', - status: 200, - response: () => 'Hi storybook user!', - delay: 1000, - }, - ], - }, -}; - -export const FetchExample = (args) => ; diff --git a/solidjs-tailwind/src/components/FetchExample/GreetingFetcher.js b/solidjs-tailwind/src/components/FetchExample/GreetingFetcher.js deleted file mode 100644 index a7f6b967b..000000000 --- a/solidjs-tailwind/src/components/FetchExample/GreetingFetcher.js +++ /dev/null @@ -1,11 +0,0 @@ -const DEFAULT_MESSAGE = 'solidjs-tailwind starter.dev!'; -const greetingFetcher = - (message = DEFAULT_MESSAGE) => - async () => { - const encodedMessage = encodeURIComponent(message); - const endpoint = `https://api.starter.dev/hello?greeting=${encodedMessage}`; - - return fetch(endpoint).then((result) => result.text()); - }; - -export default greetingFetcher; diff --git a/solidjs-tailwind/src/components/FetchExample/index.js b/solidjs-tailwind/src/components/FetchExample/index.js deleted file mode 100644 index 368719ec5..000000000 --- a/solidjs-tailwind/src/components/FetchExample/index.js +++ /dev/null @@ -1 +0,0 @@ -export { default as Greeting } from './Greeting'; diff --git a/solidjs-tailwind/src/components/index.js b/solidjs-tailwind/src/components/index.js index b6eda55dd..6885ea85e 100644 --- a/solidjs-tailwind/src/components/index.js +++ b/solidjs-tailwind/src/components/index.js @@ -1,5 +1,3 @@ -export * from './CounterExample'; -export * from './FetchExample'; export * from './UserProfile'; export * from './Icons'; export * from './RepoFilter'; diff --git a/solidjs-tailwind/src/github/index.js b/solidjs-tailwind/src/github/index.js new file mode 100644 index 000000000..f9289a18a --- /dev/null +++ b/solidjs-tailwind/src/github/index.js @@ -0,0 +1,15 @@ +import { Octokit } from '@octokit/rest'; +import { useAuth } from '../auth'; + +export const useOctokit = () => { + const { authStore } = useAuth(); + if (!authStore.isAuthenticated) { + throw new Error( + 'Trying to use GitHub without authentication, did you forget to use `preventUnauthenticated`?' + ); + } + + return new Octokit({ + auth: authStore.token, + }); +}; diff --git a/solidjs-tailwind/src/helper/constants.js b/solidjs-tailwind/src/helper/constants.js new file mode 100644 index 000000000..d550960a4 --- /dev/null +++ b/solidjs-tailwind/src/helper/constants.js @@ -0,0 +1,9 @@ +export const API_URL = import.meta.env.VITE_API_URL; +export const APP_BASE_URL = import.meta.env.VITE_BASE_URL; +export const GITHUB_URL_BASE = import.meta.env.VITE_GITHUB_URL; + +export const REDIRECT_URL = `${APP_BASE_URL}/auth/redirect`; + +export const SIGN_IN_BASE_URL = `${API_URL}/auth/signin`; + +export const GITHUB_GRAPHQL = `${GITHUB_URL_BASE}/graphql`; diff --git a/solidjs-tailwind/src/pages/ApiExample.jsx b/solidjs-tailwind/src/pages/ApiExample.jsx deleted file mode 100644 index cf08b4e73..000000000 --- a/solidjs-tailwind/src/pages/ApiExample.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { Greeting, PageFooter, PageHeader } from '../components'; - -const ApiExample = () => { - return ( - <> - SolidJS Fetch Data from API - - - - ); -}; - -export default ApiExample; diff --git a/solidjs-tailwind/src/pages/Counter.jsx b/solidjs-tailwind/src/pages/Counter.jsx deleted file mode 100644 index d407a34c7..000000000 --- a/solidjs-tailwind/src/pages/Counter.jsx +++ /dev/null @@ -1,13 +0,0 @@ -import { CounterExample, PageFooter, PageHeader } from '../components'; - -const Counter = () => { - return ( - <> - Increment, Decrement and Reset Button Example - - - - ); -}; - -export default Counter; diff --git a/solidjs-tailwind/src/pages/Home.jsx b/solidjs-tailwind/src/pages/Home.jsx index f1e679623..acffce29b 100644 --- a/solidjs-tailwind/src/pages/Home.jsx +++ b/solidjs-tailwind/src/pages/Home.jsx @@ -1,25 +1,28 @@ -import { NavLink } from '@solidjs/router'; +import { createResource, Show } from 'solid-js'; +import { useAuth } from '../auth'; +import { useOctokit } from '../github'; const Home = () => { + useAuth().preventUnauthorised(); + + const [data] = createResource(() => { + try { + return useOctokit() + .rest.users.getAuthenticated() + .then((response) => response.data); + } catch { + return Promise.resolve({}); + } + }); + return ( <> -
+

SolidJs and Tailwind CSS Starter kit -

-
- - See Counter example component - - - See API example component - -
+ + +

Welcome {data().login}

+
); }; diff --git a/solidjs-tailwind/src/pages/Redirect.jsx b/solidjs-tailwind/src/pages/Redirect.jsx new file mode 100644 index 000000000..7317ee3a1 --- /dev/null +++ b/solidjs-tailwind/src/pages/Redirect.jsx @@ -0,0 +1,19 @@ +import { useNavigate } from "@solidjs/router"; +import { createEffect, onCleanup } from "solid-js"; + +const Redirect = () => { + const route = useNavigate() + createEffect(() => { + const timer = setTimeout(() => { + const last_visted_path = sessionStorage.getItem('auth_return_path'); + const isAuthPage = last_visted_path.includes('signin'); + const to = isAuthPage ? '/' : last_visted_path; + route(to, { replace: true }); + }, 3000); + onCleanup(() => clearTimeout(timer)); + + }) + return
Redirecting...
; +} + +export default Redirect; diff --git a/solidjs-tailwind/src/pages/Signin.jsx b/solidjs-tailwind/src/pages/Signin.jsx new file mode 100644 index 000000000..9188b5390 --- /dev/null +++ b/solidjs-tailwind/src/pages/Signin.jsx @@ -0,0 +1,44 @@ +import { createEffect, createResource } from 'solid-js'; +import { useAuth } from '../auth'; +import { useNavigate } from '@solidjs/router'; +import { API_URL, REDIRECT_URL, SIGN_IN_BASE_URL } from '../helper/constants'; + +const fetchToken = () => + fetch(`${API_URL}/auth/token`, { + credentials: 'include', + }) + .then((response) => { + return response.json() + }) + .then((data) => { + return data.access_token + }); + + const SigninPage = () => { + const signInHref = `${SIGN_IN_BASE_URL}?redirect_url=${REDIRECT_URL}`; + const { setAuth } = useAuth(); + const navigate = useNavigate(); + const [token] = createResource(fetchToken); + + createEffect(() => { + if (token() && !token.loading) { + setAuth({ token: token() }); + navigate(sessionStorage.getItem('auth_return_path')); + } + }); + + return ( +
+ +
+ ); +}; + +export default SigninPage; diff --git a/solidjs-tailwind/src/pages/index.js b/solidjs-tailwind/src/pages/index.js index 57f34e3ec..59e94a5d5 100644 --- a/solidjs-tailwind/src/pages/index.js +++ b/solidjs-tailwind/src/pages/index.js @@ -1,3 +1,3 @@ export { default as Home } from './Home'; -export { default as Counter } from './Counter'; -export { default as ApiExample } from './ApiExample'; +export { default as SigninPage } from './Signin'; +export { default as RedirectPage } from './Redirect'; diff --git a/solidjs-tailwind/src/routes.js b/solidjs-tailwind/src/routes.js new file mode 100644 index 000000000..f0dd88172 --- /dev/null +++ b/solidjs-tailwind/src/routes.js @@ -0,0 +1,7 @@ +const ROUTES = { + HOME: '/', + SIGNIN: '/signin', + REDIRECT: '/auth/redirect', +}; + +export default ROUTES; diff --git a/solidjs-tailwind/vite.config.js b/solidjs-tailwind/vite.config.js index 9ad1e816e..319511627 100644 --- a/solidjs-tailwind/vite.config.js +++ b/solidjs-tailwind/vite.config.js @@ -13,13 +13,16 @@ export default defineConfig({ }, test: { globals: true, - environment: "jsdom", + environment: 'jsdom', setupFiles: './setupVitest.js', deps: { inline: [/solid-js/, /solid-testing-library/], }, }, - resolve: { - conditions: ['development', 'browser'], - }, + resolve: { + conditions: ['development', 'browser'], + alias: { + 'node-fetch': 'isomorphic-fetch', + }, + }, });