From 253519f35b72cf95f0890d399e17fd2bc9014c9d Mon Sep 17 00:00:00 2001 From: Marco Montalbano Date: Thu, 25 May 2023 23:54:57 +0200 Subject: [PATCH 1/7] Add 'figma-export login' command to the cli --- packages/cli/package.json | 1 + packages/cli/src/commands/login.ts | 43 ++ packages/cli/src/run.ts | 3 +- packages/core/src/lib/figma.ts | 2 +- packages/website/.env.example | 3 + packages/website/lib/auth-storage.ts | 28 ++ packages/website/pages/api/check/[state].ts | 19 + packages/website/pages/api/login/[state].ts | 17 + packages/website/pages/api/oauth.ts | 34 ++ packages/website/pages/authorized.tsx | 15 + packages/website/pages/index.tsx | 6 +- packages/website/scss/index.scss | 6 +- yarn.lock | 517 ++++++++++---------- 13 files changed, 435 insertions(+), 259 deletions(-) create mode 100644 packages/cli/src/commands/login.ts create mode 100644 packages/website/.env.example create mode 100644 packages/website/lib/auth-storage.ts create mode 100644 packages/website/pages/api/check/[state].ts create mode 100644 packages/website/pages/api/login/[state].ts create mode 100644 packages/website/pages/api/oauth.ts create mode 100644 packages/website/pages/authorized.tsx diff --git a/packages/cli/package.json b/packages/cli/package.json index 1fd0ad0b..f073f2a6 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -10,6 +10,7 @@ "dependencies": { "@figma-export/core": "^5.0.1", "@figma-export/types": "^5.0.1", + "axios": "^1.4.0", "ora": "~5.4.1", "sade": "~1.8.1" }, diff --git a/packages/cli/src/commands/login.ts b/packages/cli/src/commands/login.ts new file mode 100644 index 00000000..efef7619 --- /dev/null +++ b/packages/cli/src/commands/login.ts @@ -0,0 +1,43 @@ +import crypto from 'crypto'; +import { Ora } from 'ora'; +import { Sade } from 'sade'; +import axios from 'axios'; + +type Auth = { + user_id: number + access_token: string + refresh_token: string + expires_in: number +} + +function check(state: string): Promise { + const result = axios.get(`http://localhost:3000/api/check/${state}`).then((response) => { + return response.data; + }).catch(() => { + return new Promise((resolve) => { + setTimeout(() => resolve(check(state)), 2000); + }); + }); + + return result; +} + +export const addLogin = (prog: Sade, spinner: Ora) => prog + .command('login') + .describe('Login to Figma.') + .example('login') + .action( + () => { + const state = crypto.createHash('md5').update(Math.random().toString()).digest('hex'); + spinner.info('Log in on https://figma.com'); + console.log(` +Login at: +http://localhost:3000/api/login/${state} + `); + spinner.start('waiting'); + check(state).then((response) => { + spinner.info(response.access_token); + spinner.succeed('Logged in on https://figma.com.'); + }); + }, + ); diff --git a/packages/cli/src/run.ts b/packages/cli/src/run.ts index 69702515..dda27621 100644 --- a/packages/cli/src/run.ts +++ b/packages/cli/src/run.ts @@ -4,6 +4,7 @@ import ora from 'ora'; import { addComponents } from './commands/components'; import { addStyles } from './commands/styles'; import { addUseConfig } from './commands/use-config'; +import { addLogin } from './commands/login'; // eslint-disable-next-line @typescript-eslint/no-var-requires const pkg = require('../package.json'); @@ -14,5 +15,5 @@ const spinner = ora({}); prog.version(pkg.version); -addUseConfig(addStyles(addComponents(prog, spinner), spinner), spinner) +addLogin(addUseConfig(addStyles(addComponents(prog, spinner), spinner), spinner), spinner) .parse(process.argv); diff --git a/packages/core/src/lib/figma.ts b/packages/core/src/lib/figma.ts index 237cc311..d3ca89c0 100644 --- a/packages/core/src/lib/figma.ts +++ b/packages/core/src/lib/figma.ts @@ -23,7 +23,7 @@ export const getClient = (token: string): Figma.ClientInterface => { throw new Error('\'Access Token\' is missing. https://www.figma.com/developers/docs#authentication'); } - return Figma.Client({ personalAccessToken: token }); + return Figma.Client({ accessToken: token }); }; /** diff --git a/packages/website/.env.example b/packages/website/.env.example new file mode 100644 index 00000000..0dd7766f --- /dev/null +++ b/packages/website/.env.example @@ -0,0 +1,3 @@ +FIGMA_APP_CLIENT_SECRET= +FIGMA_APP_CLIENT_ID= +FIGMA_APP_REDIRECT_URI=http://localhost:3000/api/oauth diff --git a/packages/website/lib/auth-storage.ts b/packages/website/lib/auth-storage.ts new file mode 100644 index 00000000..992ac9cc --- /dev/null +++ b/packages/website/lib/auth-storage.ts @@ -0,0 +1,28 @@ +type Auth = { + user_id: number + access_token: string + refresh_token: string + expires_in: number +} + +const store: Record = {} + +export function hasItem(key: string): boolean { + return key in store +} + +export function setItem(key: string, value: Auth): void { + store[key] = value + + setTimeout(() => { + removeItem(key) + }, 10 * 1000) +} + +export function getItem(key: string): Auth | undefined { + return store[key] +} + +export function removeItem(key: string): void { + delete store[key] +} diff --git a/packages/website/pages/api/check/[state].ts b/packages/website/pages/api/check/[state].ts new file mode 100644 index 00000000..3b1501ee --- /dev/null +++ b/packages/website/pages/api/check/[state].ts @@ -0,0 +1,19 @@ +import type { NextApiRequest, NextApiResponse } from 'next' +import { getItem, removeItem } from '../../../lib/auth-storage' + +export default function handler(req: NextApiRequest, res: NextApiResponse) { + if (typeof req.query.state !== 'string') { + return res.status(404).send('') + } + + console.log('invoked', req.query.state) + + const auth = getItem(req.query.state) + + if (auth == null) { + return res.status(404).send('') + } + + removeItem(req.query.state) + res.status(200).json(auth) +} diff --git a/packages/website/pages/api/login/[state].ts b/packages/website/pages/api/login/[state].ts new file mode 100644 index 00000000..d4be16c3 --- /dev/null +++ b/packages/website/pages/api/login/[state].ts @@ -0,0 +1,17 @@ +import type { NextApiRequest, NextApiResponse } from 'next' + +function isValid(state: unknown): state is string { + return typeof state === 'string' && state !== '' +} + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + const { FIGMA_APP_CLIENT_ID, FIGMA_APP_REDIRECT_URI } = process.env + const state = req.query.state + + if (!isValid(state)) { + return res.status(443).json({ message: 'Access denied!' }) + } + + res.setHeader('Set-Cookie', `state=${state}; Path=/api/oauth`) + res.redirect(307, `https://www.figma.com/oauth?client_id=${FIGMA_APP_CLIENT_ID}&redirect_uri=${FIGMA_APP_REDIRECT_URI}&scope=file_read&state=${state}&response_type=code`) +} diff --git a/packages/website/pages/api/oauth.ts b/packages/website/pages/api/oauth.ts new file mode 100644 index 00000000..b8f840e7 --- /dev/null +++ b/packages/website/pages/api/oauth.ts @@ -0,0 +1,34 @@ +import type { NextApiRequest, NextApiResponse } from 'next' +import { setItem } from '../../lib/auth-storage' + +function isValid(cookieState: unknown, queryState: unknown): cookieState is string { + return typeof cookieState === 'string' && typeof queryState === 'string' + && cookieState !== '' && queryState !== '' + && cookieState === queryState +} + +export default async function handler(req: NextApiRequest, res: NextApiResponse) { + const state = req.query.state + const cookieState = req.cookies.state + + // delete `state` cookie + res.setHeader('Set-Cookie', `state=; Path=/api/oauth; Max-Age=0`) + + if (isValid(state, cookieState)) { + const code = req.query.code + + const { FIGMA_APP_CLIENT_ID, FIGMA_APP_CLIENT_SECRET, FIGMA_APP_REDIRECT_URI } = process.env + const auth = await fetch( + `https://www.figma.com/api/oauth/token?client_id=${FIGMA_APP_CLIENT_ID}&client_secret=${FIGMA_APP_CLIENT_SECRET}&redirect_uri=${FIGMA_APP_REDIRECT_URI}&code=${code}&grant_type=authorization_code`, + { + method: 'POST' + } + ) + .then(r => r.json()) + + setItem(state, auth) + res.status(307).redirect('/authorized') + } else { + res.status(443).json({ message: 'Access denied!' }) + } +} diff --git a/packages/website/pages/authorized.tsx b/packages/website/pages/authorized.tsx new file mode 100644 index 00000000..f0c15922 --- /dev/null +++ b/packages/website/pages/authorized.tsx @@ -0,0 +1,15 @@ +import GitHubLink from '../src/GitHubLink' + +export default function HomePage() { + return ( + <> +
+
+

@figma-export

+

you are authorized

+
+
+ + + ); +} diff --git a/packages/website/pages/index.tsx b/packages/website/pages/index.tsx index e0c5fe61..482c17ec 100644 --- a/packages/website/pages/index.tsx +++ b/packages/website/pages/index.tsx @@ -16,8 +16,10 @@ export default function HomePage({ icons, monochromeIcons }: Props) {
- - <GitHubLink /> + <div className='mb-25px'> + <Title /> + <GitHubLink /> + </div> <OutputComponents /> <OutputStyles /> diff --git a/packages/website/scss/index.scss b/packages/website/scss/index.scss index 690ab0ff..8ff656a6 100644 --- a/packages/website/scss/index.scss +++ b/packages/website/scss/index.scss @@ -80,7 +80,7 @@ pre[class*=language-] { .hero { text-align: center; - margin-bottom: 25px; + // margin-bottom: 25px; &:last-child { margin-bottom: 0; @@ -343,4 +343,8 @@ h2 { max-width: 700px; display: block; margin: 0 -15px; +} + +.mb-25px { + margin-bottom: 25px; } \ No newline at end of file diff --git a/yarn.lock b/yarn.lock index 5a10ab4c..e5c01e60 100644 --- a/yarn.lock +++ b/yarn.lock @@ -320,6 +320,7 @@ __metadata: dependencies: "@figma-export/core": ^5.0.1 "@figma-export/types": ^5.0.1 + axios: ^1.4.0 ora: ~5.4.1 sade: ~1.8.1 bin: @@ -553,20 +554,20 @@ __metadata: linkType: hard "@jridgewell/gen-mapping@npm:^0.3.0, @jridgewell/gen-mapping@npm:^0.3.2": - version: 0.3.3 - resolution: "@jridgewell/gen-mapping@npm:0.3.3" + version: 0.3.4 + resolution: "@jridgewell/gen-mapping@npm:0.3.4" dependencies: "@jridgewell/set-array": ^1.0.1 "@jridgewell/sourcemap-codec": ^1.4.10 "@jridgewell/trace-mapping": ^0.3.9 - checksum: 4a74944bd31f22354fc01c3da32e83c19e519e3bbadafa114f6da4522ea77dd0c2842607e923a591d60a76699d819a2fbb6f3552e277efdb9b58b081390b60ab + checksum: 944080268f57919e354c57ea0c787c0b23d6b5be77440a468f8ccad24919e3fcefbd3833ce3b9836d89761503af4cbb750483acdb7fdc15213dde1c26430251d languageName: node linkType: hard "@jridgewell/resolve-uri@npm:^3.0.3, @jridgewell/resolve-uri@npm:^3.1.0": - version: 3.1.1 - resolution: "@jridgewell/resolve-uri@npm:3.1.1" - checksum: f5b441fe7900eab4f9155b3b93f9800a916257f4e8563afbcd3b5a5337b55e52bd8ae6735453b1b745457d9f6cdb16d74cd6220bbdd98cf153239e13f6cbb653 + version: 3.1.2 + resolution: "@jridgewell/resolve-uri@npm:3.1.2" + checksum: 83b85f72c59d1c080b4cbec0fef84528963a1b5db34e4370fa4bd1e3ff64a0d80e0cee7369d11d73c704e0286fb2865b530acac7a871088fbe92b5edf1000870 languageName: node linkType: hard @@ -595,12 +596,12 @@ __metadata: linkType: hard "@jridgewell/trace-mapping@npm:^0.3.17, @jridgewell/trace-mapping@npm:^0.3.9": - version: 0.3.22 - resolution: "@jridgewell/trace-mapping@npm:0.3.22" + version: 0.3.23 + resolution: "@jridgewell/trace-mapping@npm:0.3.23" dependencies: "@jridgewell/resolve-uri": ^3.1.0 "@jridgewell/sourcemap-codec": ^1.4.14 - checksum: ac7dd2cfe0b479aa1b81776d40d789243131cc792dc8b6b6a028c70fcd6171958ae1a71bf67b618ffe3c0c3feead9870c095ee46a5e30319410d92976b28f498 + checksum: a4ebaf196a500c9a65a667ba873f7836ba76b0581ed1c6bd33450b8093182f1c4aeb9c66a4467419cffd15694faecfa027ffbeca3aea5de3d322aa7d6bc41802 languageName: node linkType: hard @@ -1161,11 +1162,11 @@ __metadata: linkType: hard "@npmcli/query@npm:^3.0.0": - version: 3.0.1 - resolution: "@npmcli/query@npm:3.0.1" + version: 3.1.0 + resolution: "@npmcli/query@npm:3.1.0" dependencies: postcss-selector-parser: ^6.0.10 - checksum: b169b9c9a37c5a6e68d61604c7e3175ebdefbc3a77a8981326eaa8fa89cf4044fc6a87bd0fdbe5d096eda2f765aff1477924b55f4e23f64b3143dd1d9004eead + checksum: 33c018bfcc6d64593e7969847d0442beab4e8a42b6c9f932237c9fd135c95ab55de5c4b5d5d66302dd9fc3c748bc4ead780d3595e5d586fedf9859ed6b5f2744 languageName: node linkType: hard @@ -1221,32 +1222,32 @@ __metadata: languageName: node linkType: hard -"@nrwl/devkit@npm:18.0.4": - version: 18.0.4 - resolution: "@nrwl/devkit@npm:18.0.4" +"@nrwl/devkit@npm:18.0.5": + version: 18.0.5 + resolution: "@nrwl/devkit@npm:18.0.5" dependencies: - "@nx/devkit": 18.0.4 - checksum: 7bac6db4dcdcc325668f9c64389f50c6073b945da593add793e73f9f765394e52bc9e620e97ba2ad0b667856420d5ab6fc8ab250889e1432812ec7b9e47e3163 + "@nx/devkit": 18.0.5 + checksum: 5e49a0833a65e2074004414db3f2bf3c22b49821cefca808ce2f059d9124656a0fa5d725f29b73fccf20da4f0f0fb849c708bce3279c567b078c716727df8f74 languageName: node linkType: hard -"@nrwl/tao@npm:18.0.4": - version: 18.0.4 - resolution: "@nrwl/tao@npm:18.0.4" +"@nrwl/tao@npm:18.0.5": + version: 18.0.5 + resolution: "@nrwl/tao@npm:18.0.5" dependencies: - nx: 18.0.4 + nx: 18.0.5 tslib: ^2.3.0 bin: tao: index.js - checksum: 8af7d32976b1be82f308e7b8b825241dbe6de5724e80cb9e24d11e661ab3a67d83c36b251b628d991df7245692eafea8f160d0c2e1d8916afc1db71c5d1e5fbb + checksum: ff20e00e1408f82e650b41d63a991c1d3b9fb75ecb9a2d2111054fbfebc54f7855106d718834f2239b1f71488d1987130ca2d5c55c2c1fa4dc2b6f6a7edb4d85 languageName: node linkType: hard -"@nx/devkit@npm:18.0.4, @nx/devkit@npm:>=17.1.2 < 19": - version: 18.0.4 - resolution: "@nx/devkit@npm:18.0.4" +"@nx/devkit@npm:18.0.5, @nx/devkit@npm:>=17.1.2 < 19": + version: 18.0.5 + resolution: "@nx/devkit@npm:18.0.5" dependencies: - "@nrwl/devkit": 18.0.4 + "@nrwl/devkit": 18.0.5 ejs: ^3.1.7 enquirer: ~2.3.6 ignore: ^5.0.4 @@ -1256,76 +1257,76 @@ __metadata: yargs-parser: 21.1.1 peerDependencies: nx: ">= 16 <= 18" - checksum: e2e515ae6e61027ac2aad27593d1ac853fb622547df19eb5183de14f0f04b7ce4eac7d168e57f9ba77a8ca59da141d33a96c32fc70212979103fd4b8b963c4dc + checksum: 42033bde8583327b5c60295e7fd1bb94d8c1534c5fecf901366cc147ec280b1cd0d2eb57b47d89e7b69add15a0fe9258766f9b6da2cc48d7d427f52b057773dc languageName: node linkType: hard -"@nx/nx-darwin-arm64@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-darwin-arm64@npm:18.0.4" +"@nx/nx-darwin-arm64@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-darwin-arm64@npm:18.0.5" conditions: os=darwin & cpu=arm64 languageName: node linkType: hard -"@nx/nx-darwin-x64@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-darwin-x64@npm:18.0.4" +"@nx/nx-darwin-x64@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-darwin-x64@npm:18.0.5" conditions: os=darwin & cpu=x64 languageName: node linkType: hard -"@nx/nx-freebsd-x64@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-freebsd-x64@npm:18.0.4" +"@nx/nx-freebsd-x64@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-freebsd-x64@npm:18.0.5" conditions: os=freebsd & cpu=x64 languageName: node linkType: hard -"@nx/nx-linux-arm-gnueabihf@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-linux-arm-gnueabihf@npm:18.0.4" +"@nx/nx-linux-arm-gnueabihf@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-linux-arm-gnueabihf@npm:18.0.5" conditions: os=linux & cpu=arm languageName: node linkType: hard -"@nx/nx-linux-arm64-gnu@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-linux-arm64-gnu@npm:18.0.4" +"@nx/nx-linux-arm64-gnu@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-linux-arm64-gnu@npm:18.0.5" conditions: os=linux & cpu=arm64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-arm64-musl@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-linux-arm64-musl@npm:18.0.4" +"@nx/nx-linux-arm64-musl@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-linux-arm64-musl@npm:18.0.5" conditions: os=linux & cpu=arm64 & libc=musl languageName: node linkType: hard -"@nx/nx-linux-x64-gnu@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-linux-x64-gnu@npm:18.0.4" +"@nx/nx-linux-x64-gnu@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-linux-x64-gnu@npm:18.0.5" conditions: os=linux & cpu=x64 & libc=glibc languageName: node linkType: hard -"@nx/nx-linux-x64-musl@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-linux-x64-musl@npm:18.0.4" +"@nx/nx-linux-x64-musl@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-linux-x64-musl@npm:18.0.5" conditions: os=linux & cpu=x64 & libc=musl languageName: node linkType: hard -"@nx/nx-win32-arm64-msvc@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-win32-arm64-msvc@npm:18.0.4" +"@nx/nx-win32-arm64-msvc@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-win32-arm64-msvc@npm:18.0.5" conditions: os=win32 & cpu=arm64 languageName: node linkType: hard -"@nx/nx-win32-x64-msvc@npm:18.0.4": - version: 18.0.4 - resolution: "@nx/nx-win32-x64-msvc@npm:18.0.4" +"@nx/nx-win32-x64-msvc@npm:18.0.5": + version: 18.0.5 + resolution: "@nx/nx-win32-x64-msvc@npm:18.0.5" conditions: os=win32 & cpu=x64 languageName: node linkType: hard @@ -1532,12 +1533,12 @@ __metadata: languageName: node linkType: hard -"@sigstore/bundle@npm:^2.1.1": - version: 2.1.1 - resolution: "@sigstore/bundle@npm:2.1.1" +"@sigstore/bundle@npm:^2.2.0": + version: 2.2.0 + resolution: "@sigstore/bundle@npm:2.2.0" dependencies: - "@sigstore/protobuf-specs": ^0.2.1 - checksum: c441904765e94710288f3fcf0458f2544a9b480b239219eb738f11bddb2518a5dc5b4a3f8ca22884d7948f1034d4b802ce74a4d21517a35b7ac52970f78971f0 + "@sigstore/protobuf-specs": ^0.3.0 + checksum: 08f71c19b5223694e4915dd1ada9dcae66637051cbb7ac3968122bd38e8a2078e52d28ed6b18f1dbe2408740304cf76675180fdc51cbd74b167200a47d4a325b languageName: node linkType: hard @@ -1548,13 +1549,20 @@ __metadata: languageName: node linkType: hard -"@sigstore/protobuf-specs@npm:^0.2.0, @sigstore/protobuf-specs@npm:^0.2.1": +"@sigstore/protobuf-specs@npm:^0.2.0": version: 0.2.1 resolution: "@sigstore/protobuf-specs@npm:0.2.1" checksum: ddb7c829c7bf4148eccb571ede07cf9fda62f46b7b4d3a5ca02c0308c950ee90b4206b61082ee8d5753f24098632a8b24c147117bef8c68791bf5da537b55db9 languageName: node linkType: hard +"@sigstore/protobuf-specs@npm:^0.3.0": + version: 0.3.0 + resolution: "@sigstore/protobuf-specs@npm:0.3.0" + checksum: 584ea2888aede7124c747a343ab09dd5234195973f15169b6afff19f87347c2e29a2e688298dba87827883c704096fc31a8a0748049dde0b85fbec2cf922a350 + languageName: node + linkType: hard + "@sigstore/sign@npm:^1.0.0": version: 1.0.0 resolution: "@sigstore/sign@npm:1.0.0" @@ -1566,15 +1574,15 @@ __metadata: languageName: node linkType: hard -"@sigstore/sign@npm:^2.2.2": - version: 2.2.2 - resolution: "@sigstore/sign@npm:2.2.2" +"@sigstore/sign@npm:^2.2.3": + version: 2.2.3 + resolution: "@sigstore/sign@npm:2.2.3" dependencies: - "@sigstore/bundle": ^2.1.1 + "@sigstore/bundle": ^2.2.0 "@sigstore/core": ^1.0.0 - "@sigstore/protobuf-specs": ^0.2.1 + "@sigstore/protobuf-specs": ^0.3.0 make-fetch-happen: ^13.0.0 - checksum: 59d53822c2f6dc247df144d8d586d3d6eee169f58964244153cbdfb56fd42aba63180694710230232fef25dcf8f1b27d541af4be56c6dad4d7fb52f5b271e204 + checksum: 191a74d6bfa4d8c8fafeebc07f871145a1f883a832a763f27ec1973f182f713fce07828d98d6052a96277a4ac4dd0f915adac4cf33bcde6737c905b43304be9e languageName: node linkType: hard @@ -1588,24 +1596,24 @@ __metadata: languageName: node linkType: hard -"@sigstore/tuf@npm:^2.3.0": - version: 2.3.0 - resolution: "@sigstore/tuf@npm:2.3.0" +"@sigstore/tuf@npm:^2.3.1": + version: 2.3.1 + resolution: "@sigstore/tuf@npm:2.3.1" dependencies: - "@sigstore/protobuf-specs": ^0.2.1 + "@sigstore/protobuf-specs": ^0.3.0 tuf-js: ^2.2.0 - checksum: 77ed2931c4e80b13310ccb1f57623bdf20b8c1d1760a07ed2f0b6c31aeed799cb839646f688c7cc3be05e05f7cf25acce18d90a864774ce768834a6e9017deef + checksum: 809befef876567b14240ee41baabc5b595e9d5a245c7cf31b7ae2e37f4600e0ac353b010807f5caa7b720d12f630ea5b33d2f222c1844083d6a1ee08b3cc4250 languageName: node linkType: hard -"@sigstore/verify@npm:^1.0.0": - version: 1.0.0 - resolution: "@sigstore/verify@npm:1.0.0" +"@sigstore/verify@npm:^1.1.0": + version: 1.1.0 + resolution: "@sigstore/verify@npm:1.1.0" dependencies: - "@sigstore/bundle": ^2.1.1 + "@sigstore/bundle": ^2.2.0 "@sigstore/core": ^1.0.0 - "@sigstore/protobuf-specs": ^0.2.1 - checksum: 7e4d93bc0a6d7932ebe4794aab780b5c0e2eff02269aae9981b270900f23fc01bcf44d8ce00ce5d58825bde778f71a514885e12ee692d501f4f1cb9ad647aeb3 + "@sigstore/protobuf-specs": ^0.3.0 + checksum: dcc978d7cbad4adf05d16a44b17d6bbce401381adf3909b3524a627eee37ed0ef1b66c4db1eba0965d42a3dea2444a01c985ea3358f01ec48053eeb13e0a6aad languageName: node linkType: hard @@ -1914,14 +1922,7 @@ __metadata: languageName: node linkType: hard -"@types/chai@npm:*": - version: 4.3.11 - resolution: "@types/chai@npm:4.3.11" - checksum: d0c05fe5d02b2e6bbca2bd4866a2ab20a59cf729bc04af0060e7a3277eaf2fb65651b90d4c74b0ebf1d152b4b1d49fa8e44143acef276a2bbaa7785fbe5642d3 - languageName: node - linkType: hard - -"@types/chai@npm:~4.3.12": +"@types/chai@npm:*, @types/chai@npm:~4.3.12": version: 4.3.12 resolution: "@types/chai@npm:4.3.12" checksum: 64e9354181046bfc78f527bba006f2e58b49efb702a501bdd1faec51e21e4d2248e7fb49843fd3f2189e3bf3680480b94e8a1ab6d097e67183bdeacd6d024ed6 @@ -1970,16 +1971,7 @@ __metadata: languageName: node linkType: hard -"@types/node@npm:*": - version: 20.11.17 - resolution: "@types/node@npm:20.11.17" - dependencies: - undici-types: ~5.26.4 - checksum: 59c0dde187120adc97da30063c86511664b24b50fe777abfe1f557c217d0a0b84a68aaab5ef8ac44f5c2986b3f9cd605a15fa6e4f31195e594da96bbe9617c20 - languageName: node - linkType: hard - -"@types/node@npm:~20.11.20": +"@types/node@npm:*, @types/node@npm:~20.11.20": version: 20.11.20 resolution: "@types/node@npm:20.11.20" dependencies: @@ -2003,13 +1995,13 @@ __metadata: linkType: hard "@types/react@npm:^18.2.58": - version: 18.2.58 - resolution: "@types/react@npm:18.2.58" + version: 18.2.59 + resolution: "@types/react@npm:18.2.59" dependencies: "@types/prop-types": "*" "@types/scheduler": "*" csstype: ^3.0.2 - checksum: 42551e30c8a54161a11b2ecd11406782ddba4472a4471d45034c551295263d56f06234f283526d0c0420352ce9ce9675b2a6c65db7a287d9613643d3ceaaf1f0 + checksum: 0b6c72d22817039b90b889eec1a3099ed9b194b2971f6322671e6a5eddc384356e0fd1d7b0c0d0e92e828c9515b85458d19f923d9e99dc49694850acc5190650 languageName: node linkType: hard @@ -2028,9 +2020,9 @@ __metadata: linkType: hard "@types/semver@npm:^7.5.0": - version: 7.5.7 - resolution: "@types/semver@npm:7.5.7" - checksum: 5af9b13e3d74d86d4b618f6506ccbded801fb35dbc28608cd5a7bfb8bcac0021dd35ef305a72a0c2a8def0cff60acd706bfee16a9ed1c39a893d2a175e778ea7 + version: 7.5.8 + resolution: "@types/semver@npm:7.5.8" + checksum: ea6f5276f5b84c55921785a3a27a3cd37afee0111dfe2bcb3e03c31819c197c782598f17f0b150a69d453c9584cd14c4c4d7b9a55d2c5e6cacd4d66fdb3b3663 languageName: node linkType: hard @@ -2586,7 +2578,7 @@ __metadata: languageName: node linkType: hard -"array-buffer-byte-length@npm:^1.0.0, array-buffer-byte-length@npm:^1.0.1": +"array-buffer-byte-length@npm:^1.0.1": version: 1.0.1 resolution: "array-buffer-byte-length@npm:1.0.1" dependencies: @@ -2731,7 +2723,7 @@ __metadata: languageName: node linkType: hard -"arraybuffer.prototype.slice@npm:^1.0.2": +"arraybuffer.prototype.slice@npm:^1.0.3": version: 1.0.3 resolution: "arraybuffer.prototype.slice@npm:1.0.3" dependencies: @@ -2812,10 +2804,12 @@ __metadata: languageName: node linkType: hard -"available-typed-arrays@npm:^1.0.5, available-typed-arrays@npm:^1.0.6": - version: 1.0.6 - resolution: "available-typed-arrays@npm:1.0.6" - checksum: 8295571eb86447138adf64a0df0c08ae61250b17190bba30e1fae8c80a816077a6d028e5506f602c382c0197d3080bae131e92e331139d55460989580eeae659 +"available-typed-arrays@npm:^1.0.6, available-typed-arrays@npm:^1.0.7": + version: 1.0.7 + resolution: "available-typed-arrays@npm:1.0.7" + dependencies: + possible-typed-array-names: ^1.0.0 + checksum: 1aa3ffbfe6578276996de660848b6e95669d9a95ad149e3dd0c0cda77db6ee1dbd9d1dd723b65b6d277b882dd0c4b91a654ae9d3cf9e1254b7e93e4908d78fd3 languageName: node linkType: hard @@ -2970,16 +2964,16 @@ __metadata: linkType: hard "browserslist@npm:^4.22.2": - version: 4.22.3 - resolution: "browserslist@npm:4.22.3" + version: 4.23.0 + resolution: "browserslist@npm:4.23.0" dependencies: - caniuse-lite: ^1.0.30001580 - electron-to-chromium: ^1.4.648 + caniuse-lite: ^1.0.30001587 + electron-to-chromium: ^1.4.668 node-releases: ^2.0.14 update-browserslist-db: ^1.0.13 bin: browserslist: cli.js - checksum: e62b17348e92143fe58181b02a6a97c4a98bd812d1dc9274673a54f73eec53dbed1c855ebf73e318ee00ee039f23c9a6d0e7629d24f3baef08c7a5b469742d57 + checksum: 436f49e796782ca751ebab7edc010cfc9c29f68536f387666cd70ea22f7105563f04dd62c6ff89cb24cc3254d17cba385f979eeeb3484d43e012412ff7e75def languageName: node linkType: hard @@ -3158,7 +3152,7 @@ __metadata: languageName: node linkType: hard -"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6": +"call-bind@npm:^1.0.2, call-bind@npm:^1.0.5, call-bind@npm:^1.0.6, call-bind@npm:^1.0.7": version: 1.0.7 resolution: "call-bind@npm:1.0.7" dependencies: @@ -3210,10 +3204,10 @@ __metadata: languageName: node linkType: hard -"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001580": - version: 1.0.30001587 - resolution: "caniuse-lite@npm:1.0.30001587" - checksum: fb50aa9beaaae42f9feae92ce038f6ff71e97510f024ef1bef2666f3adcfd36d6c59e5675442e5fe795575193f71bc826cb7721d4b0f6d763e82d193bea57863 +"caniuse-lite@npm:^1.0.30001406, caniuse-lite@npm:^1.0.30001587": + version: 1.0.30001589 + resolution: "caniuse-lite@npm:1.0.30001589" + checksum: 7a6e6c4fb14c2bd0103a8f744bdd8701c1a5f19162f4a7600b89e25bc86d689f82204dc135f3a1dcd1a53050caa04fd0bb39b7df88698a6b90f189ec48900689 languageName: node linkType: hard @@ -4118,7 +4112,7 @@ __metadata: languageName: node linkType: hard -"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.2": +"define-data-property@npm:^1.0.1, define-data-property@npm:^1.1.2, define-data-property@npm:^1.1.4": version: 1.1.4 resolution: "define-data-property@npm:1.1.4" dependencies: @@ -4383,10 +4377,10 @@ __metadata: languageName: node linkType: hard -"electron-to-chromium@npm:^1.4.648": - version: 1.4.667 - resolution: "electron-to-chromium@npm:1.4.667" - checksum: 18826f242e390a5ad5696c836c4c1e15ce1308fb667f053b31f67ee675857a6774047a4ed179c62d39789850f3d4f13d450625b913930b049a78e5c6d5eae7a5 +"electron-to-chromium@npm:^1.4.668": + version: 1.4.682 + resolution: "electron-to-chromium@npm:1.4.682" + checksum: d7b0cfc9a338c7447648127cb7609f058d0bd346818a12661dfc2b2b3c1e07dd78763fa03826f6cde98f0afb6365523243882ac20dd316bb2b775cdc597e14cf languageName: node linkType: hard @@ -4494,50 +4488,52 @@ __metadata: languageName: node linkType: hard -"es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3": - version: 1.22.3 - resolution: "es-abstract@npm:1.22.3" +"es-abstract@npm:^1.20.4, es-abstract@npm:^1.22.1, es-abstract@npm:^1.22.3, es-abstract@npm:^1.22.4": + version: 1.22.4 + resolution: "es-abstract@npm:1.22.4" dependencies: - array-buffer-byte-length: ^1.0.0 - arraybuffer.prototype.slice: ^1.0.2 - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.5 - es-set-tostringtag: ^2.0.1 + array-buffer-byte-length: ^1.0.1 + arraybuffer.prototype.slice: ^1.0.3 + available-typed-arrays: ^1.0.6 + call-bind: ^1.0.7 + es-define-property: ^1.0.0 + es-errors: ^1.3.0 + es-set-tostringtag: ^2.0.2 es-to-primitive: ^1.2.1 function.prototype.name: ^1.1.6 - get-intrinsic: ^1.2.2 - get-symbol-description: ^1.0.0 + get-intrinsic: ^1.2.4 + get-symbol-description: ^1.0.2 globalthis: ^1.0.3 gopd: ^1.0.1 - has-property-descriptors: ^1.0.0 + has-property-descriptors: ^1.0.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 - hasown: ^2.0.0 - internal-slot: ^1.0.5 - is-array-buffer: ^3.0.2 + hasown: ^2.0.1 + internal-slot: ^1.0.7 + is-array-buffer: ^3.0.4 is-callable: ^1.2.7 is-negative-zero: ^2.0.2 is-regex: ^1.1.4 is-shared-array-buffer: ^1.0.2 is-string: ^1.0.7 - is-typed-array: ^1.1.12 + is-typed-array: ^1.1.13 is-weakref: ^1.0.2 object-inspect: ^1.13.1 object-keys: ^1.1.1 - object.assign: ^4.1.4 - regexp.prototype.flags: ^1.5.1 - safe-array-concat: ^1.0.1 - safe-regex-test: ^1.0.0 + object.assign: ^4.1.5 + regexp.prototype.flags: ^1.5.2 + safe-array-concat: ^1.1.0 + safe-regex-test: ^1.0.3 string.prototype.trim: ^1.2.8 string.prototype.trimend: ^1.0.7 string.prototype.trimstart: ^1.0.7 - typed-array-buffer: ^1.0.0 + typed-array-buffer: ^1.0.1 typed-array-byte-length: ^1.0.0 typed-array-byte-offset: ^1.0.0 typed-array-length: ^1.0.4 unbox-primitive: ^1.0.2 - which-typed-array: ^1.1.13 - checksum: b1bdc962856836f6e72be10b58dc128282bdf33771c7a38ae90419d920fc3b36cc5d2b70a222ad8016e3fc322c367bf4e9e89fc2bc79b7e933c05b218e83d79a + which-typed-array: ^1.1.14 + checksum: c254102395bd59315b713d72a1ce07980c0f71c9edcac6b036868740789ab5344020e940d6321fc1b31aecf6b27941fdd9655b602696e08f170986dd4d75ddc6 languageName: node linkType: hard @@ -4582,36 +4578,36 @@ __metadata: linkType: hard "es-iterator-helpers@npm:^1.0.12, es-iterator-helpers@npm:^1.0.15": - version: 1.0.16 - resolution: "es-iterator-helpers@npm:1.0.16" + version: 1.0.17 + resolution: "es-iterator-helpers@npm:1.0.17" dependencies: asynciterator.prototype: ^1.0.0 - call-bind: ^1.0.6 + call-bind: ^1.0.7 define-properties: ^1.2.1 - es-abstract: ^1.22.3 + es-abstract: ^1.22.4 es-errors: ^1.3.0 es-set-tostringtag: ^2.0.2 function-bind: ^1.1.2 get-intrinsic: ^1.2.4 globalthis: ^1.0.3 - has-property-descriptors: ^1.0.1 + has-property-descriptors: ^1.0.2 has-proto: ^1.0.1 has-symbols: ^1.0.3 internal-slot: ^1.0.7 iterator.prototype: ^1.1.2 safe-array-concat: ^1.1.0 - checksum: 3c968e85854bab9bb984b9b9d973a6fab010e80ddec9d9fbd4224b720b3c8d0e6ca633a13bf87d603706ff3fccec28af02280d2c92b1ad0f3ca6789d18c37e8c + checksum: f0962abbf120c37516c9008716fcaffeacf7bc6147a07e63cda3c3ac8be94b88e4ef8d71234c4b8873d1fc209f65c6d9e11a7faac78f59b5d3bcfa399affed7b languageName: node linkType: hard -"es-set-tostringtag@npm:^2.0.1, es-set-tostringtag@npm:^2.0.2": - version: 2.0.2 - resolution: "es-set-tostringtag@npm:2.0.2" +"es-set-tostringtag@npm:^2.0.2": + version: 2.0.3 + resolution: "es-set-tostringtag@npm:2.0.3" dependencies: - get-intrinsic: ^1.2.2 - has-tostringtag: ^1.0.0 - hasown: ^2.0.0 - checksum: afcec3a4c9890ae14d7ec606204858441c801ff84f312538e1d1ccf1e5493c8b17bd672235df785f803756472cb4f2d49b87bde5237aef33411e74c22f194e07 + get-intrinsic: ^1.2.4 + has-tostringtag: ^1.0.2 + hasown: ^2.0.1 + checksum: 7227fa48a41c0ce83e0377b11130d324ac797390688135b8da5c28994c0165be8b252e15cd1de41e1325e5a5412511586960213e88f9ab4a5e7d028895db5129 languageName: node linkType: hard @@ -5263,9 +5259,9 @@ __metadata: linkType: hard "flatted@npm:^3.2.9": - version: 3.2.9 - resolution: "flatted@npm:3.2.9" - checksum: f14167fbe26a9d20f6fca8d998e8f1f41df72c8e81f9f2c9d61ed2bea058248f5e1cbd05e7f88c0e5087a6a0b822a1e5e2b446e879f3cfbe0b07ba2d7f80b026 + version: 3.3.1 + resolution: "flatted@npm:3.3.1" + checksum: 85ae7181650bb728c221e7644cbc9f4bf28bc556f2fc89bb21266962bdf0ce1029cc7acc44bb646cd469d9baac7c317f64e841c4c4c00516afa97320cdac7f94 languageName: node linkType: hard @@ -5581,7 +5577,7 @@ __metadata: languageName: node linkType: hard -"get-symbol-description@npm:^1.0.0": +"get-symbol-description@npm:^1.0.2": version: 1.0.2 resolution: "get-symbol-description@npm:1.0.2" dependencies: @@ -5900,7 +5896,7 @@ __metadata: languageName: node linkType: hard -"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1": +"has-property-descriptors@npm:^1.0.0, has-property-descriptors@npm:^1.0.1, has-property-descriptors@npm:^1.0.2": version: 1.0.2 resolution: "has-property-descriptors@npm:1.0.2" dependencies: @@ -5909,10 +5905,10 @@ __metadata: languageName: node linkType: hard -"has-proto@npm:^1.0.1": - version: 1.0.1 - resolution: "has-proto@npm:1.0.1" - checksum: febc5b5b531de8022806ad7407935e2135f1cc9e64636c3916c6842bd7995994ca3b29871ecd7954bd35f9e2986c17b3b227880484d22259e2f8e6ce63fd383e +"has-proto@npm:^1.0.1, has-proto@npm:^1.0.3": + version: 1.0.3 + resolution: "has-proto@npm:1.0.3" + checksum: fe7c3d50b33f50f3933a04413ed1f69441d21d2d2944f81036276d30635cad9279f6b43bc8f32036c31ebdfcf6e731150f46c1907ad90c669ffe9b066c3ba5c4 languageName: node linkType: hard @@ -5923,7 +5919,7 @@ __metadata: languageName: node linkType: hard -"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1": +"has-tostringtag@npm:^1.0.0, has-tostringtag@npm:^1.0.1, has-tostringtag@npm:^1.0.2": version: 1.0.2 resolution: "has-tostringtag@npm:1.0.2" dependencies: @@ -5956,7 +5952,7 @@ __metadata: languageName: node linkType: hard -"hasown@npm:^2.0.0": +"hasown@npm:^2.0.0, hasown@npm:^2.0.1": version: 2.0.1 resolution: "hasown@npm:2.0.1" dependencies: @@ -6082,12 +6078,12 @@ __metadata: linkType: hard "http-proxy-agent@npm:^7.0.0": - version: 7.0.1 - resolution: "http-proxy-agent@npm:7.0.1" + version: 7.0.2 + resolution: "http-proxy-agent@npm:7.0.2" dependencies: agent-base: ^7.1.0 debug: ^4.3.4 - checksum: e8e153dc9106c2a2a05f7a576ea2002ab4a24f2586eeab3947571962532829c0c7cf8a88e67c2cfe2fff9a81deb27e9b5d69452f4a8a1b5d7066a162763e6307 + checksum: 670858c8f8f3146db5889e1fa117630910101db601fff7d5a8aa637da0abedf68c899f03d3451cac2f83bcc4c3d2dabf339b3aa00ff8080571cceb02c3ce02f3 languageName: node linkType: hard @@ -6112,12 +6108,12 @@ __metadata: linkType: hard "https-proxy-agent@npm:^7.0.1": - version: 7.0.3 - resolution: "https-proxy-agent@npm:7.0.3" + version: 7.0.4 + resolution: "https-proxy-agent@npm:7.0.4" dependencies: agent-base: ^7.0.2 debug: 4 - checksum: 8aacdde7db31d57674e86e23ecb5f37d79baf54dfc674a44671cb33c1f6a302cc78b2bdf042f6ce37f7c0c61b9b556965cb34f5484880b1864171122dedbdd7d + checksum: daaab857a967a2519ddc724f91edbbd388d766ff141b9025b629f92b9408fc83cee8a27e11a907aede392938e9c398e240d643e178408a59e4073539cde8cfe9 languageName: node linkType: hard @@ -6367,7 +6363,7 @@ __metadata: languageName: node linkType: hard -"is-array-buffer@npm:^3.0.2, is-array-buffer@npm:^3.0.4": +"is-array-buffer@npm:^3.0.4": version: 3.0.4 resolution: "is-array-buffer@npm:3.0.4" dependencies: @@ -6555,9 +6551,9 @@ __metadata: linkType: hard "is-negative-zero@npm:^2.0.2": - version: 2.0.2 - resolution: "is-negative-zero@npm:2.0.2" - checksum: f3232194c47a549da60c3d509c9a09be442507616b69454716692e37ae9f37c4dea264fb208ad0c9f3efd15a796a46b79df07c7e53c6227c32170608b809149a + version: 2.0.3 + resolution: "is-negative-zero@npm:2.0.3" + checksum: c1e6b23d2070c0539d7b36022d5a94407132411d01aba39ec549af824231f3804b1aea90b5e4e58e807a65d23ceb538ed6e355ce76b267bdd86edb757ffcbdcd languageName: node linkType: hard @@ -6653,11 +6649,11 @@ __metadata: linkType: hard "is-shared-array-buffer@npm:^1.0.2": - version: 1.0.2 - resolution: "is-shared-array-buffer@npm:1.0.2" + version: 1.0.3 + resolution: "is-shared-array-buffer@npm:1.0.3" dependencies: - call-bind: ^1.0.2 - checksum: 9508929cf14fdc1afc9d61d723c6e8d34f5e117f0bffda4d97e7a5d88c3a8681f633a74f8e3ad1fe92d5113f9b921dc5ca44356492079612f9a247efbce7032a + call-bind: ^1.0.7 + checksum: a4fff602c309e64ccaa83b859255a43bb011145a42d3f56f67d9268b55bc7e6d98a5981a1d834186ad3105d6739d21547083fe7259c76c0468483fc538e716d8 languageName: node linkType: hard @@ -6718,7 +6714,7 @@ __metadata: languageName: node linkType: hard -"is-typed-array@npm:^1.1.10, is-typed-array@npm:^1.1.12, is-typed-array@npm:^1.1.13, is-typed-array@npm:^1.1.9": +"is-typed-array@npm:^1.1.13": version: 1.1.13 resolution: "is-typed-array@npm:1.1.13" dependencies: @@ -6897,12 +6893,12 @@ __metadata: linkType: hard "istanbul-reports@npm:^3.0.2": - version: 3.1.6 - resolution: "istanbul-reports@npm:3.1.6" + version: 3.1.7 + resolution: "istanbul-reports@npm:3.1.7" dependencies: html-escaper: ^2.0.0 istanbul-lib-report: ^3.0.0 - checksum: 44c4c0582f287f02341e9720997f9e82c071627e1e862895745d5f52ec72c9b9f38e1d12370015d2a71dcead794f34c7732aaef3fab80a24bc617a21c3d911d6 + checksum: 2072db6e07bfbb4d0eb30e2700250636182398c1af811aea5032acb219d2080f7586923c09fa194029efd6b92361afb3dcbe1ebcc3ee6651d13340f7c6c4ed95 languageName: node linkType: hard @@ -8915,11 +8911,11 @@ __metadata: linkType: hard "npm-run-path@npm:^5.1.0": - version: 5.2.0 - resolution: "npm-run-path@npm:5.2.0" + version: 5.3.0 + resolution: "npm-run-path@npm:5.3.0" dependencies: path-key: ^4.0.0 - checksum: c5325e016014e715689c4014f7e0be16cc4cbf529f32a1723e511bc4689b5f823b704d2bca61ac152ce2bda65e0205dc8b3ba0ec0f5e4c3e162d302f6f5b9efb + checksum: ae8e7a89da9594fb9c308f6555c73f618152340dcaae423e5fb3620026fefbec463618a8b761920382d666fa7a2d8d240b6fe320e8a6cdd54dc3687e2b659d25 languageName: node linkType: hard @@ -8956,21 +8952,21 @@ __metadata: languageName: node linkType: hard -"nx@npm:18.0.4, nx@npm:>=17.1.2 < 19": - version: 18.0.4 - resolution: "nx@npm:18.0.4" +"nx@npm:18.0.5, nx@npm:>=17.1.2 < 19": + version: 18.0.5 + resolution: "nx@npm:18.0.5" dependencies: - "@nrwl/tao": 18.0.4 - "@nx/nx-darwin-arm64": 18.0.4 - "@nx/nx-darwin-x64": 18.0.4 - "@nx/nx-freebsd-x64": 18.0.4 - "@nx/nx-linux-arm-gnueabihf": 18.0.4 - "@nx/nx-linux-arm64-gnu": 18.0.4 - "@nx/nx-linux-arm64-musl": 18.0.4 - "@nx/nx-linux-x64-gnu": 18.0.4 - "@nx/nx-linux-x64-musl": 18.0.4 - "@nx/nx-win32-arm64-msvc": 18.0.4 - "@nx/nx-win32-x64-msvc": 18.0.4 + "@nrwl/tao": 18.0.5 + "@nx/nx-darwin-arm64": 18.0.5 + "@nx/nx-darwin-x64": 18.0.5 + "@nx/nx-freebsd-x64": 18.0.5 + "@nx/nx-linux-arm-gnueabihf": 18.0.5 + "@nx/nx-linux-arm64-gnu": 18.0.5 + "@nx/nx-linux-arm64-musl": 18.0.5 + "@nx/nx-linux-x64-gnu": 18.0.5 + "@nx/nx-linux-x64-musl": 18.0.5 + "@nx/nx-win32-arm64-msvc": 18.0.5 + "@nx/nx-win32-x64-msvc": 18.0.5 "@yarnpkg/lockfile": ^1.1.0 "@yarnpkg/parsers": 3.0.0-rc.46 "@zkochan/js-yaml": 0.0.6 @@ -9036,7 +9032,7 @@ __metadata: bin: nx: bin/nx.js nx-cloud: bin/nx-cloud.js - checksum: d6d06285db13851577bada69bcb407e3802c6e7c3fa18b7314c0b6f916e6fb5e8529fc166e9821050949f74ec57f57623781c4d49782bae5ab437f0c6ccc64b3 + checksum: e23a6cf588559b6237532ef7dc8dc257c7602da31e3b60ef3e5fa57a88f3b64b0022aba45b8369757cc0ce4bd08076e22d1c742944ce001325d90a7986d4abbe languageName: node linkType: hard @@ -9098,7 +9094,7 @@ __metadata: languageName: node linkType: hard -"object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4": +"object.assign@npm:^4.1.0, object.assign@npm:^4.1.2, object.assign@npm:^4.1.4, object.assign@npm:^4.1.5": version: 4.1.5 resolution: "object.assign@npm:4.1.5" dependencies: @@ -9796,6 +9792,13 @@ __metadata: languageName: node linkType: hard +"possible-typed-array-names@npm:^1.0.0": + version: 1.0.0 + resolution: "possible-typed-array-names@npm:1.0.0" + checksum: b32d403ece71e042385cc7856385cecf1cd8e144fa74d2f1de40d1e16035dba097bc189715925e79b67bdd1472796ff168d3a90d296356c9c94d272d5b95f3ae + languageName: node + linkType: hard + "postcss-selector-parser@npm:^6.0.10": version: 6.0.15 resolution: "postcss-selector-parser@npm:6.0.15" @@ -10319,7 +10322,7 @@ __metadata: languageName: node linkType: hard -"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.1": +"regexp.prototype.flags@npm:^1.5.0, regexp.prototype.flags@npm:^1.5.2": version: 1.5.2 resolution: "regexp.prototype.flags@npm:1.5.2" dependencies: @@ -10599,7 +10602,7 @@ __metadata: languageName: node linkType: hard -"safe-array-concat@npm:^1.0.1, safe-array-concat@npm:^1.1.0": +"safe-array-concat@npm:^1.1.0": version: 1.1.0 resolution: "safe-array-concat@npm:1.1.0" dependencies: @@ -10625,7 +10628,7 @@ __metadata: languageName: node linkType: hard -"safe-regex-test@npm:^1.0.0": +"safe-regex-test@npm:^1.0.3": version: 1.0.3 resolution: "safe-regex-test@npm:1.0.3" dependencies: @@ -10741,13 +10744,14 @@ __metadata: linkType: hard "set-function-name@npm:^2.0.0, set-function-name@npm:^2.0.1": - version: 2.0.1 - resolution: "set-function-name@npm:2.0.1" + version: 2.0.2 + resolution: "set-function-name@npm:2.0.2" dependencies: - define-data-property: ^1.0.1 + define-data-property: ^1.1.4 + es-errors: ^1.3.0 functions-have-names: ^1.2.3 - has-property-descriptors: ^1.0.0 - checksum: 4975d17d90c40168eee2c7c9c59d023429f0a1690a89d75656306481ece0c3c1fb1ebcc0150ea546d1913e35fbd037bace91372c69e543e51fc5d1f31a9fa126 + has-property-descriptors: ^1.0.2 + checksum: d6229a71527fd0404399fc6227e0ff0652800362510822a291925c9d7b48a1ca1a468b11b281471c34cd5a2da0db4f5d7ff315a61d26655e77f6e971e6d0c80f languageName: node linkType: hard @@ -10841,16 +10845,16 @@ __metadata: linkType: hard "sigstore@npm:^2.2.0": - version: 2.2.1 - resolution: "sigstore@npm:2.2.1" + version: 2.2.2 + resolution: "sigstore@npm:2.2.2" dependencies: - "@sigstore/bundle": ^2.1.1 + "@sigstore/bundle": ^2.2.0 "@sigstore/core": ^1.0.0 - "@sigstore/protobuf-specs": ^0.2.1 - "@sigstore/sign": ^2.2.2 - "@sigstore/tuf": ^2.3.0 - "@sigstore/verify": ^1.0.0 - checksum: 410d9e1113a6d620ffe4ed01564afb77fcc4b87acf836b2cd5d80d18d5c496c7afad2f8a6a31f0a980658be2aa8fb2d60a1f190d3a5d4d2352c45153469e962a + "@sigstore/protobuf-specs": ^0.3.0 + "@sigstore/sign": ^2.2.3 + "@sigstore/tuf": ^2.3.1 + "@sigstore/verify": ^1.1.0 + checksum: 7bb2bd0a971246bbd1d1cfb749404a4a1700dfdd4ea288e922b167af3643d2f2e0e5c25b6b1701701c66f086a8138097c7572a59e288a0b0e4e4e28e5df4f16c languageName: node linkType: hard @@ -10974,12 +10978,12 @@ __metadata: linkType: hard "socks@npm:^2.6.2, socks@npm:^2.7.1": - version: 2.8.0 - resolution: "socks@npm:2.8.0" + version: 2.8.1 + resolution: "socks@npm:2.8.1" dependencies: ip-address: ^9.0.5 smart-buffer: ^4.2.0 - checksum: b245081650c5fc112f0e10d2ee3976f5665d2191b9f86b181edd3c875d53d84a94bc173752d5be2651a450e3ef799fe7ec405dba3165890c08d9ac0b4ec1a487 + checksum: 29586d42e9c36c5016632b2bcb6595e3adfbcb694b3a652c51bc8741b079c5ec37bdd5675a1a89a1620078c8137208294991fabb50786f92d47759a725b2b62e languageName: node linkType: hard @@ -11050,9 +11054,9 @@ __metadata: linkType: hard "spdx-exceptions@npm:^2.1.0": - version: 2.4.0 - resolution: "spdx-exceptions@npm:2.4.0" - checksum: b1b650a8d94424473bf9629cf972c86a91c03cccc260f5c901bce0e4b92d831627fec28c9e0a1e9c34c5ebad0a12cf2eab887bec088e0a862abb9d720c2fd0a1 + version: 2.5.0 + resolution: "spdx-exceptions@npm:2.5.0" + checksum: bb127d6e2532de65b912f7c99fc66097cdea7d64c10d3ec9b5e96524dbbd7d20e01cba818a6ddb2ae75e62bb0c63d5e277a7e555a85cbc8ab40044984fa4ae15 languageName: node linkType: hard @@ -11807,50 +11811,55 @@ __metadata: languageName: node linkType: hard -"typed-array-buffer@npm:^1.0.0": - version: 1.0.1 - resolution: "typed-array-buffer@npm:1.0.1" +"typed-array-buffer@npm:^1.0.1": + version: 1.0.2 + resolution: "typed-array-buffer@npm:1.0.2" dependencies: - call-bind: ^1.0.6 + call-bind: ^1.0.7 es-errors: ^1.3.0 is-typed-array: ^1.1.13 - checksum: 1d65e46b2b9b7ec2a30df39b9ddf32e55ad08d6119aec33975506a3dba56057796bdc3c64dbeb7fdb61bf340a75e279dfd55b48ce8f3b874f01731e1da6833d2 + checksum: 02ffc185d29c6df07968272b15d5319a1610817916ec8d4cd670ded5d1efe72901541ff2202fcc622730d8a549c76e198a2f74e312eabbfb712ed907d45cbb0b languageName: node linkType: hard "typed-array-byte-length@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-length@npm:1.0.0" + version: 1.0.1 + resolution: "typed-array-byte-length@npm:1.0.1" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: b03db16458322b263d87a702ff25388293f1356326c8a678d7515767ef563ef80e1e67ce648b821ec13178dd628eb2afdc19f97001ceae7a31acf674c849af94 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: f65e5ecd1cf76b1a2d0d6f631f3ea3cdb5e08da106c6703ffe687d583e49954d570cc80434816d3746e18be889ffe53c58bf3e538081ea4077c26a41055b216d languageName: node linkType: hard "typed-array-byte-offset@npm:^1.0.0": - version: 1.0.0 - resolution: "typed-array-byte-offset@npm:1.0.0" + version: 1.0.2 + resolution: "typed-array-byte-offset@npm:1.0.2" dependencies: - available-typed-arrays: ^1.0.5 - call-bind: ^1.0.2 + available-typed-arrays: ^1.0.7 + call-bind: ^1.0.7 for-each: ^0.3.3 - has-proto: ^1.0.1 - is-typed-array: ^1.1.10 - checksum: 04f6f02d0e9a948a95fbfe0d5a70b002191fae0b8fe0fe3130a9b2336f043daf7a3dda56a31333c35a067a97e13f539949ab261ca0f3692c41603a46a94e960b + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + checksum: c8645c8794a621a0adcc142e0e2c57b1823bbfa4d590ad2c76b266aa3823895cf7afb9a893bf6685e18454ab1b0241e1a8d885a2d1340948efa4b56add4b5f67 languageName: node linkType: hard "typed-array-length@npm:^1.0.4": - version: 1.0.4 - resolution: "typed-array-length@npm:1.0.4" + version: 1.0.5 + resolution: "typed-array-length@npm:1.0.5" dependencies: - call-bind: ^1.0.2 + call-bind: ^1.0.7 for-each: ^0.3.3 - is-typed-array: ^1.1.9 - checksum: 2228febc93c7feff142b8c96a58d4a0d7623ecde6c7a24b2b98eb3170e99f7c7eff8c114f9b283085cd59dcd2bd43aadf20e25bba4b034a53c5bb292f71f8956 + gopd: ^1.0.1 + has-proto: ^1.0.3 + is-typed-array: ^1.1.13 + possible-typed-array-names: ^1.0.0 + checksum: 82f5b666155cff1b345a1f3ab018d3f7667990f525435e4c8448cc094ab0f8ea283bb7cbde4d7bc82ea0b9b1072523bf31e86620d72615951d7fa9ccb4f42dfa languageName: node linkType: hard @@ -12225,7 +12234,7 @@ __metadata: languageName: node linkType: hard -"which-typed-array@npm:^1.1.13, which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.9": +"which-typed-array@npm:^1.1.14, which-typed-array@npm:^1.1.9": version: 1.1.14 resolution: "which-typed-array@npm:1.1.14" dependencies: From 9feda4613b77bbc9b281451e36b099e1e9b64837 Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Fri, 26 May 2023 20:28:12 +0200 Subject: [PATCH 2/7] Start using next.js api --- netlify.toml | 6 ++++- packages/core/src/lib/figma.ts | 2 +- packages/website/.env.example | 2 +- .../website/pages/api/{oauth.ts => auth.ts} | 4 ++-- packages/website/pages/api/login/[state].ts | 2 +- packages/website/pages/auth/success.tsx | 23 +++++++++++++++++++ packages/website/pages/authorized.tsx | 15 ------------ 7 files changed, 33 insertions(+), 21 deletions(-) rename packages/website/pages/api/{oauth.ts => auth.ts} (90%) create mode 100644 packages/website/pages/auth/success.tsx delete mode 100644 packages/website/pages/authorized.tsx diff --git a/netlify.toml b/netlify.toml index 22bb6544..31f19b84 100644 --- a/netlify.toml +++ b/netlify.toml @@ -1,6 +1,10 @@ [build] - publish = './packages/website/dist' command = 'yarn website:build' + # publish = './packages/website/dist' + publish = './packages/website/.next' + +[[plugins]] + package = "@netlify/plugin-nextjs" [[redirects]] from = "https://figma-export.netlify.app/*" diff --git a/packages/core/src/lib/figma.ts b/packages/core/src/lib/figma.ts index d3ca89c0..237cc311 100644 --- a/packages/core/src/lib/figma.ts +++ b/packages/core/src/lib/figma.ts @@ -23,7 +23,7 @@ export const getClient = (token: string): Figma.ClientInterface => { throw new Error('\'Access Token\' is missing. https://www.figma.com/developers/docs#authentication'); } - return Figma.Client({ accessToken: token }); + return Figma.Client({ personalAccessToken: token }); }; /** diff --git a/packages/website/.env.example b/packages/website/.env.example index 0dd7766f..ae25ad82 100644 --- a/packages/website/.env.example +++ b/packages/website/.env.example @@ -1,3 +1,3 @@ FIGMA_APP_CLIENT_SECRET= FIGMA_APP_CLIENT_ID= -FIGMA_APP_REDIRECT_URI=http://localhost:3000/api/oauth +FIGMA_APP_REDIRECT_URI=http://localhost:3000/api/auth diff --git a/packages/website/pages/api/oauth.ts b/packages/website/pages/api/auth.ts similarity index 90% rename from packages/website/pages/api/oauth.ts rename to packages/website/pages/api/auth.ts index b8f840e7..4cdaf2e4 100644 --- a/packages/website/pages/api/oauth.ts +++ b/packages/website/pages/api/auth.ts @@ -12,7 +12,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) const cookieState = req.cookies.state // delete `state` cookie - res.setHeader('Set-Cookie', `state=; Path=/api/oauth; Max-Age=0`) + res.setHeader('Set-Cookie', `state=; Path=/api/auth; Max-Age=0`) if (isValid(state, cookieState)) { const code = req.query.code @@ -27,7 +27,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) .then(r => r.json()) setItem(state, auth) - res.status(307).redirect('/authorized') + res.status(307).redirect('/auth/success') } else { res.status(443).json({ message: 'Access denied!' }) } diff --git a/packages/website/pages/api/login/[state].ts b/packages/website/pages/api/login/[state].ts index d4be16c3..c419e8d2 100644 --- a/packages/website/pages/api/login/[state].ts +++ b/packages/website/pages/api/login/[state].ts @@ -12,6 +12,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) return res.status(443).json({ message: 'Access denied!' }) } - res.setHeader('Set-Cookie', `state=${state}; Path=/api/oauth`) + res.setHeader('Set-Cookie', `state=${state}; Path=/api/auth`) res.redirect(307, `https://www.figma.com/oauth?client_id=${FIGMA_APP_CLIENT_ID}&redirect_uri=${FIGMA_APP_REDIRECT_URI}&scope=file_read&state=${state}&response_type=code`) } diff --git a/packages/website/pages/auth/success.tsx b/packages/website/pages/auth/success.tsx new file mode 100644 index 00000000..4bb8645b --- /dev/null +++ b/packages/website/pages/auth/success.tsx @@ -0,0 +1,23 @@ +import Link from 'next/link' +import GitHubLink from '../../src/GitHubLink' + +export default function HomePage() { + return ( + <> + <div className="container hero figma-gradient with-opacity-05"> + <section> + <h1 className="title"> + <Link href="/"><a className="figma-gradient text"> + @figma-export + </a></Link> + </h1> + <p> + <code className="figma-gradient with-opacity-10">authentication complete</code> + </p> + <p>You may now close this window</p> + </section> + </div> + <GitHubLink /> + </> + ); +} diff --git a/packages/website/pages/authorized.tsx b/packages/website/pages/authorized.tsx deleted file mode 100644 index f0c15922..00000000 --- a/packages/website/pages/authorized.tsx +++ /dev/null @@ -1,15 +0,0 @@ -import GitHubLink from '../src/GitHubLink' - -export default function HomePage() { - return ( - <> - <div className="container hero figma-gradient with-opacity-05"> - <section> - <h1 className="figma-gradient text title">@figma-export</h1> - <p>you are authorized</p> - </section> - </div> - <GitHubLink /> - </> - ); -} From bfe7ea39729447705543e0942aed78eca027f01c Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Fri, 26 May 2023 20:33:19 +0200 Subject: [PATCH 3/7] Disable website export --- package.json | 4 ++-- packages/website/package.json | 4 +++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index a3eaa6d1..bdfbae2f 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "coverage": "nyc yarn test --reporter=dot", "coverage:watch": "npx nodemon -e js,mjs,ts --exec yarn coverage", "website:start": "yarn build && yarn workspace @figma-export/website dev", - "website:build": "yarn build && yarn workspace @figma-export/website build", - "website:serve": "yarn dlx serve packages/website/dist/", + "website:build": "yarn build && yarn workspace @figma-export/website build-only", + "website:serve": "yarn workspace @figma-export/website start", "upgrade:major": "npx npm-check-updates -ws --root -u", "upgrade:minor": "yarn upgrade:major --target minor", "ls-engines": "yarn dlx ls-engines", diff --git a/packages/website/package.json b/packages/website/package.json index f87079af..f46b0a69 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -22,7 +22,9 @@ "next:build": "next build", "next:export": "next export -o dist/", "dev": "run-s export next:dev", - "build": "run-s clean export next:build" + "build-only": "run-s clean export next:build", + "build": "run-s clean export next:build next:export", + "start": "run-s next:start" }, "devDependencies": { "@figma-export/cli": "^5.0.1", From 72641f4cfbed8cce709da467aaf03c00dc01a0a0 Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Tue, 19 Sep 2023 09:43:09 +0200 Subject: [PATCH 4/7] Remove axios from the dependency list --- packages/cli/package.json | 1 - packages/cli/src/commands/login.ts | 48 ++++++++++++------- packages/cli/src/jsonFetch.ts | 62 +++++++++++++++++++++++++ packages/website/.env.example | 2 +- packages/website/lib/auth-storage.ts | 2 +- packages/website/pages/api/auth.ts | 11 ++++- packages/website/pages/auth/success.tsx | 62 +++++++++++++++++++++++-- yarn.lock | 1 - 8 files changed, 164 insertions(+), 25 deletions(-) create mode 100644 packages/cli/src/jsonFetch.ts diff --git a/packages/cli/package.json b/packages/cli/package.json index f073f2a6..1fd0ad0b 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -10,7 +10,6 @@ "dependencies": { "@figma-export/core": "^5.0.1", "@figma-export/types": "^5.0.1", - "axios": "^1.4.0", "ora": "~5.4.1", "sade": "~1.8.1" }, diff --git a/packages/cli/src/commands/login.ts b/packages/cli/src/commands/login.ts index efef7619..61aafc34 100644 --- a/packages/cli/src/commands/login.ts +++ b/packages/cli/src/commands/login.ts @@ -1,7 +1,9 @@ import crypto from 'crypto'; import { Ora } from 'ora'; import { Sade } from 'sade'; -import axios from 'axios'; + +import readline from 'readline'; +import { jsonFetch } from '../jsonFetch'; type Auth = { user_id: number @@ -10,16 +12,8 @@ type Auth = { expires_in: number } -function check(state: string): Promise<Auth> { - const result = axios.get<Auth>(`http://localhost:3000/api/check/${state}`).then((response) => { - return response.data; - }).catch(() => { - return new Promise<Auth>((resolve) => { - setTimeout(() => resolve(check(state)), 2000); - }); - }); - - return result; +function check(state: string): Promise<Auth | undefined> { + return jsonFetch<Auth>(`http://127.0.0.1:3000/api/check/${state}`).then((response) => response.data).catch(() => undefined); } export const addLogin = (prog: Sade, spinner: Ora) => prog @@ -32,12 +26,34 @@ export const addLogin = (prog: Sade, spinner: Ora) => prog spinner.info('Log in on https://figma.com'); console.log(` Login at: -http://localhost:3000/api/login/${state} +http://127.0.0.1:3000/api/login/${state} `); - spinner.start('waiting'); - check(state).then((response) => { - spinner.info(response.access_token); - spinner.succeed('Logged in on https://figma.com.'); + + const rl = readline.createInterface({ + input: process.stdin, + output: process.stdout, + }); + + rl.question('PIN: ', (pin) => { + check(`${state}:${pin}`).then((response) => { + if (response == null) { + spinner.fail('Failed to login!'); + return; + } + + spinner.info(JSON.stringify(response, undefined, 2)); + spinner.succeed('Logged in on https://figma.com.'); + }).catch((error) => { + spinner.fail(error); + }); + rl.close(); }); + + // spinner.start('waiting'); + + // check(state).then((response) => { + // spinner.info(JSON.stringify(response, undefined, 2)); + // spinner.succeed('Logged in on https://figma.com.'); + // }); }, ); diff --git a/packages/cli/src/jsonFetch.ts b/packages/cli/src/jsonFetch.ts new file mode 100644 index 00000000..813cbf70 --- /dev/null +++ b/packages/cli/src/jsonFetch.ts @@ -0,0 +1,62 @@ +import http from 'http'; +import https from 'https'; + +type Response<Data> = { + status?: number + statusText?: string + headers: http.IncomingHttpHeaders + body: string + data: Data +} + +export const jsonFetch = <Data>(url: string): Promise<Response<Data>> => { + return new Promise((resolve, reject) => { + // Parse the URL + const parsedUrl = new URL(url); + + // Determine the protocol module (http or https) + const protocol = parsedUrl.protocol === 'https:' ? https : http; + + // Prepare the request options + const options = { + hostname: parsedUrl.hostname, + port: parsedUrl.port, + path: parsedUrl.pathname + parsedUrl.search, + method: 'GET', + }; + + // Send the request + const req = protocol.request(options, (res) => { + let body = ''; + + // Accumulate the response data + res.on('data', (chunk) => { + body += chunk; + }); + + // Resolve the promise when the response ends + res.on('end', () => { + try { + const data = JSON.parse(body); + resolve({ + status: res.statusCode, + statusText: res.statusMessage, + headers: res.headers, + body, + data, + }); + } catch (error) { + reject(error); + } + }); + }); + + // Handle request errors + req.on('error', (error) => { + reject(error); + }); + + // End the request + req.end(); + }); +}; diff --git a/packages/website/.env.example b/packages/website/.env.example index ae25ad82..e697532e 100644 --- a/packages/website/.env.example +++ b/packages/website/.env.example @@ -1,3 +1,3 @@ FIGMA_APP_CLIENT_SECRET= FIGMA_APP_CLIENT_ID= -FIGMA_APP_REDIRECT_URI=http://localhost:3000/api/auth +FIGMA_APP_REDIRECT_URI=http://127.0.0.1:3000/api/auth diff --git a/packages/website/lib/auth-storage.ts b/packages/website/lib/auth-storage.ts index 992ac9cc..3e2f9af9 100644 --- a/packages/website/lib/auth-storage.ts +++ b/packages/website/lib/auth-storage.ts @@ -16,7 +16,7 @@ export function setItem(key: string, value: Auth): void { setTimeout(() => { removeItem(key) - }, 10 * 1000) + }, 30 * 1000) } export function getItem(key: string): Auth | undefined { diff --git a/packages/website/pages/api/auth.ts b/packages/website/pages/api/auth.ts index 4cdaf2e4..ca1dd6a7 100644 --- a/packages/website/pages/api/auth.ts +++ b/packages/website/pages/api/auth.ts @@ -7,6 +7,12 @@ function isValid(cookieState: unknown, queryState: unknown): cookieState is stri && cookieState === queryState } +function rnd(length: number) { + let min = Math.pow(10, length - 1) + let max = Math.pow(10, length) - 1 + return Math.floor(Math.random() * (max - min + 1)) + min +} + export default async function handler(req: NextApiRequest, res: NextApiResponse) { const state = req.query.state const cookieState = req.cookies.state @@ -26,8 +32,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse) ) .then(r => r.json()) - setItem(state, auth) - res.status(307).redirect('/auth/success') + const pin = rnd(6) + setItem(`${state}:${pin}`, auth) + res.status(307).redirect(`/auth/success#${pin}`) } else { res.status(443).json({ message: 'Access denied!' }) } diff --git a/packages/website/pages/auth/success.tsx b/packages/website/pages/auth/success.tsx index 4bb8645b..14da8901 100644 --- a/packages/website/pages/auth/success.tsx +++ b/packages/website/pages/auth/success.tsx @@ -1,7 +1,57 @@ import Link from 'next/link' import GitHubLink from '../../src/GitHubLink' +import { useEffect, useRef, useState } from 'react' export default function HomePage() { + const [pin, setPin] = useState<number>(NaN) + const [timer, setTimer] = useState<number>(30) + const interval = useRef<NodeJS.Timer>() + + useEffect(function handleTimer() { + if (interval.current == null && !isNaN(pin)) { + const endTimeString = window.sessionStorage.getItem(pin.toString()) + if (endTimeString == null) { + window.sessionStorage.setItem(pin.toString(), (Date.now() + 30 * 1000).toString()) + } else { + const endTime = parseInt(endTimeString ?? '0') + setTimer(Math.round((endTime - Date.now()) / 1000)) + } + + interval.current = setInterval(() => setTimer((t) => t - 1), 1000); + } + + () => clearInterval(interval.current) + }, [pin]) + + useEffect(function clearTimer() { + if (timer < 0) { + clearInterval(interval.current) + setTimer(0) + } + }, [timer]) + + + useEffect(function readPin() { + setPin(parseInt(window.location.hash.slice(1))) + }, []) + + if (isNaN(pin)) { + return ( + <> + <div className="container hero figma-gradient with-opacity-05"> + <section> + <h1 className="title"> + <Link href="/"><a className="figma-gradient text"> + @figma-export + </a></Link> + </h1> + </section> + </div> + <GitHubLink /> + </> + ) + } + return ( <> <div className="container hero figma-gradient with-opacity-05"> @@ -12,12 +62,18 @@ export default function HomePage() { </a></Link> </h1> <p> - <code className="figma-gradient with-opacity-10">authentication complete</code> + <code className="figma-gradient with-opacity-10" style={{ fontSize: '36px', textDecoration: timer > 0 ? undefined : 'line-through' }}>{pin}</code> </p> - <p>You may now close this window</p> + { + timer > 0 ? ( + <p>Copy this <code>pin</code> in your terminal window in {timer} seconds.</p> + ) : ( + <p>This <code>pin</code> expired.</p> + ) + } </section> </div> <GitHubLink /> </> - ); + ) } diff --git a/yarn.lock b/yarn.lock index e5c01e60..56913221 100644 --- a/yarn.lock +++ b/yarn.lock @@ -320,7 +320,6 @@ __metadata: dependencies: "@figma-export/core": ^5.0.1 "@figma-export/types": ^5.0.1 - axios: ^1.4.0 ora: ~5.4.1 sade: ~1.8.1 bin: From 6b9e08841e4d29d5a6782a979376bea36a10b1d0 Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Mon, 26 Feb 2024 22:24:33 +0100 Subject: [PATCH 5/7] chore: update with latest changes --- package.json | 6 +++--- packages/website/next.config.js | 1 - packages/website/package.json | 5 ++--- packages/website/pages/auth/success.tsx | 3 ++- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/package.json b/package.json index bdfbae2f..35c7fbf6 100644 --- a/package.json +++ b/package.json @@ -24,9 +24,9 @@ "test:watch": "yarn test --watch --reporter=dot", "coverage": "nyc yarn test --reporter=dot", "coverage:watch": "npx nodemon -e js,mjs,ts --exec yarn coverage", - "website:start": "yarn build && yarn workspace @figma-export/website dev", - "website:build": "yarn build && yarn workspace @figma-export/website build-only", - "website:serve": "yarn workspace @figma-export/website start", + "website:dev": "yarn build && yarn workspace @figma-export/website dev", + "website:build": "yarn build && yarn workspace @figma-export/website build", + "website:start": "yarn workspace @figma-export/website start", "upgrade:major": "npx npm-check-updates -ws --root -u", "upgrade:minor": "yarn upgrade:major --target minor", "ls-engines": "yarn dlx ls-engines", diff --git a/packages/website/next.config.js b/packages/website/next.config.js index 0587eb99..f2894d0d 100644 --- a/packages/website/next.config.js +++ b/packages/website/next.config.js @@ -8,7 +8,6 @@ const nextConfig = { // https://nextjs.org/docs/api-reference/next.config.js/react-strict-mode reactStrictMode: true, - output: 'export', distDir: 'dist' } diff --git a/packages/website/package.json b/packages/website/package.json index f46b0a69..19a38153 100644 --- a/packages/website/package.json +++ b/packages/website/package.json @@ -20,10 +20,9 @@ "next:lint": "next lint", "next:dev": "next dev", "next:build": "next build", - "next:export": "next export -o dist/", + "next:start": "next start", "dev": "run-s export next:dev", - "build-only": "run-s clean export next:build", - "build": "run-s clean export next:build next:export", + "build": "run-s clean export next:build", "start": "run-s next:start" }, "devDependencies": { diff --git a/packages/website/pages/auth/success.tsx b/packages/website/pages/auth/success.tsx index 14da8901..8ef04516 100644 --- a/packages/website/pages/auth/success.tsx +++ b/packages/website/pages/auth/success.tsx @@ -5,7 +5,7 @@ import { useEffect, useRef, useState } from 'react' export default function HomePage() { const [pin, setPin] = useState<number>(NaN) const [timer, setTimer] = useState<number>(30) - const interval = useRef<NodeJS.Timer>() + const interval = useRef<number>() useEffect(function handleTimer() { if (interval.current == null && !isNaN(pin)) { @@ -17,6 +17,7 @@ export default function HomePage() { setTimer(Math.round((endTime - Date.now()) / 1000)) } + /** @ts-expect-error Interval is a number */ interval.current = setInterval(() => setTimer((t) => t - 1), 1000); } From 1d71351cd460329fc90a0ae9f40c21a3abc6ff24 Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Mon, 26 Feb 2024 22:33:51 +0100 Subject: [PATCH 6/7] chore: use native fetch (Node >= 18) --- packages/cli/src/commands/login.ts | 5 ++- packages/cli/src/jsonFetch.ts | 62 ------------------------------ 2 files changed, 3 insertions(+), 64 deletions(-) delete mode 100644 packages/cli/src/jsonFetch.ts diff --git a/packages/cli/src/commands/login.ts b/packages/cli/src/commands/login.ts index 61aafc34..b4df7b84 100644 --- a/packages/cli/src/commands/login.ts +++ b/packages/cli/src/commands/login.ts @@ -3,7 +3,6 @@ import { Ora } from 'ora'; import { Sade } from 'sade'; import readline from 'readline'; -import { jsonFetch } from '../jsonFetch'; type Auth = { user_id: number @@ -13,7 +12,9 @@ type Auth = { } function check(state: string): Promise<Auth | undefined> { - return jsonFetch<Auth>(`http://127.0.0.1:3000/api/check/${state}`).then((response) => response.data).catch(() => undefined); + return fetch(`http://127.0.0.1:3000/api/check/${state}`) + .then((response) => response.json() as Promise<Auth>) + .catch(() => undefined); } export const addLogin = (prog: Sade, spinner: Ora) => prog diff --git a/packages/cli/src/jsonFetch.ts b/packages/cli/src/jsonFetch.ts deleted file mode 100644 index 813cbf70..00000000 --- a/packages/cli/src/jsonFetch.ts +++ /dev/null @@ -1,62 +0,0 @@ -import http from 'http'; -import https from 'https'; - -type Response<Data> = { - status?: number - statusText?: string - headers: http.IncomingHttpHeaders - body: string - data: Data -} - -export const jsonFetch = <Data>(url: string): Promise<Response<Data>> => { - return new Promise((resolve, reject) => { - // Parse the URL - const parsedUrl = new URL(url); - - // Determine the protocol module (http or https) - const protocol = parsedUrl.protocol === 'https:' ? https : http; - - // Prepare the request options - const options = { - hostname: parsedUrl.hostname, - port: parsedUrl.port, - path: parsedUrl.pathname + parsedUrl.search, - method: 'GET', - }; - - // Send the request - const req = protocol.request(options, (res) => { - let body = ''; - - // Accumulate the response data - res.on('data', (chunk) => { - body += chunk; - }); - - // Resolve the promise when the response ends - res.on('end', () => { - try { - const data = JSON.parse(body); - resolve({ - status: res.statusCode, - statusText: res.statusMessage, - headers: res.headers, - body, - data, - }); - } catch (error) { - reject(error); - } - }); - }); - - // Handle request errors - req.on('error', (error) => { - reject(error); - }); - - // End the request - req.end(); - }); -}; From 691c8c1fa520699d4d15a4f1bafa12b5bfeb3227 Mon Sep 17 00:00:00 2001 From: Marco Montalbano <marcomontalbano.work@gmail.com> Date: Mon, 26 Feb 2024 22:36:36 +0100 Subject: [PATCH 7/7] fix: remove 'distDir' from next config file --- packages/website/next.config.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/packages/website/next.config.js b/packages/website/next.config.js index f2894d0d..d6e4937d 100644 --- a/packages/website/next.config.js +++ b/packages/website/next.config.js @@ -7,8 +7,7 @@ /** @type {import('next').NextConfig} */ const nextConfig = { // https://nextjs.org/docs/api-reference/next.config.js/react-strict-mode - reactStrictMode: true, - distDir: 'dist' + reactStrictMode: true } module.exports = nextConfig;