diff --git a/package.json b/package.json index 7d4cef8..6aa618a 100644 --- a/package.json +++ b/package.json @@ -16,5 +16,8 @@ "packages/lambda-layer/nodejs", "packages/*" ] + }, + "devDependencies": { + "prettier": "^3.3.3" } } diff --git a/packages/api/serverless.yml b/packages/api/serverless.yml index 10f8c97..f45b670 100644 --- a/packages/api/serverless.yml +++ b/packages/api/serverless.yml @@ -43,6 +43,7 @@ provider: NODE_ENV: ${sls:stage} TABLE_NAME: ${self:service}-${sls:stage} CUSTOM_DOMAIN: ${param:CUSTOM_DOMAIN} + EDGE_ENDPOINT: !GetAtt HttpApi.ApiEndpoint # S3_BUCKET: ${self:service}-${sls:stage} # CLOUDFRONT_DOMAIN: !GetAtt UserMediaDistribution.DomainName # USER_POOL_ID: diff --git a/packages/api/src/functions/collector/handler.js b/packages/api/src/functions/collector/handler.js index f179d53..c1544f1 100644 --- a/packages/api/src/functions/collector/handler.js +++ b/packages/api/src/functions/collector/handler.js @@ -7,46 +7,58 @@ export const app = async ({ body }) => { if (span.type === "log") { // save log span - await put({ - ...span, - pk: `transaction#${span.transactionId || span.transaction_id}`, - sk: `log#${span.started}#${span.id}`, - type: "log", - }); + await put( + { + ...span, + pk: `transaction#${span.transactionId || span.transaction_id}`, + sk: `log#${span.started}#${span.id}`, + type: "log", + }, + true, + ); continue; } // save transaction span - await put({ - ...span, - pk: `transaction#${span.transactionId || span.transaction_id}`, - sk: `span#${span.started || span.sending_time}#${span.id}`, - type: "span", - spanType: span.type, - }); + await put( + { + ...span, + pk: `transaction#${span.transactionId || span.transaction_id}`, + sk: `span#${span.started || span.sending_time}#${span.id}`, + type: "span", + spanType: span.type, + }, + true, + ); if (span.type === "function" && span.ended) { // save function invocation details - await put({ - ...span, - pk: `function#${span.name}`, - sk: `invocation#${span.started}#${span.id}`, - type: "invocation", - }); + await put( + { + ...span, + pk: `function#${span.name}`, + sk: `invocation#${span.started}#${span.id}`, + type: "invocation", + }, + true, + ); // save function meta data - await put({ - pk: `function#${span.name}`, - sk: `function`, - type: "function", - lastInvocation: span.started, - runtime: span.runtime, - account: span.account, - region: span.region, - arn: span.invokedArn, - memoryAllocation: span.memoryAllocation, - timeout: span.maxFinishTime - span.started, - }); + await put( + { + pk: `function#${span.name}`, + sk: `function`, + type: "function", + lastInvocation: span.started, + runtime: span.runtime, + account: span.account, + region: span.region, + arn: span.invokedArn, + memoryAllocation: span.memoryAllocation, + timeout: span.maxFinishTime - span.started, + }, + true, + ); } } }; diff --git a/packages/api/src/functions/media/upload/function.yml b/packages/api/src/functions/media/upload/function.yml deleted file mode 100644 index 6433b5c..0000000 --- a/packages/api/src/functions/media/upload/function.yml +++ /dev/null @@ -1,8 +0,0 @@ -media-upload: - handler: src/functions/media/upload/handler.handler - events: - - httpApi: - path: /media/upload - method: get - authorizer: - name: WebAuthorizer diff --git a/packages/api/src/functions/media/upload/handler.js b/packages/api/src/functions/media/upload/handler.js deleted file mode 100644 index deaad15..0000000 --- a/packages/api/src/functions/media/upload/handler.js +++ /dev/null @@ -1,38 +0,0 @@ -import { middleware, auth } from "@includable/serverless-middleware"; -import { v4 as uuid } from "uuid"; - -import { getSignedUrl, sanitizeFilename } from "../../../lib/media"; - -const dependencies = () => ({ - getSignedUrl, - uuid, -}); - -const defaultParams = { - type: "avatar", - filename: "image.jpg", - contentType: "image/jpeg", -}; - -export const app = async ( - { query = {} }, - { currentUser, getSignedUrl, uuid }, -) => { - const { filename, type, contentType } = { ...defaultParams, ...query }; - const safeFilename = sanitizeFilename(filename); - const safeType = sanitizeFilename(type); - const key = `${safeType}/${currentUser.id}/${uuid()}/${safeFilename}`; - - const uploadUrl = await getSignedUrl(key, contentType, { - "x-upload-user": currentUser.id, - "x-upload-category": safeType, - "x-upload-filename": filename, - }); - - return { - uploadUrl, - publicUrl: `https://${process.env.CLOUDFRONT_DOMAIN}/${key}`, - }; -}; - -export const handler = middleware(app, [auth]).register(dependencies); diff --git a/packages/api/src/functions/media/upload/test.js b/packages/api/src/functions/media/upload/test.js deleted file mode 100644 index a914540..0000000 --- a/packages/api/src/functions/media/upload/test.js +++ /dev/null @@ -1,38 +0,0 @@ -const { app } = require("./handler"); - -describe("media-upload", () => { - it("can generate signed URL", async () => { - const event = { - query: { - type: "custom-image", - }, - }; - const getSignedUrl = jest.fn().mockReturnValue("https://example.com/"); - const dependencies = { - getSignedUrl, - uuid: jest.fn().mockReturnValue("133a1a65-dc63-48e5-9afd-40d17b228874"), - currentUser: { - id: "test123", - }, - }; - - process.env.CLOUDFRONT_DOMAIN = "test.com"; - const result = await app(event, dependencies); - - expect(result).toEqual({ - publicUrl: - "https://test.com/custom-image/test123/133a1a65-dc63-48e5-9afd-40d17b228874/image.jpg", - uploadUrl: "https://example.com/", - }); - expect(getSignedUrl).toBeCalledTimes(1); - expect(getSignedUrl).toBeCalledWith( - "custom-image/test123/133a1a65-dc63-48e5-9afd-40d17b228874/image.jpg", - "image/jpeg", - { - "x-upload-user": "test123", - "x-upload-category": "custom-image", - "x-upload-filename": "image.jpg", - } - ); - }); -}); diff --git a/packages/api/src/functions/preferences/get/function.yml b/packages/api/src/functions/preferences/get/function.yml deleted file mode 100644 index 7cb513e..0000000 --- a/packages/api/src/functions/preferences/get/function.yml +++ /dev/null @@ -1,8 +0,0 @@ -preferences-get: - handler: src/functions/preferences/get/handler.handler - events: - - httpApi: - path: /preferences - method: get - authorizer: - name: WebAuthorizer diff --git a/packages/api/src/functions/preferences/get/handler.js b/packages/api/src/functions/preferences/get/handler.js deleted file mode 100644 index 5d649ee..0000000 --- a/packages/api/src/functions/preferences/get/handler.js +++ /dev/null @@ -1,15 +0,0 @@ -import { middleware, auth } from "@includable/serverless-middleware"; - -import User from "../../../lib/entities/User"; - -const dependencies = () => ({ - User, -}); - -export const app = async (event, { User, currentUser }) => { - let { Item: result } = await User.get({ id: currentUser.id }); - - return (result && result.preferences) || {}; -}; - -export const handler = middleware(app, [auth]).register(dependencies); diff --git a/packages/api/src/functions/preferences/get/test.js b/packages/api/src/functions/preferences/get/test.js deleted file mode 100644 index 338ae82..0000000 --- a/packages/api/src/functions/preferences/get/test.js +++ /dev/null @@ -1,65 +0,0 @@ -const { app } = require("./handler"); - -describe("preferences-get", () => { - it("can get preferences if user exists and has preferences", async () => { - const preferences = { - myPreference: true, - somethingElse: [123, "test", false, null], - }; - const getHandler = jest.fn().mockResolvedValue({ Item: { preferences } }); - const dependencies = { - User: { - get: getHandler, - }, - currentUser: { - id: "test123", - }, - }; - - const result = await app({}, dependencies); - - expect(result).toEqual(preferences); - expect(getHandler).toBeCalledTimes(1); - expect(getHandler).toBeCalledWith({ - id: "test123", - }); - }); - it("can get preferences if user exists and has no preferences", async () => { - const getHandler = jest.fn().mockResolvedValue({ Item: {} }); - const dependencies = { - User: { - get: getHandler, - }, - currentUser: { - id: "test123", - }, - }; - - const result = await app({}, dependencies); - - expect(result).toEqual({}); - expect(getHandler).toBeCalledTimes(1); - expect(getHandler).toBeCalledWith({ - id: "test123", - }); - }); - it("can get preferences if user does not exist", async () => { - const getHandler = jest.fn().mockResolvedValue({ Item: null }); - const dependencies = { - User: { - get: getHandler, - }, - currentUser: { - id: "test123", - }, - }; - - const result = await app({}, dependencies); - - expect(result).toEqual({}); - expect(getHandler).toBeCalledTimes(1); - expect(getHandler).toBeCalledWith({ - id: "test123", - }); - }); -}); diff --git a/packages/api/src/functions/preferences/update/function.yml b/packages/api/src/functions/preferences/update/function.yml deleted file mode 100644 index cd873cb..0000000 --- a/packages/api/src/functions/preferences/update/function.yml +++ /dev/null @@ -1,8 +0,0 @@ -preferences-update: - handler: src/functions/preferences/update/handler.handler - events: - - httpApi: - path: /preferences - method: post - authorizer: - name: WebAuthorizer diff --git a/packages/api/src/functions/preferences/update/handler.js b/packages/api/src/functions/preferences/update/handler.js deleted file mode 100644 index 77b4abd..0000000 --- a/packages/api/src/functions/preferences/update/handler.js +++ /dev/null @@ -1,46 +0,0 @@ -import Joi from "joi"; -import { middleware, auth } from "@includable/serverless-middleware"; - -import User from "../../../lib/entities/User"; - -const dependencies = () => ({ - User, -}); - -const schema = Joi.object().unknown(true); - -export const app = async ({ body }, { User, currentUser }) => { - // Validate input - const data = await schema.validateAsync(body); - - // Update db entry - let res; - try { - // Note the $set: ... in here! - res = await User.update( - { - id: currentUser.id, - preferences: { $set: data }, - }, - { - returnValues: "all_new", - } - ); - } catch (e) { - // Means the user doesn't yet exist - res = await User.update( - { - id: currentUser.id, - preferences: { ...data }, - }, - { - returnValues: "all_new", - } - ); - } - - // Output updated version - return res.Attributes.preferences; -}; - -export const handler = middleware(app, [auth]).register(dependencies); diff --git a/packages/api/src/functions/preferences/update/test.js b/packages/api/src/functions/preferences/update/test.js deleted file mode 100644 index 9e89bb1..0000000 --- a/packages/api/src/functions/preferences/update/test.js +++ /dev/null @@ -1,103 +0,0 @@ -const { app } = require("./handler"); - -describe("preferences-update", () => { - it("can update if user exists", async () => { - const event = { - body: { - myPreference: true, - somethingElse: [123, "test", false, null], - }, - }; - const updateHandler = jest - .fn() - .mockResolvedValue({ Attributes: { preferences: event.body } }); - const dependencies = { - User: { - update: updateHandler, - }, - currentUser: { - id: "test123", - }, - }; - - const result = await app(event, dependencies); - - expect(result).toEqual(event.body); - expect(updateHandler).toBeCalledTimes(1); - expect(updateHandler).toBeCalledWith( - { - id: "test123", - preferences: { $set: event.body }, - }, - { - returnValues: "all_new", - } - ); - }); - it("can update if user does not exist", async () => { - const event = { - body: { - myPreference: true, - somethingElse: [123, "test", false, null], - }, - }; - const updateHandler = jest - .fn() - .mockRejectedValueOnce(new Error("Item not found.")) - .mockResolvedValue({ Attributes: { preferences: event.body } }); - const dependencies = { - User: { - update: updateHandler, - }, - currentUser: { - id: "test123", - }, - }; - - const result = await app(event, dependencies); - - expect(result).toEqual(event.body); - expect(updateHandler).toBeCalledTimes(2); - expect(updateHandler).toBeCalledWith( - { - id: "test123", - preferences: { $set: event.body }, - }, - { - returnValues: "all_new", - } - ); - expect(updateHandler).toBeCalledWith( - { - id: "test123", - preferences: event.body, - }, - { - returnValues: "all_new", - } - ); - }); - it("rejects invalid body", async () => { - const event = { - body: "lalala", - }; - const dependencies = { - User: { - update: jest.fn(), - }, - currentUser: { - id: "test123", - }, - }; - - expect.assertions(2); - - try { - await app(event, dependencies); - } catch (e) { - expect(e.message).toEqual('"value" must be of type object'); - } - - expect(dependencies.User.update).not.toBeCalled(); - }); -}); diff --git a/packages/api/src/functions/users/get/function.yml b/packages/api/src/functions/users/get/function.yml deleted file mode 100644 index a493e60..0000000 --- a/packages/api/src/functions/users/get/function.yml +++ /dev/null @@ -1,13 +0,0 @@ -users-get: - handler: src/functions/users/get/handler.handler - events: - - httpApi: - path: /users/{userId} - method: get - authorizer: - name: WebAuthorizer - - httpApi: - path: /me - method: get - authorizer: - name: WebAuthorizer diff --git a/packages/api/src/functions/users/get/handler.js b/packages/api/src/functions/users/get/handler.js deleted file mode 100644 index b833f4c..0000000 --- a/packages/api/src/functions/users/get/handler.js +++ /dev/null @@ -1,33 +0,0 @@ -import { middleware, auth } from "@includable/serverless-middleware"; - -import User from "../../../lib/entities/User"; -import { createUser } from "../../../lib/userManagement"; - -const dependencies = () => ({ - User, - createUser, -}); - -export const app = async ({ userId }, { User, currentUser }) => { - let { Item: result } = await User.get({ id: userId || currentUser.id }); - if (!result && (!userId || userId === currentUser.id)) { - // Create profile for user if it doesn't exist - // using data from Cognito - result = await createUser(currentUser.id); - } - - if (!result) { - throw new Error("User not found."); - } - - const publicWhitelist = ["id", "displayName", "name", "avatar", "bio"]; - if (result.id === currentUser.id) { - return result; - } - - return Object.fromEntries( - Object.entries(result).filter(([key]) => publicWhitelist.includes(key)) - ); -}; - -export const handler = middleware(app, [auth]).register(dependencies); diff --git a/packages/api/src/functions/users/update/function.yml b/packages/api/src/functions/users/update/function.yml deleted file mode 100644 index 2f2f519..0000000 --- a/packages/api/src/functions/users/update/function.yml +++ /dev/null @@ -1,13 +0,0 @@ -users-update: - handler: src/functions/users/update/handler.handler - events: - - httpApi: - path: /users/{userId} - method: post - authorizer: - name: WebAuthorizer - - httpApi: - path: /me - method: post - authorizer: - name: WebAuthorizer diff --git a/packages/api/src/functions/users/update/handler.js b/packages/api/src/functions/users/update/handler.js deleted file mode 100644 index 68dae77..0000000 --- a/packages/api/src/functions/users/update/handler.js +++ /dev/null @@ -1,62 +0,0 @@ -import { middleware, auth } from "@includable/serverless-middleware"; -import Joi from "joi"; - -import User from "../../../lib/entities/User"; -import { createUser, updateUserAttributes } from "../../../lib/userManagement"; - -const dependencies = () => ({ - User, - createUser, -}); - -const schema = Joi.object({ - displayName: Joi.string().min(3).max(60), - name: Joi.string().min(3).max(120), - email: Joi.string().email(), - bio: Joi.string().max(500), - avatar: Joi.string().uri({ scheme: ["https"] }), -}); - -export const app = async ({ userId, body }, { User, currentUser }) => { - const id = userId || currentUser.id; - if (id !== currentUser.id) { - throw new Error("No permission to edit other users."); - } - - // Validate input - const input = await schema.validateAsync(body); - - // Update cognito - const cognitoAllowedAttributesMap = { - email: "email", - name: "name", - displayName: "nickname", - avatar: "picture", - }; - const cognitoAttributes = {}; - Object.entries(cognitoAllowedAttributesMap).forEach( - ([attribute, cognitoName]) => { - if ( - attribute in input && - input[attribute] && - input[attribute] !== currentUser[cognitoName] - ) { - cognitoAttributes[cognitoName] = input[attribute]; - } - } - ); - if (Object.keys(cognitoAttributes).length) { - await updateUserAttributes(id, cognitoAttributes); - } - - // Update db entry - const { Attributes } = await User.update( - { ...input, id }, - { returnValues: "all_new" } - ); - - // Output updated version - return Attributes; -}; - -export const handler = middleware(app, [auth]).register(dependencies); diff --git a/packages/api/src/infrastructure/storage/bucket.yml b/packages/api/src/infrastructure/storage/bucket.yml deleted file mode 100644 index 3966c2c..0000000 --- a/packages/api/src/infrastructure/storage/bucket.yml +++ /dev/null @@ -1,51 +0,0 @@ -Resources: - UserMediaBucket: - Type: AWS::S3::Bucket - DeletionPolicy: Retain - Properties: - BucketName: ${self:service}-${sls:stage} - AccelerateConfiguration: - AccelerationStatus: Enabled - WebsiteConfiguration: - IndexDocument: default.png - ErrorDocument: default.png - OwnershipControls: - Rules: - - ObjectOwnership: BucketOwnerPreferred - CorsConfiguration: - CorsRules: - - AllowedOrigins: - - "*" - AllowedHeaders: - - "*" - AllowedMethods: - - GET - - PUT - - POST - - DELETE - - HEAD - MaxAge: 3000 - UserMediaDistribution: - Type: AWS::CloudFront::Distribution - Properties: - DistributionConfig: - DefaultCacheBehavior: - TargetOriginId: UserMediaBucket - ViewerProtocolPolicy: allow-all - Compress: true - ForwardedValues: - QueryString: true - Cookies: - Forward: none - AllowedMethods: - - GET - - HEAD - - OPTIONS - Enabled: true - Origins: - - Id: UserMediaBucket - DomainName: ${self:service}-${sls:stage}.s3-website-${self:provider.region}.amazonaws.com - CustomOriginConfig: - HTTPPort: 80 - HTTPSPort: 443 - OriginProtocolPolicy: http-only diff --git a/packages/api/src/lib/events.js b/packages/api/src/lib/events.js deleted file mode 100644 index 2aa5efc..0000000 --- a/packages/api/src/lib/events.js +++ /dev/null @@ -1,12 +0,0 @@ -import { EventBridge } from "@aws-sdk/client-eventbridge"; - -const bridge = new EventBridge(); - -const createEventEntry = (type, data = {}) => ({ - Source: process.env.SERVICE, - DetailType: type, - Detail: JSON.stringify({ data }), -}); - -export const sendEvent = async (type, data = {}) => - bridge.putEvents({ Entries: [createEventEntry(type, data)] }); diff --git a/packages/api/src/lib/media.js b/packages/api/src/lib/media.js deleted file mode 100644 index 587fad2..0000000 --- a/packages/api/src/lib/media.js +++ /dev/null @@ -1,30 +0,0 @@ -import { getSignedUrl as s3SignedUrl } from "@aws-sdk/s3-request-presigner"; -import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; -const client = new S3Client({ useAccelerateEndpoint: true }); - -const illegalRe = /[\/?<>\\:*|"]/g; -const controlRe = /[\x00-\x1f\x80-\x9f]/g; -const reservedRe = /^\.+$/; -const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i; -const windowsTrailingRe = /[. ]+$/; - -export const sanitizeFilename = (input) => - input - .replace(illegalRe, "-") - .replace(controlRe, "-") - .replace(reservedRe, "-") - .replace(windowsReservedRe, "-") - .replace(windowsTrailingRe, "-") - .replace(/ /g, "-"); - -export async function getSignedUrl(key, contentType, metadata = {}) { - const command = new PutObjectCommand({ - Key: key, - Bucket: process.env.S3_BUCKET, - ContentType: contentType, - ACL: "public-read", - Metadata: metadata, - }); - - return s3SignedUrl(client, command, { expiresIn: 3600 }); -} diff --git a/packages/api/src/lib/userManagement.js b/packages/api/src/lib/userManagement.js deleted file mode 100644 index f98cbd8..0000000 --- a/packages/api/src/lib/userManagement.js +++ /dev/null @@ -1,43 +0,0 @@ -import { CognitoIdentityProvider } from "@aws-sdk/client-cognito-identity-provider"; -import User from "./entities/User"; - -const cognito = new CognitoIdentityProvider(); -const { USER_POOL_ID: UserPoolId } = process.env; - -export const createUser = async (userId) => { - const user = await cognito.adminGetUser({ - UserPoolId, - Username: userId, - }); - if (!user.Enabled) { - throw new Error("Unknown user."); - } - const name = user.UserAttributes?.find(({ Name }) => Name === "name"); - const { Attributes } = await User.update( - { - id: user.Username, - created: new Date(user.UserCreateDate || 0).toISOString(), - modified: new Date(user.UserLastModifiedDate || 0).toISOString(), - email: user.UserAttributes?.find(({ Name }) => Name === "email")?.Value, - name: name && name.Value, - }, - { - returnValues: "ALL_NEW", - }, - ); - - return Attributes; -}; - -export const updateUserAttributes = async (userId, attributes) => - cognito.adminUpdateUserAttributes({ - UserPoolId, - Username: userId, - UserAttributes: [ - { - Name: "email_verified", - Value: "true", - }, - ...Object.entries(attributes).map(([Name, Value]) => ({ Name, Value })), - ], - }); diff --git a/packages/dashboard/.gitignore b/packages/dashboard/.gitignore new file mode 100644 index 0000000..a547bf3 --- /dev/null +++ b/packages/dashboard/.gitignore @@ -0,0 +1,24 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +pnpm-debug.log* +lerna-debug.log* + +node_modules +dist +dist-ssr +*.local + +# Editor directories and files +.vscode/* +!.vscode/extensions.json +.idea +.DS_Store +*.suo +*.ntvs* +*.njsproj +*.sln +*.sw? diff --git a/packages/dashboard/README.md b/packages/dashboard/README.md new file mode 100644 index 0000000..f768e33 --- /dev/null +++ b/packages/dashboard/README.md @@ -0,0 +1,8 @@ +# React + Vite + +This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. + +Currently, two official plugins are available: + +- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh +- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh diff --git a/packages/dashboard/eslint.config.js b/packages/dashboard/eslint.config.js new file mode 100644 index 0000000..238d2e4 --- /dev/null +++ b/packages/dashboard/eslint.config.js @@ -0,0 +1,38 @@ +import js from '@eslint/js' +import globals from 'globals' +import react from 'eslint-plugin-react' +import reactHooks from 'eslint-plugin-react-hooks' +import reactRefresh from 'eslint-plugin-react-refresh' + +export default [ + { ignores: ['dist'] }, + { + files: ['**/*.{js,jsx}'], + languageOptions: { + ecmaVersion: 2020, + globals: globals.browser, + parserOptions: { + ecmaVersion: 'latest', + ecmaFeatures: { jsx: true }, + sourceType: 'module', + }, + }, + settings: { react: { version: '18.3' } }, + plugins: { + react, + 'react-hooks': reactHooks, + 'react-refresh': reactRefresh, + }, + rules: { + ...js.configs.recommended.rules, + ...react.configs.recommended.rules, + ...react.configs['jsx-runtime'].rules, + ...reactHooks.configs.recommended.rules, + 'react/jsx-no-target-blank': 'off', + 'react-refresh/only-export-components': [ + 'warn', + { allowConstantExport: true }, + ], + }, + }, +] diff --git a/packages/dashboard/index.html b/packages/dashboard/index.html new file mode 100644 index 0000000..0c589ec --- /dev/null +++ b/packages/dashboard/index.html @@ -0,0 +1,13 @@ + + + + + + + Vite + React + + +
+ + + diff --git a/packages/dashboard/package.json b/packages/dashboard/package.json new file mode 100644 index 0000000..f827a1e --- /dev/null +++ b/packages/dashboard/package.json @@ -0,0 +1,22 @@ +{ + "name": "@trace-stack/dashboard", + "private": true, + "version": "0.0.0", + "type": "module", + "scripts": { + "start": "vite", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "react": "^18.3.1", + "react-dom": "^18.3.1" + }, + "devDependencies": { + "@types/react": "^18.3.3", + "@types/react-dom": "^18.3.0", + "@vitejs/plugin-react": "^4.3.1", + "globals": "^15.9.0", + "vite": "^5.4.1" + } +} diff --git a/packages/dashboard/public/vite.svg b/packages/dashboard/public/vite.svg new file mode 100644 index 0000000..e7b8dfb --- /dev/null +++ b/packages/dashboard/public/vite.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/dashboard/src/App.css b/packages/dashboard/src/App.css new file mode 100644 index 0000000..b9d355d --- /dev/null +++ b/packages/dashboard/src/App.css @@ -0,0 +1,42 @@ +#root { + max-width: 1280px; + margin: 0 auto; + padding: 2rem; + text-align: center; +} + +.logo { + height: 6em; + padding: 1.5em; + will-change: filter; + transition: filter 300ms; +} +.logo:hover { + filter: drop-shadow(0 0 2em #646cffaa); +} +.logo.react:hover { + filter: drop-shadow(0 0 2em #61dafbaa); +} + +@keyframes logo-spin { + from { + transform: rotate(0deg); + } + to { + transform: rotate(360deg); + } +} + +@media (prefers-reduced-motion: no-preference) { + a:nth-of-type(2) .logo { + animation: logo-spin infinite 20s linear; + } +} + +.card { + padding: 2em; +} + +.read-the-docs { + color: #888; +} diff --git a/packages/dashboard/src/App.jsx b/packages/dashboard/src/App.jsx new file mode 100644 index 0000000..b8b8473 --- /dev/null +++ b/packages/dashboard/src/App.jsx @@ -0,0 +1,35 @@ +import { useState } from 'react' +import reactLogo from './assets/react.svg' +import viteLogo from '/vite.svg' +import './App.css' + +function App() { + const [count, setCount] = useState(0) + + return ( + <> +
+ + Vite logo + + + React logo + +
+

Vite + React

+
+ +

+ Edit src/App.jsx and save to test HMR +

+
+

+ Click on the Vite and React logos to learn more +

+ + ) +} + +export default App diff --git a/packages/dashboard/src/assets/react.svg b/packages/dashboard/src/assets/react.svg new file mode 100644 index 0000000..6c87de9 --- /dev/null +++ b/packages/dashboard/src/assets/react.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/packages/dashboard/src/index.css b/packages/dashboard/src/index.css new file mode 100644 index 0000000..6119ad9 --- /dev/null +++ b/packages/dashboard/src/index.css @@ -0,0 +1,68 @@ +:root { + font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif; + line-height: 1.5; + font-weight: 400; + + color-scheme: light dark; + color: rgba(255, 255, 255, 0.87); + background-color: #242424; + + font-synthesis: none; + text-rendering: optimizeLegibility; + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; +} + +a { + font-weight: 500; + color: #646cff; + text-decoration: inherit; +} +a:hover { + color: #535bf2; +} + +body { + margin: 0; + display: flex; + place-items: center; + min-width: 320px; + min-height: 100vh; +} + +h1 { + font-size: 3.2em; + line-height: 1.1; +} + +button { + border-radius: 8px; + border: 1px solid transparent; + padding: 0.6em 1.2em; + font-size: 1em; + font-weight: 500; + font-family: inherit; + background-color: #1a1a1a; + cursor: pointer; + transition: border-color 0.25s; +} +button:hover { + border-color: #646cff; +} +button:focus, +button:focus-visible { + outline: 4px auto -webkit-focus-ring-color; +} + +@media (prefers-color-scheme: light) { + :root { + color: #213547; + background-color: #ffffff; + } + a:hover { + color: #747bff; + } + button { + background-color: #f9f9f9; + } +} diff --git a/packages/dashboard/src/main.jsx b/packages/dashboard/src/main.jsx new file mode 100644 index 0000000..89f91e5 --- /dev/null +++ b/packages/dashboard/src/main.jsx @@ -0,0 +1,10 @@ +import { StrictMode } from 'react' +import { createRoot } from 'react-dom/client' +import App from './App.jsx' +import './index.css' + +createRoot(document.getElementById('root')).render( + + + , +) diff --git a/packages/dashboard/vite.config.js b/packages/dashboard/vite.config.js new file mode 100644 index 0000000..5a33944 --- /dev/null +++ b/packages/dashboard/vite.config.js @@ -0,0 +1,7 @@ +import { defineConfig } from 'vite' +import react from '@vitejs/plugin-react' + +// https://vitejs.dev/config/ +export default defineConfig({ + plugins: [react()], +}) diff --git a/yarn.lock b/yarn.lock index 124aaf2..24ed6c9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1737,7 +1737,7 @@ __metadata: languageName: node linkType: hard -"@babel/core@npm:^7.1.0": +"@babel/core@npm:^7.1.0, @babel/core@npm:^7.24.5": version: 7.25.2 resolution: "@babel/core@npm:7.25.2" dependencies: @@ -2101,6 +2101,13 @@ __metadata: languageName: node linkType: hard +"@babel/helper-plugin-utils@npm:^7.24.7": + version: 7.24.8 + resolution: "@babel/helper-plugin-utils@npm:7.24.8" + checksum: 10c0/0376037f94a3bfe6b820a39f81220ac04f243eaee7193774b983e956c1750883ff236b30785795abbcda43fac3ece74750566830c2daa4d6e3870bb0dff34c2d + languageName: node + linkType: hard + "@babel/helper-remap-async-to-generator@npm:^7.22.20": version: 7.22.20 resolution: "@babel/helper-remap-async-to-generator@npm:7.22.20" @@ -3064,6 +3071,28 @@ __metadata: languageName: node linkType: hard +"@babel/plugin-transform-react-jsx-self@npm:^7.24.5": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-jsx-self@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/dcf3b732401f47f06bb29d6016e48066f66de00029a0ded98ddd9983c770a00a109d91cd04d2700d15ee0bcec3ae3027a5f12d69e15ec56efc0bcbfac65e92cb + languageName: node + linkType: hard + +"@babel/plugin-transform-react-jsx-source@npm:^7.24.1": + version: 7.24.7 + resolution: "@babel/plugin-transform-react-jsx-source@npm:7.24.7" + dependencies: + "@babel/helper-plugin-utils": "npm:^7.24.7" + peerDependencies: + "@babel/core": ^7.0.0-0 + checksum: 10c0/970ef1264c7c6c416ab11610665d5309aec2bd2b9086ae394e1132e65138d97b060a7dc9d31054e050d6dc475b5a213938c9707c0202a5022d55dcb4c5abe28f + languageName: node + linkType: hard + "@babel/plugin-transform-regenerator@npm:^7.23.3": version: 7.23.3 resolution: "@babel/plugin-transform-regenerator@npm:7.23.3" @@ -3452,6 +3481,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/aix-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/aix-ppc64@npm:0.21.5" + conditions: os=aix & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/android-arm64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/android-arm64@npm:0.20.1" @@ -3459,6 +3495,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm64@npm:0.21.5" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/android-arm@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/android-arm@npm:0.20.1" @@ -3466,6 +3509,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-arm@npm:0.21.5" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + "@esbuild/android-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/android-x64@npm:0.20.1" @@ -3473,6 +3523,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/android-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/android-x64@npm:0.21.5" + conditions: os=android & cpu=x64 + languageName: node + linkType: hard + "@esbuild/darwin-arm64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/darwin-arm64@npm:0.20.1" @@ -3480,6 +3537,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-arm64@npm:0.21.5" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/darwin-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/darwin-x64@npm:0.20.1" @@ -3487,6 +3551,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/darwin-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/darwin-x64@npm:0.21.5" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + "@esbuild/freebsd-arm64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/freebsd-arm64@npm:0.20.1" @@ -3494,6 +3565,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-arm64@npm:0.21.5" + conditions: os=freebsd & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/freebsd-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/freebsd-x64@npm:0.20.1" @@ -3501,6 +3579,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/freebsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/freebsd-x64@npm:0.21.5" + conditions: os=freebsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/linux-arm64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-arm64@npm:0.20.1" @@ -3508,6 +3593,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm64@npm:0.21.5" + conditions: os=linux & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/linux-arm@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-arm@npm:0.20.1" @@ -3515,6 +3607,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-arm@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-arm@npm:0.21.5" + conditions: os=linux & cpu=arm + languageName: node + linkType: hard + "@esbuild/linux-ia32@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-ia32@npm:0.20.1" @@ -3522,6 +3621,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ia32@npm:0.21.5" + conditions: os=linux & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/linux-loong64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-loong64@npm:0.20.1" @@ -3529,6 +3635,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-loong64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-loong64@npm:0.21.5" + conditions: os=linux & cpu=loong64 + languageName: node + linkType: hard + "@esbuild/linux-mips64el@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-mips64el@npm:0.20.1" @@ -3536,6 +3649,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-mips64el@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-mips64el@npm:0.21.5" + conditions: os=linux & cpu=mips64el + languageName: node + linkType: hard + "@esbuild/linux-ppc64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-ppc64@npm:0.20.1" @@ -3543,6 +3663,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-ppc64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-ppc64@npm:0.21.5" + conditions: os=linux & cpu=ppc64 + languageName: node + linkType: hard + "@esbuild/linux-riscv64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-riscv64@npm:0.20.1" @@ -3550,6 +3677,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-riscv64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-riscv64@npm:0.21.5" + conditions: os=linux & cpu=riscv64 + languageName: node + linkType: hard + "@esbuild/linux-s390x@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-s390x@npm:0.20.1" @@ -3557,6 +3691,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-s390x@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-s390x@npm:0.21.5" + conditions: os=linux & cpu=s390x + languageName: node + linkType: hard + "@esbuild/linux-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/linux-x64@npm:0.20.1" @@ -3564,6 +3705,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/linux-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/linux-x64@npm:0.21.5" + conditions: os=linux & cpu=x64 + languageName: node + linkType: hard + "@esbuild/netbsd-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/netbsd-x64@npm:0.20.1" @@ -3571,6 +3719,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/netbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/netbsd-x64@npm:0.21.5" + conditions: os=netbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/openbsd-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/openbsd-x64@npm:0.20.1" @@ -3578,6 +3733,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/openbsd-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/openbsd-x64@npm:0.21.5" + conditions: os=openbsd & cpu=x64 + languageName: node + linkType: hard + "@esbuild/sunos-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/sunos-x64@npm:0.20.1" @@ -3585,6 +3747,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/sunos-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/sunos-x64@npm:0.21.5" + conditions: os=sunos & cpu=x64 + languageName: node + linkType: hard + "@esbuild/win32-arm64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/win32-arm64@npm:0.20.1" @@ -3592,6 +3761,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-arm64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-arm64@npm:0.21.5" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + "@esbuild/win32-ia32@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/win32-ia32@npm:0.20.1" @@ -3599,6 +3775,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-ia32@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-ia32@npm:0.21.5" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + "@esbuild/win32-x64@npm:0.20.1": version: 0.20.1 resolution: "@esbuild/win32-x64@npm:0.20.1" @@ -3606,6 +3789,13 @@ __metadata: languageName: node linkType: hard +"@esbuild/win32-x64@npm:0.21.5": + version: 0.21.5 + resolution: "@esbuild/win32-x64@npm:0.21.5" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@hapi/accept@npm:^6.0.1": version: 6.0.3 resolution: "@hapi/accept@npm:6.0.3" @@ -4721,6 +4911,118 @@ __metadata: languageName: node linkType: hard +"@rollup/rollup-android-arm-eabi@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm-eabi@npm:4.21.2" + conditions: os=android & cpu=arm + languageName: node + linkType: hard + +"@rollup/rollup-android-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-android-arm64@npm:4.21.2" + conditions: os=android & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-arm64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-arm64@npm:4.21.2" + conditions: os=darwin & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-darwin-x64@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-darwin-x64@npm:4.21.2" + conditions: os=darwin & cpu=x64 + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-gnueabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm-musleabihf@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm-musleabihf@npm:4.21.2" + conditions: os=linux & cpu=arm & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-gnu@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-arm64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-arm64-musl@npm:4.21.2" + conditions: os=linux & cpu=arm64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-powerpc64le-gnu@npm:4.21.2" + conditions: os=linux & cpu=ppc64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-riscv64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-riscv64-gnu@npm:4.21.2" + conditions: os=linux & cpu=riscv64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-s390x-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-s390x-gnu@npm:4.21.2" + conditions: os=linux & cpu=s390x & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-gnu@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-gnu@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=glibc + languageName: node + linkType: hard + +"@rollup/rollup-linux-x64-musl@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-linux-x64-musl@npm:4.21.2" + conditions: os=linux & cpu=x64 & libc=musl + languageName: node + linkType: hard + +"@rollup/rollup-win32-arm64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-arm64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=arm64 + languageName: node + linkType: hard + +"@rollup/rollup-win32-ia32-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-ia32-msvc@npm:4.21.2" + conditions: os=win32 & cpu=ia32 + languageName: node + linkType: hard + +"@rollup/rollup-win32-x64-msvc@npm:4.21.2": + version: 4.21.2 + resolution: "@rollup/rollup-win32-x64-msvc@npm:4.21.2" + conditions: os=win32 & cpu=x64 + languageName: node + linkType: hard + "@serverless/dashboard-plugin@npm:^7.2.0": version: 7.2.0 resolution: "@serverless/dashboard-plugin@npm:7.2.0" @@ -5958,6 +6260,20 @@ __metadata: languageName: unknown linkType: soft +"@trace-stack/dashboard@workspace:packages/dashboard": + version: 0.0.0-use.local + resolution: "@trace-stack/dashboard@workspace:packages/dashboard" + dependencies: + "@types/react": "npm:^18.3.3" + "@types/react-dom": "npm:^18.3.0" + "@vitejs/plugin-react": "npm:^4.3.1" + globals: "npm:^15.9.0" + react: "npm:^18.3.1" + react-dom: "npm:^18.3.1" + vite: "npm:^5.4.1" + languageName: unknown + linkType: soft + "@trace-stack/lambda-layer@workspace:packages/lambda-layer/nodejs": version: 0.0.0-use.local resolution: "@trace-stack/lambda-layer@workspace:packages/lambda-layer/nodejs" @@ -5968,7 +6284,7 @@ __metadata: languageName: unknown linkType: soft -"@types/babel__core@npm:^7.1.0": +"@types/babel__core@npm:^7.1.0, @types/babel__core@npm:^7.20.5": version: 7.20.5 resolution: "@types/babel__core@npm:7.20.5" dependencies: @@ -6034,6 +6350,13 @@ __metadata: languageName: node linkType: hard +"@types/estree@npm:1.0.5": + version: 1.0.5 + resolution: "@types/estree@npm:1.0.5" + checksum: 10c0/b3b0e334288ddb407c7b3357ca67dbee75ee22db242ca7c56fe27db4e1a31989cb8af48a84dd401deb787fe10cc6b2ab1ee82dc4783be87ededbe3d53c79c70d + languageName: node + linkType: hard + "@types/graceful-fs@npm:^4.1.3": version: 4.1.9 resolution: "@types/graceful-fs@npm:4.1.9" @@ -6136,6 +6459,32 @@ __metadata: languageName: node linkType: hard +"@types/prop-types@npm:*": + version: 15.7.12 + resolution: "@types/prop-types@npm:15.7.12" + checksum: 10c0/1babcc7db6a1177779f8fde0ccc78d64d459906e6ef69a4ed4dd6339c920c2e05b074ee5a92120fe4e9d9f1a01c952f843ebd550bee2332fc2ef81d1706878f8 + languageName: node + linkType: hard + +"@types/react-dom@npm:^18.3.0": + version: 18.3.0 + resolution: "@types/react-dom@npm:18.3.0" + dependencies: + "@types/react": "npm:*" + checksum: 10c0/6c90d2ed72c5a0e440d2c75d99287e4b5df3e7b011838cdc03ae5cd518ab52164d86990e73246b9d812eaf02ec351d74e3b4f5bd325bf341e13bf980392fd53b + languageName: node + linkType: hard + +"@types/react@npm:*, @types/react@npm:^18.3.3": + version: 18.3.5 + resolution: "@types/react@npm:18.3.5" + dependencies: + "@types/prop-types": "npm:*" + csstype: "npm:^3.0.2" + checksum: 10c0/548b1d3d7c2f0242fbfdbbd658731b4ce69a134be072fa83e6ab516f2840402a3f20e3e7f72e95133b23d4880ef24a6d864050dc8e1f7c68f39fa87ca8445917 + languageName: node + linkType: hard + "@types/responselike@npm:^1.0.0": version: 1.0.0 resolution: "@types/responselike@npm:1.0.0" @@ -6198,6 +6547,21 @@ __metadata: languageName: node linkType: hard +"@vitejs/plugin-react@npm:^4.3.1": + version: 4.3.1 + resolution: "@vitejs/plugin-react@npm:4.3.1" + dependencies: + "@babel/core": "npm:^7.24.5" + "@babel/plugin-transform-react-jsx-self": "npm:^7.24.5" + "@babel/plugin-transform-react-jsx-source": "npm:^7.24.1" + "@types/babel__core": "npm:^7.20.5" + react-refresh: "npm:^0.14.2" + peerDependencies: + vite: ^4.2.0 || ^5.0.0 + checksum: 10c0/39a027feddfd6b3e307121d79631462ef1aae05714ba7a2f9a73d240d0f89c2bf281132568eb27b55d6ddaf08d86ad1bd8b0066090240e570de8c6320eb9a903 + languageName: node + linkType: hard + "abab@npm:^2.0.0": version: 2.0.6 resolution: "abab@npm:2.0.6" @@ -8007,6 +8371,13 @@ __metadata: languageName: node linkType: hard +"csstype@npm:^3.0.2": + version: 3.1.3 + resolution: "csstype@npm:3.1.3" + checksum: 10c0/80c089d6f7e0c5b2bd83cf0539ab41474198579584fa10d86d0cafe0642202343cbc119e076a0b1aece191989477081415d66c9fefbf3c957fc2fc4b7009f248 + languageName: node + linkType: hard + "d@npm:1, d@npm:^1.0.1": version: 1.0.1 resolution: "d@npm:1.0.1" @@ -8800,6 +9171,86 @@ __metadata: languageName: node linkType: hard +"esbuild@npm:^0.21.3": + version: 0.21.5 + resolution: "esbuild@npm:0.21.5" + dependencies: + "@esbuild/aix-ppc64": "npm:0.21.5" + "@esbuild/android-arm": "npm:0.21.5" + "@esbuild/android-arm64": "npm:0.21.5" + "@esbuild/android-x64": "npm:0.21.5" + "@esbuild/darwin-arm64": "npm:0.21.5" + "@esbuild/darwin-x64": "npm:0.21.5" + "@esbuild/freebsd-arm64": "npm:0.21.5" + "@esbuild/freebsd-x64": "npm:0.21.5" + "@esbuild/linux-arm": "npm:0.21.5" + "@esbuild/linux-arm64": "npm:0.21.5" + "@esbuild/linux-ia32": "npm:0.21.5" + "@esbuild/linux-loong64": "npm:0.21.5" + "@esbuild/linux-mips64el": "npm:0.21.5" + "@esbuild/linux-ppc64": "npm:0.21.5" + "@esbuild/linux-riscv64": "npm:0.21.5" + "@esbuild/linux-s390x": "npm:0.21.5" + "@esbuild/linux-x64": "npm:0.21.5" + "@esbuild/netbsd-x64": "npm:0.21.5" + "@esbuild/openbsd-x64": "npm:0.21.5" + "@esbuild/sunos-x64": "npm:0.21.5" + "@esbuild/win32-arm64": "npm:0.21.5" + "@esbuild/win32-ia32": "npm:0.21.5" + "@esbuild/win32-x64": "npm:0.21.5" + dependenciesMeta: + "@esbuild/aix-ppc64": + optional: true + "@esbuild/android-arm": + optional: true + "@esbuild/android-arm64": + optional: true + "@esbuild/android-x64": + optional: true + "@esbuild/darwin-arm64": + optional: true + "@esbuild/darwin-x64": + optional: true + "@esbuild/freebsd-arm64": + optional: true + "@esbuild/freebsd-x64": + optional: true + "@esbuild/linux-arm": + optional: true + "@esbuild/linux-arm64": + optional: true + "@esbuild/linux-ia32": + optional: true + "@esbuild/linux-loong64": + optional: true + "@esbuild/linux-mips64el": + optional: true + "@esbuild/linux-ppc64": + optional: true + "@esbuild/linux-riscv64": + optional: true + "@esbuild/linux-s390x": + optional: true + "@esbuild/linux-x64": + optional: true + "@esbuild/netbsd-x64": + optional: true + "@esbuild/openbsd-x64": + optional: true + "@esbuild/sunos-x64": + optional: true + "@esbuild/win32-arm64": + optional: true + "@esbuild/win32-ia32": + optional: true + "@esbuild/win32-x64": + optional: true + bin: + esbuild: bin/esbuild + checksum: 10c0/fa08508adf683c3f399e8a014a6382a6b65542213431e26206c0720e536b31c09b50798747c2a105a4bbba1d9767b8d3615a74c2f7bf1ddf6d836cd11eb672de + languageName: node + linkType: hard + "escalade@npm:^3.1.1": version: 3.1.1 resolution: "escalade@npm:3.1.1" @@ -9607,6 +10058,16 @@ __metadata: languageName: node linkType: hard +"fsevents@npm:~2.3.3": + version: 2.3.3 + resolution: "fsevents@npm:2.3.3" + dependencies: + node-gyp: "npm:latest" + checksum: 10c0/a1f0c44595123ed717febbc478aa952e47adfc28e2092be66b8ab1635147254ca6cfe1df792a8997f22716d4cbafc73309899ff7bfac2ac3ad8cf2e4ecc3ec60 + conditions: os=darwin + languageName: node + linkType: hard + "fsevents@patch:fsevents@npm%3A^1.2.7#optional!builtin": version: 1.2.13 resolution: "fsevents@patch:fsevents@npm%3A1.2.13#optional!builtin::version=1.2.13&hash=d11327" @@ -9626,6 +10087,15 @@ __metadata: languageName: node linkType: hard +"fsevents@patch:fsevents@npm%3A~2.3.3#optional!builtin": + version: 2.3.3 + resolution: "fsevents@patch:fsevents@npm%3A2.3.3#optional!builtin::version=2.3.3&hash=df0bf1" + dependencies: + node-gyp: "npm:latest" + conditions: os=darwin + languageName: node + linkType: hard + "function-bind@npm:^1.1.1": version: 1.1.1 resolution: "function-bind@npm:1.1.1" @@ -9846,6 +10316,13 @@ __metadata: languageName: node linkType: hard +"globals@npm:^15.9.0": + version: 15.9.0 + resolution: "globals@npm:15.9.0" + checksum: 10c0/de4b553e412e7e830998578d51b605c492256fb2a9273eaeec6ec9ee519f1c5aa50de57e3979911607fd7593a4066420e01d8c3d551e7a6a236e96c521aee36c + languageName: node + linkType: hard + "globalthis@npm:^1.0.3": version: 1.0.4 resolution: "globalthis@npm:1.0.4" @@ -12465,7 +12942,7 @@ __metadata: languageName: node linkType: hard -"loose-envify@npm:^1.0.0": +"loose-envify@npm:^1.0.0, loose-envify@npm:^1.1.0": version: 1.4.0 resolution: "loose-envify@npm:1.4.0" dependencies: @@ -12942,6 +13419,15 @@ __metadata: languageName: node linkType: hard +"nanoid@npm:^3.3.7": + version: 3.3.7 + resolution: "nanoid@npm:3.3.7" + bin: + nanoid: bin/nanoid.cjs + checksum: 10c0/e3fb661aa083454f40500473bb69eedb85dc160e763150b9a2c567c7e9ff560ce028a9f833123b618a6ea742e311138b591910e795614a629029e86e180660f3 + languageName: node + linkType: hard + "nanomatch@npm:^1.2.9": version: 1.2.13 resolution: "nanomatch@npm:1.2.13" @@ -13823,6 +14309,17 @@ __metadata: languageName: node linkType: hard +"postcss@npm:^8.4.41": + version: 8.4.41 + resolution: "postcss@npm:8.4.41" + dependencies: + nanoid: "npm:^3.3.7" + picocolors: "npm:^1.0.1" + source-map-js: "npm:^1.2.0" + checksum: 10c0/c1828fc59e7ec1a3bf52b3a42f615dba53c67960ed82a81df6441b485fe43c20aba7f4e7c55425762fd99c594ecabbaaba8cf5b30fd79dfec5b52a9f63a2d690 + languageName: node + linkType: hard + "prelude-ls@npm:~1.1.2": version: 1.1.2 resolution: "prelude-ls@npm:1.1.2" @@ -13839,6 +14336,15 @@ __metadata: languageName: node linkType: hard +"prettier@npm:^3.3.3": + version: 3.3.3 + resolution: "prettier@npm:3.3.3" + bin: + prettier: bin/prettier.cjs + checksum: 10c0/b85828b08e7505716324e4245549b9205c0cacb25342a030ba8885aba2039a115dbcf75a0b7ca3b37bc9d101ee61fab8113fc69ca3359f2a226f1ecc07ad2e26 + languageName: node + linkType: hard + "pretty-format@npm:^24.9.0": version: 24.9.0 resolution: "pretty-format@npm:24.9.0" @@ -14034,6 +14540,18 @@ __metadata: languageName: node linkType: hard +"react-dom@npm:^18.3.1": + version: 18.3.1 + resolution: "react-dom@npm:18.3.1" + dependencies: + loose-envify: "npm:^1.1.0" + scheduler: "npm:^0.23.2" + peerDependencies: + react: ^18.3.1 + checksum: 10c0/a752496c1941f958f2e8ac56239172296fcddce1365ce45222d04a1947e0cc5547df3e8447f855a81d6d39f008d7c32eab43db3712077f09e3f67c4874973e85 + languageName: node + linkType: hard + "react-is@npm:^16.8.4": version: 16.13.1 resolution: "react-is@npm:16.13.1" @@ -14048,6 +14566,22 @@ __metadata: languageName: node linkType: hard +"react-refresh@npm:^0.14.2": + version: 0.14.2 + resolution: "react-refresh@npm:0.14.2" + checksum: 10c0/875b72ef56b147a131e33f2abd6ec059d1989854b3ff438898e4f9310bfcc73acff709445b7ba843318a953cb9424bcc2c05af2b3d80011cee28f25aef3e2ebb + languageName: node + linkType: hard + +"react@npm:^18.3.1": + version: 18.3.1 + resolution: "react@npm:18.3.1" + dependencies: + loose-envify: "npm:^1.1.0" + checksum: 10c0/283e8c5efcf37802c9d1ce767f302dd569dd97a70d9bb8c7be79a789b9902451e0d16334b05d73299b20f048cbc3c7d288bbbde10b701fa194e2089c237dbea3 + languageName: node + linkType: hard + "read-pkg-up@npm:^4.0.0": version: 4.0.0 resolution: "read-pkg-up@npm:4.0.0" @@ -14498,6 +15032,69 @@ __metadata: languageName: node linkType: hard +"rollup@npm:^4.20.0": + version: 4.21.2 + resolution: "rollup@npm:4.21.2" + dependencies: + "@rollup/rollup-android-arm-eabi": "npm:4.21.2" + "@rollup/rollup-android-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-arm64": "npm:4.21.2" + "@rollup/rollup-darwin-x64": "npm:4.21.2" + "@rollup/rollup-linux-arm-gnueabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm-musleabihf": "npm:4.21.2" + "@rollup/rollup-linux-arm64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-arm64-musl": "npm:4.21.2" + "@rollup/rollup-linux-powerpc64le-gnu": "npm:4.21.2" + "@rollup/rollup-linux-riscv64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-s390x-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-gnu": "npm:4.21.2" + "@rollup/rollup-linux-x64-musl": "npm:4.21.2" + "@rollup/rollup-win32-arm64-msvc": "npm:4.21.2" + "@rollup/rollup-win32-ia32-msvc": "npm:4.21.2" + "@rollup/rollup-win32-x64-msvc": "npm:4.21.2" + "@types/estree": "npm:1.0.5" + fsevents: "npm:~2.3.2" + dependenciesMeta: + "@rollup/rollup-android-arm-eabi": + optional: true + "@rollup/rollup-android-arm64": + optional: true + "@rollup/rollup-darwin-arm64": + optional: true + "@rollup/rollup-darwin-x64": + optional: true + "@rollup/rollup-linux-arm-gnueabihf": + optional: true + "@rollup/rollup-linux-arm-musleabihf": + optional: true + "@rollup/rollup-linux-arm64-gnu": + optional: true + "@rollup/rollup-linux-arm64-musl": + optional: true + "@rollup/rollup-linux-powerpc64le-gnu": + optional: true + "@rollup/rollup-linux-riscv64-gnu": + optional: true + "@rollup/rollup-linux-s390x-gnu": + optional: true + "@rollup/rollup-linux-x64-gnu": + optional: true + "@rollup/rollup-linux-x64-musl": + optional: true + "@rollup/rollup-win32-arm64-msvc": + optional: true + "@rollup/rollup-win32-ia32-msvc": + optional: true + "@rollup/rollup-win32-x64-msvc": + optional: true + fsevents: + optional: true + bin: + rollup: dist/bin/rollup + checksum: 10c0/c9d97f7a21cde110371b2e890a31a996fee09b81e639e79372b962a9638ae653d2d24186b94632fc5dfab8a0582e1d0639dfe34b8b75051facd86915a9585a5f + languageName: node + linkType: hard + "rsvp@npm:^4.8.4": version: 4.8.5 resolution: "rsvp@npm:4.8.5" @@ -14639,6 +15236,15 @@ __metadata: languageName: node linkType: hard +"scheduler@npm:^0.23.2": + version: 0.23.2 + resolution: "scheduler@npm:0.23.2" + dependencies: + loose-envify: "npm:^1.1.0" + checksum: 10c0/26383305e249651d4c58e6705d5f8425f153211aef95f15161c151f7b8de885f24751b377e4a0b3dd42cce09aad3f87a61dab7636859c0d89b7daf1a1e2a5c78 + languageName: node + linkType: hard + "seek-bzip@npm:^1.0.5": version: 1.0.6 resolution: "seek-bzip@npm:1.0.6" @@ -15128,6 +15734,13 @@ __metadata: languageName: node linkType: hard +"source-map-js@npm:^1.2.0": + version: 1.2.0 + resolution: "source-map-js@npm:1.2.0" + checksum: 10c0/7e5f896ac10a3a50fe2898e5009c58ff0dc102dcb056ed27a354623a0ece8954d4b2649e1a1b2b52ef2e161d26f8859c7710350930751640e71e374fe2d321a4 + languageName: node + linkType: hard + "source-map-resolve@npm:^0.5.0": version: 0.5.3 resolution: "source-map-resolve@npm:0.5.3" @@ -15875,6 +16488,8 @@ __metadata: "trace-stack@workspace:.": version: 0.0.0-use.local resolution: "trace-stack@workspace:." + dependencies: + prettier: "npm:^3.3.3" languageName: unknown linkType: soft @@ -16385,6 +17000,49 @@ __metadata: languageName: node linkType: hard +"vite@npm:^5.4.1": + version: 5.4.2 + resolution: "vite@npm:5.4.2" + dependencies: + esbuild: "npm:^0.21.3" + fsevents: "npm:~2.3.3" + postcss: "npm:^8.4.41" + rollup: "npm:^4.20.0" + peerDependencies: + "@types/node": ^18.0.0 || >=20.0.0 + less: "*" + lightningcss: ^1.21.0 + sass: "*" + sass-embedded: "*" + stylus: "*" + sugarss: "*" + terser: ^5.4.0 + dependenciesMeta: + fsevents: + optional: true + peerDependenciesMeta: + "@types/node": + optional: true + less: + optional: true + lightningcss: + optional: true + sass: + optional: true + sass-embedded: + optional: true + stylus: + optional: true + sugarss: + optional: true + terser: + optional: true + bin: + vite: bin/vite.js + checksum: 10c0/23e347ca8aa6f0a774227e4eb7abae228f12c6806a727b046aa75e7ee37ffc2d68cff74360e12a42c347f79adc294e2363bc723b957bf4b382b5a8fb39e4df9d + languageName: node + linkType: hard + "w3c-hr-time@npm:^1.0.1": version: 1.0.2 resolution: "w3c-hr-time@npm:1.0.2"