diff --git a/api/.gitignore b/api/.gitignore
new file mode 100644
index 000000000..11ddd8dbe
--- /dev/null
+++ b/api/.gitignore
@@ -0,0 +1,3 @@
+node_modules
+# Keep environment variables out of version control
+.env
diff --git a/api/SAMPLE.env b/api/SAMPLE.env
new file mode 100644
index 000000000..32b4c775a
--- /dev/null
+++ b/api/SAMPLE.env
@@ -0,0 +1,7 @@
+# Environment variables declared in this file are automatically made available to Prisma.
+# See the documentation for more detail: https://pris.ly/d/prisma-schema#accessing-environment-variables-from-the-schema
+
+# Prisma supports the native connection string format for PostgreSQL, MySQL, SQLite, SQL Server, MongoDB and CockroachDB.
+# See the documentation for all the connection string options: https://pris.ly/d/connection-strings
+
+DATABASE_URL="mongodb+srv://test:test@cluster0.ns1yp.mongodb.net/myFirstDatabase"
\ No newline at end of file
diff --git a/api/package.json b/api/package.json
new file mode 100644
index 000000000..78f147060
--- /dev/null
+++ b/api/package.json
@@ -0,0 +1,30 @@
+{
+ "name": "demo-api",
+ "version": "0.1.0",
+ "description": "",
+ "main": "src/index.ts",
+ "private": true,
+ "scripts": {
+ "start": "nodemon src/index.ts",
+ "build": "tsc",
+ "serve": "node dist/index.js"
+ },
+ "author": "Matt Glissmann",
+ "license": "ISC",
+ "dependencies": {
+ "@prisma/client": "5.5.2"
+ },
+ "devDependencies": {
+ "@types/cors": "^2.8.15",
+ "@types/express": "^4.17.20",
+ "@types/express-validator": "^3.0.0",
+ "@types/node": "^20.8.9",
+ "cors": "^2.8.5",
+ "express": "^4.18.2",
+ "express-validator": "^7.0.1",
+ "nodemon": "^3.0.2",
+ "prisma": "^5.5.2",
+ "ts-node": "^10.9.1",
+ "typescript": "^5.2.2"
+ }
+}
diff --git a/api/prisma/schema.prisma b/api/prisma/schema.prisma
new file mode 100644
index 000000000..e4c6df517
--- /dev/null
+++ b/api/prisma/schema.prisma
@@ -0,0 +1,86 @@
+// This is your Prisma schema file,
+// learn more about it in the docs: https://pris.ly/d/prisma-schema
+
+generator client {
+ provider = "prisma-client-js"
+}
+
+datasource db {
+ provider = "mongodb"
+ url = env("DATABASE_URL")
+}
+
+model User {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ email String @unique
+ name String?
+ posts Post[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+model Post {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ title String
+ content String?
+ published Boolean @default(false)
+ author User @relation(fields: [authorId], references: [id])
+ authorId String @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+model Component {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ status String?
+ description String?
+ keywords String[]
+ resources Resource[]
+ anatomy Anatomy[]
+ states ComponentState[]
+ configurations Configuration[]
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+// Anatomy is the physical structure of a component and describes the parts from which it is made
+model Anatomy {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ component Component @relation(fields: [componentId], references: [id])
+ componentId String @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+// ComponentState represent various interactive states of a component
+model ComponentState {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ component Component @relation(fields: [componentId], references: [id])
+ componentId String @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+// Configuration is a variant or flavor of a component which can be modified via its properties
+model Configuration {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ component Component @relation(fields: [componentId], references: [id])
+ componentId String @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
+
+// Resource is a file or link that is associated with a component
+model Resource {
+ id String @id @default(auto()) @map("_id") @db.ObjectId
+ name String
+ // types may include: design, code/implementation, documentation, demo, example use cases,
+ // research, design criteria, design rationale, etc.
+ type String
+ url String
+ component Component? @relation(fields: [componentId], references: [id])
+ componentId String @db.ObjectId
+ createdAt DateTime @default(now())
+ updatedAt DateTime @updatedAt
+}
diff --git a/api/src/components/actions.ts b/api/src/components/actions.ts
new file mode 100644
index 000000000..25cfe33f2
--- /dev/null
+++ b/api/src/components/actions.ts
@@ -0,0 +1,139 @@
+import { PrismaClient } from '@prisma/client';
+import { Request, Response } from 'express';
+
+const prisma = new PrismaClient();
+
+const createComponent = async (req: Request, res: Response) => {
+ if (!req.body) {
+ return res.status(400).json({ error: 'Invalid request. Request body is required.' });
+ }
+
+ const { name, description, keywords, status } = req.body;
+
+ const component = await prisma.component.create({
+ data: {
+ name,
+ description,
+ keywords,
+ status,
+ },
+ });
+
+ return res.json(component);
+}
+
+const updateComponent = async (req: Request, res: Response) => {
+ const { id, name, description, keywords, status } = req.body;
+
+ const component = await prisma.component.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!component) {
+ res.status(404).send('Component not found');
+ } else {
+ const updatedComponent = await prisma.component.update({
+ where: {
+ id: id,
+ },
+ data: {
+ name: name || component.name,
+ description: description || component.description,
+ keywords: keywords || component.keywords,
+ status: status || component.status,
+ },
+ });
+
+ return res.json(updatedComponent);
+ }
+}
+
+const createAndAddResource = async (req: Request, res: Response) => {
+ const { name, type, url, componentId } = req.body;
+
+ const resource = await prisma.resource.create({
+ data: {
+ name,
+ type,
+ url,
+ component: {
+ connect: {
+ id: componentId,
+ },
+ },
+ },
+ });
+
+ return res.json(resource);
+}
+
+const addResource = async (req: Request, res: Response) => {
+ const { id, resourceId } = req.body;
+
+ const component = await prisma.component.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!component) {
+ res.status(404).send('Component not found');
+ } else {
+ const updatedComponent = await prisma.component.update({
+ where: {
+ id: id,
+ },
+ data: {
+ resources: {
+ connect: {
+ id: resourceId,
+ },
+ },
+ },
+ });
+
+ return res.json(updatedComponent);
+ }
+}
+
+const removeResource = async (req: Request, res: Response) => {
+ const { id, resourceId } = req.body;
+
+ const component = await prisma.component.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!component) {
+ res.status(404).send('Component not found');
+ } else {
+ const updatedComponent = await prisma.component.update({
+ where: {
+ id: id,
+ },
+ data: {
+ resources: {
+ disconnect: {
+ id: resourceId,
+ },
+ },
+ },
+ include: {
+ resources: true,
+ },
+ });
+
+ return res.json(updatedComponent);
+ }
+}
+
+export {
+ createComponent,
+ updateComponent,
+ addResource,
+ createAndAddResource,
+ removeResource
+}
\ No newline at end of file
diff --git a/api/src/components/routes.ts b/api/src/components/routes.ts
new file mode 100644
index 000000000..acde47a8d
--- /dev/null
+++ b/api/src/components/routes.ts
@@ -0,0 +1,165 @@
+import { Router, Request, Response } from 'express';
+import { validationResult } from 'express-validator';
+import { PrismaClient } from '@prisma/client';
+import {
+ createComponent,
+ updateComponent,
+ addResource,
+ createAndAddResource,
+ removeResource
+} from './actions';
+import { createRules, updateRules } from './validation-rules';
+
+const prisma = new PrismaClient();
+const router = Router();
+
+// Components CRUD
+router.post('/', createRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ createComponent(req, res).then(async (component) => {
+ res.status(201).json(component);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.get('/', async (req: Request, res: Response) => {
+ const components = await prisma.component.findMany({
+ orderBy: {
+ name: 'asc',
+ },
+ });
+ res.json(components);
+ await prisma.$disconnect();
+});
+
+router.get('/:id', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const component = await prisma.component.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!component) {
+ res.status(404).send('Component not found');
+ } else {
+ res.json(component);
+ }
+
+ await prisma.$disconnect();
+});
+
+router.put('/:id', updateRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ updateComponent(req, res).then(async (component) => {
+ res.json(component);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.delete('/:id', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const component = await prisma.component.delete({
+ where: {
+ id: id,
+ },
+ });
+
+ res.json(component);
+ await prisma.$disconnect();
+});
+
+// Components + Resources
+router.get('/:id/resources', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const component = await prisma.component.findUnique({
+ where: {
+ id: id,
+ },
+ include: {
+ resources: {
+ orderBy: {
+ name: 'asc',
+ },
+ },
+ },
+ });
+
+ if (!component) {
+ res.status(404).send('Component not found');
+ } else {
+ res.json(component.resources);
+ }
+
+ await prisma.$disconnect();
+});
+
+router.post('/:id/resources', async (req: Request, res: Response) => {
+ createAndAddResource(req, res).then(async (resource) => {
+ res.status(201).json(resource);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.put('/:id/resources/:resourceId', async (req: Request, res: Response) => {
+ addResource(req, res).then(async (component) => {
+ res.json(component);
+ await prisma.$disconnect();
+ }
+ ).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.put('/:id/resources', async (req: Request, res: Response) => {
+ const resources = req.body;
+ const id = req.params.id;
+
+ const component = await prisma.component.update({
+ where: {
+ id: id,
+ },
+ data: {
+ resources: {
+ deleteMany: {},
+ create: resources,
+ },
+ },
+ });
+
+ res.json(component);
+ await prisma.$disconnect();
+});
+
+router.delete('/:id/resources/:resourceId', async (req: Request, res: Response) => {
+ removeResource(req, res).then(async (component) => {
+ res.json(component);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+const componentsRouter = router;
+export default componentsRouter;
\ No newline at end of file
diff --git a/api/src/components/validation-rules.ts b/api/src/components/validation-rules.ts
new file mode 100644
index 000000000..82444cf00
--- /dev/null
+++ b/api/src/components/validation-rules.ts
@@ -0,0 +1,19 @@
+import { body } from 'express-validator';
+
+const commonRules = [
+ body('name').notEmpty().withMessage('Name is required.'),
+];
+
+const createRules = [
+ ...commonRules,
+];
+
+const updateRules = [
+ body('id').notEmpty().withMessage('ID is required.'),
+ ...commonRules,
+];
+
+export {
+ createRules,
+ updateRules,
+};
\ No newline at end of file
diff --git a/api/src/index.ts b/api/src/index.ts
new file mode 100644
index 000000000..57acdf812
--- /dev/null
+++ b/api/src/index.ts
@@ -0,0 +1,40 @@
+import express, { Request, Response, NextFunction } from 'express';
+import cors from 'cors';
+import routes from './routes';
+import { logger } from './utils/logger';
+
+const app = express();
+const port = process.env.PORT || 8000;
+
+// Log all requests
+app.use((req: Request, res: Response, next: NextFunction) => {
+ console.log(logger(req, res, {body: true}));
+ next();
+});
+
+// Middleware
+app.use(cors())
+app.use(express.json());
+
+// Authenticaion middleware
+app.use((req: Request, res: Response, next: NextFunction) => {
+ const authHeader = req.headers.authorization;
+ const token = authHeader?.split(' ')[1];
+
+ // TODO: Implement authentication middleware
+ next();
+});
+
+// Routes
+app.use('/', routes);
+
+// Error handling
+app.use((err: Error, req: Request, res: Response, next: NextFunction) => {
+ console.error(err.stack);
+ res.status(500).send('Something\'s not quite right! Error: ' + err.message);
+});
+
+// Start app server
+app.listen(port, () => {
+ console.log(`Express app server listening at http://localhost:${port}`);
+});
diff --git a/api/src/posts/routes.ts b/api/src/posts/routes.ts
new file mode 100644
index 000000000..7a6934017
--- /dev/null
+++ b/api/src/posts/routes.ts
@@ -0,0 +1,101 @@
+import { Router, Request, Response } from 'express';
+import { body, validationResult } from 'express-validator';
+import { PrismaClient } from '@prisma/client';
+
+const prisma = new PrismaClient();
+const router = Router();
+
+const postValidationRules = [
+ body('title').notEmpty().withMessage('Title is required.'),
+];
+
+const createPostValidationRules = [
+ body('authorId').notEmpty().withMessage('Author ID is required.'),
+ ...postValidationRules,
+];
+
+const updatePostValidationRules = [
+ body('id').notEmpty().withMessage('ID is required.'),
+ ...postValidationRules,
+];
+
+const createPost = async (req: Request, res: Response) => {
+ const post = await prisma.post.create({
+ data: {
+ title: req.body.title,
+ content: req.body.content,
+ author: {
+ connect: {
+ id: req.body.authorId,
+ },
+ },
+ },
+ });
+
+ return post;
+}
+
+router.post('/', createPostValidationRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ createPost(req, res).then(async (post) => {
+ res.status(201).json(post);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.get('/', async (req: Request, res: Response) => {
+ const posts = await prisma.post.findMany();
+ res.json(posts);
+ await prisma.$disconnect();
+});
+
+router.get('/:id', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const post = await prisma.post.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ res.json(post);
+ await prisma.$disconnect();
+});
+
+router.put('/', updatePostValidationRules, async (req: Request, res: Response) => {
+ const post = await prisma.post.update({
+ where: {
+ id: req.body.id,
+ },
+ data: {
+ title: req.body.title,
+ content: req.body.content,
+ },
+ });
+
+ res.json(post);
+ await prisma.$disconnect();
+});
+
+router.delete('/:id', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const post = await prisma.post.delete({
+ where: {
+ id: id,
+ },
+ });
+
+ res.json(post);
+ await prisma.$disconnect();
+});
+
+const postsRouter = router;
+export default postsRouter;
+
diff --git a/api/src/resources/actions.ts b/api/src/resources/actions.ts
new file mode 100644
index 000000000..bb2725c05
--- /dev/null
+++ b/api/src/resources/actions.ts
@@ -0,0 +1,62 @@
+import { PrismaClient } from '@prisma/client';
+import { Request, Response } from 'express';
+
+const prisma = new PrismaClient();
+
+const createResource = async (req: Request, res: Response) => {
+ const { name, type, url } = req.body;
+
+ const resource = await prisma.resource.create({
+ data: {
+ name,
+ type,
+ url,
+ },
+ });
+
+ return res.json(resource);
+}
+
+const updateResource = async (req: Request, res: Response) => {
+ const { id, name, type, url } = req.body;
+
+ const resource = await prisma.resource.update({
+ where: {
+ id: id,
+ },
+ data: {
+ name,
+ type,
+ url,
+ },
+ });
+
+ return res.json(resource);
+}
+
+const updateResources = async (req: Request, res: Response) => {
+ const resources = req.body;
+
+ const updatedResources = await Promise.all(resources.map(
+ async (resource: { id: string, name: string, type: string, url: string}) => {
+ const { id, name, type, url } = resource;
+
+ const updatedResource = await prisma.resource.update({
+ where: {
+ id: id,
+ },
+ data: {
+ name,
+ type,
+ url,
+ },
+ });
+
+ return updatedResource;
+ }
+ ));
+
+ return res.json([...updatedResources]);
+}
+
+export { createResource, updateResource, updateResources }
\ No newline at end of file
diff --git a/api/src/resources/routes.ts b/api/src/resources/routes.ts
new file mode 100644
index 000000000..93c6dc851
--- /dev/null
+++ b/api/src/resources/routes.ts
@@ -0,0 +1,90 @@
+import { Router, Request, Response } from 'express';
+import { validationResult } from 'express-validator';
+import { PrismaClient } from '@prisma/client';
+import { createResource, updateResource, updateResources } from './actions';
+import { createRules, updateRules, updateManyRules } from './validation-rules';
+
+const prisma = new PrismaClient();
+const router = Router();
+
+// Resources CRUD
+router.post('/', createRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ createResource(req, res).then(async (resource) => {
+ res.status(201).json(resource);
+ await prisma.$disconnect();
+ }
+ ).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.get('/', async (req: Request, res: Response) => {
+ const resources = await prisma.resource.findMany({
+ orderBy: {
+ name: 'asc',
+ },
+ });
+ res.json(resources);
+ await prisma.$disconnect();
+});
+
+router.get('/:id', async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const resource = await prisma.resource.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!resource) {
+ res.status(404).send('Resource not found');
+ } else {
+ res.json(resource);
+ }
+
+ await prisma.$disconnect();
+});
+
+router.put('/:id', updateRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ updateResource(req, res).then(async (resource) => {
+ res.json(resource);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.put('/', updateManyRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ updateResources(req, res).then(async (resources) => {
+ res.json(resources);
+ await prisma.$disconnect();
+ }
+ ).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+
+const resourcesRouter = router;
+export default resourcesRouter;
diff --git a/api/src/resources/validation-rules.ts b/api/src/resources/validation-rules.ts
new file mode 100644
index 000000000..75f244f7f
--- /dev/null
+++ b/api/src/resources/validation-rules.ts
@@ -0,0 +1,25 @@
+import { body } from 'express-validator';
+
+const commonRules = [
+ body('name').notEmpty().withMessage('Name is required.'),
+];
+
+const createRules = [
+ ...commonRules,
+];
+
+const updateRules = [
+ ...commonRules,
+];
+
+const updateManyRules = [
+ body().isArray().withMessage('Body must be an array.'),
+ body('*.id').notEmpty().withMessage('Id is required.'),
+ body('*.name').notEmpty().withMessage('Name is required.'),
+];
+
+export {
+ createRules,
+ updateRules,
+ updateManyRules,
+};
\ No newline at end of file
diff --git a/api/src/routes.ts b/api/src/routes.ts
new file mode 100644
index 000000000..0b1830c2b
--- /dev/null
+++ b/api/src/routes.ts
@@ -0,0 +1,20 @@
+import { Router, Request, Response } from 'express';
+import componentsRouter from './components/routes';
+import postsRouter from './posts/routes';
+import resourcesRouter from './resources/routes';
+import tasksRouter from './tasks/routes';
+import usersRouter from './users/routes';
+
+const router = Router();
+
+router.get('/', (req: Request, res: Response) => {
+ res.send('Hello World');
+});
+
+router.use('/components', componentsRouter);
+router.use('/posts', postsRouter);
+router.use('/resources', resourcesRouter);
+router.use('/tasks', tasksRouter);
+router.use('/users', usersRouter);
+
+export default router;
diff --git a/api/src/tasks/model.ts b/api/src/tasks/model.ts
new file mode 100644
index 000000000..b9ec412b1
--- /dev/null
+++ b/api/src/tasks/model.ts
@@ -0,0 +1,6 @@
+export interface Task {
+ id: number;
+ title: string;
+ description: string;
+ completed: boolean;
+}
diff --git a/api/src/tasks/routes.ts b/api/src/tasks/routes.ts
new file mode 100644
index 000000000..22f7b208e
--- /dev/null
+++ b/api/src/tasks/routes.ts
@@ -0,0 +1,80 @@
+import { Router, Request, Response } from 'express';
+import { body, validationResult } from 'express-validator';
+import { Task } from './model'
+
+const router = Router();
+let tasks: Task[] = [];
+
+const taskValidationRules = [
+ body('title').notEmpty().isString().withMessage('Title is required.'),
+ body('description').isString(),
+ body('completed').isBoolean().withMessage('Completed must be either true or false.'),
+];
+
+router.post('/', taskValidationRules, (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ const task: Task = {
+ id: tasks.length + 1,
+ title: req.body.title,
+ description: req.body.description,
+ completed: false,
+ };
+
+ tasks.push(task);
+ res.status(201).json(task);
+});
+
+router.get('/', (req: Request, res: Response) => {
+ res.json(tasks);
+});
+
+router.get('/:id', (req: Request, res: Response) => {
+ const id = parseInt(req.params.id);
+ const task = tasks.find((task) => task.id === id);
+
+ if (!task) {
+ res.status(404).send('Task not found');
+ } else {
+ res.json(task);
+ }
+});
+
+router.put('/:id', taskValidationRules, (req: Request, res: Response) => {
+ const id = parseInt(req.params.id);
+ const task = tasks.find((task) => task.id === id);
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ if (!task) {
+ res.status(404).send('Task not found');
+ } else {
+ task.title = req.body.title || task.title;
+ task.description = req.body.description || task.description;
+ task.completed = req.body.completed || task.completed;
+
+ res.json(task);
+ }
+});
+
+router.delete('/:id', (req: Request, res: Response) => {
+ const id = parseInt(req.params.id);
+ const taskIndex = tasks.findIndex((task) => task.id === id);
+
+ if (taskIndex === -1) {
+ res.status(404).send('Task not found');
+ } else {
+ tasks.splice(taskIndex, 1);
+ res.status(204).send();
+ }
+});
+
+const tasksRouter = router;
+export default tasksRouter;
diff --git a/api/src/users/routes.ts b/api/src/users/routes.ts
new file mode 100644
index 000000000..1990c5a5d
--- /dev/null
+++ b/api/src/users/routes.ts
@@ -0,0 +1,106 @@
+import { Router, Request, Response } from 'express';
+import { body, validationResult } from 'express-validator';
+import { PrismaClient } from '@prisma/client';
+
+const prisma = new PrismaClient();
+const router = Router();
+
+const userValidationRules = [
+ body('email').optional().trim().isEmail().withMessage('Email must be a valid email address.'),
+];
+
+const createUserValidationRules = [
+ body('email').notEmpty().withMessage('Email is required.'),
+ ...userValidationRules,
+];
+
+const updateUserValidationRules = [
+ body('id').notEmpty().withMessage('ID is required.'),
+ ...userValidationRules,
+];
+
+const createUser = async (req: Request, res: Response) => {
+ const user = await prisma.user.create({
+ data: {
+ email: req.body.email,
+ name: req.body.name
+ },
+ });
+
+ return user;
+}
+
+router.post('/', createUserValidationRules, async (req: Request, res: Response) => {
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ createUser(req, res).then(async (user) => {
+ res.status(201).json(user);
+ await prisma.$disconnect();
+ }).catch(async (error) => {
+ console.error(error);
+ await prisma.$disconnect();
+ });
+});
+
+router.get('/', async (req: Request, res: Response) => {
+ const users = await prisma.user.findMany();
+ res.json(users);
+ await prisma.$disconnect();
+});
+
+router.get('/:id', async (req: Request, res: Response) => {
+ const { id } = req.params;
+
+ const user = await prisma.user.findUnique({
+ where: {
+ id: id,
+ },
+ });
+
+ if (!user) {
+ res.status(404).send('User not found');
+ } else {
+ res.json(user);
+ }
+
+ await prisma.$disconnect();
+});
+
+router.put('/:id', updateUserValidationRules, async (req: Request, res: Response) => {
+ const id = req.params.id;
+ const user = await prisma.user.findUnique({
+ where: {
+ id: id,
+ },
+ });
+ const errors = validationResult(req);
+
+ if (!errors.isEmpty()) {
+ return res.status(422).json({ errors: errors.array() });
+ }
+
+ if (!user) {
+ res.status(404).send('User not found');
+ } else {
+ const updatedUser = await prisma.user.update({
+ where: {
+ id: id,
+ },
+ data: {
+ email: req.body.email || user.email,
+ name: req.body.name || user.name
+ },
+ });
+
+ res.json(updatedUser);
+ }
+
+ await prisma.$disconnect();
+});
+
+const usersRouter = router;
+export default usersRouter;
\ No newline at end of file
diff --git a/api/src/utils/logger.ts b/api/src/utils/logger.ts
new file mode 100644
index 000000000..8229caccd
--- /dev/null
+++ b/api/src/utils/logger.ts
@@ -0,0 +1,33 @@
+import exp from 'constants';
+import { Request, Response } from 'express';
+
+export interface LoggerOptions {
+ method?: boolean;
+ url?: boolean;
+ headers?: boolean;
+ body?: boolean;
+ baseUrl?: boolean;
+ originalUrl?: boolean;
+ path?: boolean;
+ query?: boolean;
+ params?: boolean;
+ referer?: boolean;
+}
+
+export const logger = (req: Request, res: Response, options: LoggerOptions) => {
+ let log = '';
+ log += `${req.method} ${req.url}\n`;
+
+ if(options.method) log += `Method: ${req.method}\n`;
+ if(options.url) log += `URL: ${req.url}\n`;
+ if(options.headers) log += `Headers: ${req.headers}\n`;
+ if(options.body) log += `Body: ${req.body}\n`;
+ if(options.baseUrl) log += `BaseUrl: ${req.baseUrl}\n`;
+ if(options.originalUrl) log += `OriginalUrl: ${req.originalUrl}\n`;
+ if(options.path) log += `Path: ${req.path}\n`;
+ if(options.query) log += `Query: ${req.query}\n`;
+ if(options.params) log += `Params: ${req.params}\n`;
+ if(options.referer) log += `Referrer: ${req.headers.referer}\n`;
+
+ return log;
+}
diff --git a/api/tsconfig.json b/api/tsconfig.json
new file mode 100644
index 000000000..deaf0d37c
--- /dev/null
+++ b/api/tsconfig.json
@@ -0,0 +1,13 @@
+{
+ "compilerOptions": {
+ "target": "es6",
+ "module": "commonjs",
+ "outDir": "./dist",
+ "strict": true,
+ "esModuleInterop": true,
+ "forceConsistentCasingInFileNames": true,
+ "skipLibCheck": true
+ },
+ "include": ["src/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/aries-core/src/js/components/controls/ReverseAnchor.js b/aries-core/src/js/components/controls/ReverseAnchor.js
new file mode 100644
index 000000000..830af452d
--- /dev/null
+++ b/aries-core/src/js/components/controls/ReverseAnchor.js
@@ -0,0 +1,24 @@
+import React from 'react';
+import PropTypes from 'prop-types';
+import { Anchor } from 'grommet';
+import { FormPrevious } from 'grommet-icons';
+
+export const ReverseAnchor = React.forwardRef(
+ ({ href, label, ...rest }, ref) => {
+ return (
+ }
+ gap="hair"
+ {...rest}
+ />
+ );
+ },
+);
+
+ReverseAnchor.propTypes = {
+ href: PropTypes.string,
+ label: PropTypes.string.isRequired,
+};
diff --git a/aries-core/src/js/components/controls/index.d.ts b/aries-core/src/js/components/controls/index.d.ts
new file mode 100644
index 000000000..bcfd44751
--- /dev/null
+++ b/aries-core/src/js/components/controls/index.d.ts
@@ -0,0 +1,8 @@
+export interface ReverseAnchorProps {
+ href?: string;
+ label: string;
+}
+
+declare const ReverseAnchor: React.FC;
+
+export { ReverseAnchor };
diff --git a/aries-core/src/js/components/controls/index.js b/aries-core/src/js/components/controls/index.js
new file mode 100644
index 000000000..343e37938
--- /dev/null
+++ b/aries-core/src/js/components/controls/index.js
@@ -0,0 +1 @@
+export * from './ReverseAnchor';
diff --git a/aries-core/src/js/components/index.js b/aries-core/src/js/components/index.js
index e73559006..f66549e05 100644
--- a/aries-core/src/js/components/index.js
+++ b/aries-core/src/js/components/index.js
@@ -1,3 +1,4 @@
+export * from './controls';
export * from './core';
export * from './helpers';
export * from './layouts';
diff --git a/aries-core/src/js/components/layouts/ButtonGroup/ButtonGroup.js b/aries-core/src/js/components/layouts/ButtonGroup/ButtonGroup.js
index 651edf442..ac94b391d 100644
--- a/aries-core/src/js/components/layouts/ButtonGroup/ButtonGroup.js
+++ b/aries-core/src/js/components/layouts/ButtonGroup/ButtonGroup.js
@@ -6,7 +6,7 @@ export const ButtonGroup = ({ children, ...rest }) => {
const { buttonGroup } = useContext(ThemeContext);
return (
-
+
{children}
);
diff --git a/aries-core/src/js/components/layouts/FormChildObjects/ChildHeader.jsx b/aries-core/src/js/components/layouts/FormChildObjects/ChildHeader.jsx
new file mode 100644
index 000000000..391c66674
--- /dev/null
+++ b/aries-core/src/js/components/layouts/FormChildObjects/ChildHeader.jsx
@@ -0,0 +1,57 @@
+// ChildHeader.js
+import { useState } from 'react';
+import PropTypes from 'prop-types';
+import { Box, Header, Heading, Text } from 'grommet';
+import { Up, Down } from 'grommet-icons';
+
+export const ChildHeader = ({
+ collectionName,
+ index,
+ headingLevel,
+ name,
+ open,
+ summary,
+ ...rest
+}) => {
+ const [background, setBackground] = useState(null);
+ const borderStyle = { side: 'top', color: 'border-weak' };
+
+ return (
+ setBackground('background-contrast')}
+ onMouseLeave={() => setBackground(null)}
+ pad="small"
+ {...rest}
+ >
+
+
+ {name || `New ${collectionName} (undefined)`}
+
+ {summary && {summary}}
+
+ {open ? (
+
+ ) : (
+
+ )}
+
+ );
+};
+
+ChildHeader.propTypes = {
+ annotationIds: PropTypes.shape({
+ container: PropTypes.string,
+ label: PropTypes.string,
+ icon: PropTypes.string,
+ valuesSummary: PropTypes.string,
+ }),
+ collectionName: PropTypes.string,
+ index: PropTypes.number,
+ headingLevel: PropTypes.number,
+ name: PropTypes.string,
+ open: PropTypes.bool,
+ summary: PropTypes.string,
+};
diff --git a/aries-core/src/js/components/layouts/FormChildObjects/FormChildObject.jsx b/aries-core/src/js/components/layouts/FormChildObjects/FormChildObject.jsx
new file mode 100644
index 000000000..f73859881
--- /dev/null
+++ b/aries-core/src/js/components/layouts/FormChildObjects/FormChildObject.jsx
@@ -0,0 +1,96 @@
+// FormChildObject.js
+import { useState } from 'react';
+import PropTypes from 'prop-types';
+import { Box, Button, Collapsible } from 'grommet';
+import { Trash } from 'grommet-icons';
+import { ChildHeader } from './ChildHeader';
+
+// using value names from summarize prop, builds the summary message
+// to be displayed beneath the heading
+const getSummaryString = (values, keys) => {
+ let summary = '';
+ const summarize = new Map();
+ for (let i = 0; i <= keys.length - 1; i += 1) {
+ if (typeof keys[i] === 'object') {
+ summarize.set(keys[i].name, keys[i].showName !== false);
+ } else {
+ summarize.set(keys[i], true);
+ }
+ }
+
+ // create flat array of just keys from Map
+ const flattenedKeys = [...summarize.keys()];
+ Object.entries(values).forEach(([key, value]) => {
+ summary +=
+ flattenedKeys.includes(key) &&
+ (value.length > 0 || typeof value === 'number')
+ ? // if the showName value for a key is true, include it
+ `${summarize.get(key) ? `${key}: ` : ''}${value}, `
+ : '';
+ });
+ summary = summary.slice(0, -2);
+ return summary;
+};
+
+export const FormChildObject = ({
+ children,
+ collectionName,
+ index,
+ headingLevel,
+ name,
+ onClick: onClickProp,
+ onRemove,
+ open: openProp = false,
+ summarize,
+ values,
+}) => {
+ const [open, setOpen] = useState(openProp);
+ const valuesSummary = summarize ? getSummaryString(values, summarize) : null;
+ const onClick = () => onClickProp || setOpen(!open);
+
+ return (
+ <>
+
+
+ {children}
+
+ {onRemove && (
+ }
+ aria-label={`Remove ${name || index}`}
+ onClick={() => onRemove(index)}
+ />
+ )}
+
+
+ >
+ );
+};
+
+FormChildObject.propTypes = {
+ children: PropTypes.node.isRequired,
+ collectionName: PropTypes.string.isRequired,
+ index: PropTypes.number.isRequired,
+ headingLevel: PropTypes.number.isRequired,
+ name: PropTypes.string,
+ onClick: PropTypes.func,
+ onRemove: PropTypes.func,
+ open: PropTypes.bool,
+ summarize: PropTypes.arrayOf(
+ PropTypes.oneOfType([
+ PropTypes.string,
+ PropTypes.shape({ name: PropTypes.string, showName: PropTypes.bool }),
+ ]),
+ ),
+ values: PropTypes.object.isRequired,
+};
diff --git a/aries-core/src/js/components/layouts/FormChildObjects/FormChildObjects.jsx b/aries-core/src/js/components/layouts/FormChildObjects/FormChildObjects.jsx
new file mode 100644
index 000000000..71fe93aa1
--- /dev/null
+++ b/aries-core/src/js/components/layouts/FormChildObjects/FormChildObjects.jsx
@@ -0,0 +1,92 @@
+// FormChildObjects.js
+import PropTypes from 'prop-types';
+import { Box, Button } from 'grommet';
+import { ButtonGroup } from 'aries-core';
+import { FormChildObject } from './FormChildObject';
+
+export const FormChildObjects = ({
+ collection,
+ fields,
+ headingLevel,
+ onAdd,
+ onRemove,
+ onRemoveAll,
+ primaryKey,
+ required,
+ summarize,
+ values,
+}) => {
+ return (
+
+ {values?.length
+ ? values.map((obj, index) => (
+
+ {Object.entries(obj).map(([key, value]) => {
+ return fields[key]
+ ? fields[key]({ key, value, primaryKey, index })
+ : null;
+ })}
+
+ ))
+ : null}
+ {collection ? (
+
+ {values?.length >= 2 && !required && (
+
+ )}
+
+
+ ) : null}
+
+ );
+};
+
+FormChildObjects.propTypes = {
+ collection: PropTypes.shape({
+ // Name of the collection of objects e.g. "servers"
+ name: PropTypes.string.isRequired,
+ // Name of a single object e.g. "server"
+ itemName: PropTypes.string.isRequired,
+ // Name of parent object e.g. "group", "cluster"
+ parentName: PropTypes.string,
+ }).isRequired,
+ fields: PropTypes.objectOf(PropTypes.func).isRequired,
+ headingLevel: PropTypes.number, // Semantic heading headingLevel 1-6
+ onAdd: PropTypes.func,
+ onRemove: PropTypes.func,
+ onRemoveAll: PropTypes.func,
+ primaryKey: PropTypes.string,
+ required: PropTypes.bool,
+ summarize: PropTypes.arrayOf(PropTypes.string),
+ values: PropTypes.arrayOf(PropTypes.object).isRequired,
+};
diff --git a/aries-core/src/js/components/layouts/FormChildObjects/index.js b/aries-core/src/js/components/layouts/FormChildObjects/index.js
new file mode 100644
index 000000000..fb89d061e
--- /dev/null
+++ b/aries-core/src/js/components/layouts/FormChildObjects/index.js
@@ -0,0 +1 @@
+export * from './FormChildObjects';
diff --git a/aries-core/src/js/components/layouts/Panel/Panel.jsx b/aries-core/src/js/components/layouts/Panel/Panel.jsx
new file mode 100644
index 000000000..9d4625d9f
--- /dev/null
+++ b/aries-core/src/js/components/layouts/Panel/Panel.jsx
@@ -0,0 +1,8 @@
+import React from 'react';
+import { Box } from 'grommet';
+
+export const Panel = ({ ...rest }) => {
+ return (
+
+ );
+};
diff --git a/aries-core/src/js/components/layouts/Panel/index.js b/aries-core/src/js/components/layouts/Panel/index.js
new file mode 100644
index 000000000..8960d84f6
--- /dev/null
+++ b/aries-core/src/js/components/layouts/Panel/index.js
@@ -0,0 +1 @@
+export * from './Panel';
diff --git a/aries-core/src/js/components/layouts/index.js b/aries-core/src/js/components/layouts/index.js
index 70b1d11dc..3584c43f1 100644
--- a/aries-core/src/js/components/layouts/index.js
+++ b/aries-core/src/js/components/layouts/index.js
@@ -1,5 +1,7 @@
export * from './ActionMenu';
export * from './ButtonGroup';
export * from './EmptyState';
+export * from './FormChildObjects';
export * from './Layer';
export * from './ModalDialog';
+export * from './Panel';
diff --git a/aries-core/src/js/index.js b/aries-core/src/js/index.js
index 07635cbbc..021480a9d 100644
--- a/aries-core/src/js/index.js
+++ b/aries-core/src/js/index.js
@@ -1 +1,3 @@
+'use client';
+
export * from './components';
diff --git a/design-system-manager/.eslintrc.json b/design-system-manager/.eslintrc.json
new file mode 100644
index 000000000..4d765f281
--- /dev/null
+++ b/design-system-manager/.eslintrc.json
@@ -0,0 +1,3 @@
+{
+ "extends": ["next/core-web-vitals", "prettier"]
+}
diff --git a/design-system-manager/.gitignore b/design-system-manager/.gitignore
new file mode 100644
index 000000000..fd3dbb571
--- /dev/null
+++ b/design-system-manager/.gitignore
@@ -0,0 +1,36 @@
+# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
+
+# dependencies
+/node_modules
+/.pnp
+.pnp.js
+.yarn/install-state.gz
+
+# testing
+/coverage
+
+# next.js
+/.next/
+/out/
+
+# production
+/build
+
+# misc
+.DS_Store
+*.pem
+
+# debug
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+
+# local env files
+.env*.local
+
+# vercel
+.vercel
+
+# typescript
+*.tsbuildinfo
+next-env.d.ts
diff --git a/design-system-manager/README.md b/design-system-manager/README.md
new file mode 100644
index 000000000..c4033664f
--- /dev/null
+++ b/design-system-manager/README.md
@@ -0,0 +1,36 @@
+This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
+
+## Getting Started
+
+First, run the development server:
+
+```bash
+npm run dev
+# or
+yarn dev
+# or
+pnpm dev
+# or
+bun dev
+```
+
+Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
+
+You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
+
+This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
+
+## Learn More
+
+To learn more about Next.js, take a look at the following resources:
+
+- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
+- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
+
+You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
+
+## Deploy on Vercel
+
+The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
+
+Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
diff --git a/design-system-manager/next.config.js b/design-system-manager/next.config.js
new file mode 100644
index 000000000..767719fc4
--- /dev/null
+++ b/design-system-manager/next.config.js
@@ -0,0 +1,4 @@
+/** @type {import('next').NextConfig} */
+const nextConfig = {}
+
+module.exports = nextConfig
diff --git a/design-system-manager/package.json b/design-system-manager/package.json
new file mode 100644
index 000000000..653baf3d2
--- /dev/null
+++ b/design-system-manager/package.json
@@ -0,0 +1,23 @@
+{
+ "name": "design-system-manager",
+ "version": "0.1.0",
+ "private": true,
+ "scripts": {
+ "dev": "next dev",
+ "build": "next build",
+ "start": "next start",
+ "lint": "next lint"
+ },
+ "dependencies": {
+ "next": "14.0.3"
+ },
+ "devDependencies": {
+ "@types/node": "^20",
+ "@types/react": "^18",
+ "@types/react-dom": "^18",
+ "eslint": "^8",
+ "eslint-config-next": "14.0.3",
+ "eslint-config-prettier": "^9.1.0",
+ "typescript": "^5"
+ }
+}
diff --git a/design-system-manager/public/next.svg b/design-system-manager/public/next.svg
new file mode 100644
index 000000000..5174b28c5
--- /dev/null
+++ b/design-system-manager/public/next.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/design-system-manager/public/vercel.svg b/design-system-manager/public/vercel.svg
new file mode 100644
index 000000000..d2f842227
--- /dev/null
+++ b/design-system-manager/public/vercel.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/Collection.tsx b/design-system-manager/src/app/components/Collection.tsx
new file mode 100644
index 000000000..50c013cfb
--- /dev/null
+++ b/design-system-manager/src/app/components/Collection.tsx
@@ -0,0 +1,17 @@
+import { Data } from 'grommet';
+import type { LevelType } from '@/utilities/types';
+import { Pane } from '../../components/Pane.tsx';
+import { CardGroup } from './CollectionViews.tsx';
+
+export const Collection = (
+ {data, level}: {data: [], level: LevelType}
+) => {
+ return (
+
+
+ {/* */}
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/CollectionViews.tsx b/design-system-manager/src/app/components/CollectionViews.tsx
new file mode 100644
index 000000000..5114d6396
--- /dev/null
+++ b/design-system-manager/src/app/components/CollectionViews.tsx
@@ -0,0 +1,37 @@
+'use client';
+
+import Link from "next/link";
+import { Box, Card, CardBody, Cards, List, Heading, Paragraph } from "grommet";
+import type { LevelType } from "@/utilities/types";
+
+export const ComponentList = () => {
+ return (
+
+ {({ name }) => (
+
+ {name}
+
+ )}
+
+)};
+
+export const CardGroup = ({level, ...rest} : {level: LevelType}) => {
+ return (
+
+ {(item, index) => {
+ const DELAY = 75;
+ const DURATION = 750;
+
+ return(
+
+
+
+ {item.name}
+ {item.description}
+
+
+
+ );
+ }}
+
+)}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/Insights.tsx b/design-system-manager/src/app/components/Insights.tsx
new file mode 100644
index 000000000..c37e613d5
--- /dev/null
+++ b/design-system-manager/src/app/components/Insights.tsx
@@ -0,0 +1,15 @@
+import {Box} from 'grommet';
+import type {LevelType} from '@/utilities/types'
+import { Pane } from '../../components/Pane.tsx';
+
+export const Insights = ({ level }: {level: LevelType}) => {
+ return (
+
+
+ KPI a
+ KPI b
+ KPI c
+
+
+ )
+}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/[id]/Design.tsx b/design-system-manager/src/app/components/[id]/Design.tsx
new file mode 100644
index 000000000..e69de29bb
diff --git a/design-system-manager/src/app/components/[id]/Detail/Edit.tsx b/design-system-manager/src/app/components/[id]/Detail/Edit.tsx
new file mode 100644
index 000000000..9addf29c6
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Detail/Edit.tsx
@@ -0,0 +1,136 @@
+'use client';
+
+import { useState, ReactNode } from 'react';
+import {
+ Box,
+ Button,
+ Form,
+ FormField,
+ Header,
+ Heading,
+ Layer,
+ Select,
+ TextArea,
+ TextInput
+} from 'grommet';
+import { Close } from 'grommet-icons';
+import { ButtonGroup } from 'aries-core';
+import type { ComponentType } from "@/utilities/types";
+import { updateComponent } from "../actions.ts";
+
+interface InputMap {
+ // eslint-disable-next-line no-unused-vars
+ [key: string]: ({ ...rest }: { [x: string]: any }) => ReactNode | null;
+}
+
+const INPUT_MAP: InputMap = {
+ id: ({...rest}) => ,
+ description: ({...rest}) => ,
+ keywords: ({...rest}) => ,
+ status: ({...rest}) => ,
+ createdAt: ({...rest}) => ,
+ updatedAt: ({...rest}) => ,
+};
+
+const DATATYPE_MAP: InputMap = {
+ string: ({...rest}) => ,
+ number: ({...rest}) => ,
+ object: ({value, ...rest}) => {
+ let result = ;
+ if (Array.isArray(value)) {
+ result =
+ }
+ return result;
+ },
+};
+
+export const Edit = ({ component, onClose } : { component: ComponentType, onClose: () => void }) => {
+ const [currentData, setCurrentData] = useState(component);
+ const [tempData, setTempData] = useState(currentData);
+ const [saving, setSaving] = useState(false);
+ const [success, setSuccess] = useState(false);
+
+ const handleSave = (formValue: ComponentType) => {
+ const SUCCESS_ANIMATION_DELAY = 1000;
+
+ setSaving(true);
+ updateComponent(formValue)
+ .then((updatedComponent) => { setCurrentData(updatedComponent); })
+ .then(() => {
+ setSaving(false);
+ setSuccess(true);
+ })
+ .then(() => {
+ setTimeout(() => { onClose(); }, SUCCESS_ANIMATION_DELAY);
+ });
+ }
+
+ const handleCancel = () => {
+ setTempData(currentData);
+ onClose();
+ }
+
+ return (
+
+
+
+ {/* eslint-disable-next-line react/jsx-no-useless-fragment */}
+ <>>
+ } onClick={handleCancel} />
+
+
+ Edit {component.name} detail
+
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/[id]/Detail/Editable.tsx b/design-system-manager/src/app/components/[id]/Detail/Editable.tsx
new file mode 100644
index 000000000..394c367dc
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Detail/Editable.tsx
@@ -0,0 +1,59 @@
+'use client';
+
+import { useEffect, useState, ReactNode } from 'react';
+import { Button } from 'grommet';
+import { Close, Edit as EditIcon } from 'grommet-icons';
+import { Pane } from '../../../../components/Pane.tsx';
+import { getComponent } from '../actions.ts';
+import { Edit } from './Edit.tsx';
+
+export const Editable = (
+ { children, id } :
+ {children: ReactNode, id: string}
+) => {
+ const [data, setData] = useState({id: '', name: ''});
+ const [edit, setEdit] = useState(false);
+
+ useEffect(() => {
+ if (!edit) {
+ const fetchData = async () => {
+ const component = await getComponent(id);
+ setData(component);
+ };
+ fetchData();
+ }
+ }, [id, edit]);
+
+ const content = !edit ? (
+ children
+ ) : (
+ setEdit(false)} />
+ );
+
+ const EditButton = () => {
+ return (
+ // eslint-disable-next-line grommet/button-icon-a11ytitle
+
+ ) : (
+
+ )
+ }
+ onClick={() => setEdit(!edit)}
+ />
+ );
+ }
+
+ return (
+ }
+ >
+ {content}
+
+ );
+};
diff --git a/design-system-manager/src/app/components/[id]/Detail/Properties.tsx b/design-system-manager/src/app/components/[id]/Detail/Properties.tsx
new file mode 100644
index 000000000..d2467b1b8
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Detail/Properties.tsx
@@ -0,0 +1,18 @@
+import { NameValueList, NameValuePair } from "grommet";
+import { ComponentType } from "@/utilities/types";
+import { getComponent } from "../actions";
+
+export const Properties = async ({ id } : { id: string }) => {
+ const component: ComponentType = await getComponent(id);
+
+ return (
+
+ {component ? Object.entries(component).map(([name, value]) => (
+
+ {`${typeof value === 'object' ? JSON.stringify(value) : value}`}
+
+ ))
+ : null}
+
+ );
+}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/[id]/Detail/index.tsx b/design-system-manager/src/app/components/[id]/Detail/index.tsx
new file mode 100644
index 000000000..907af5ab9
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Detail/index.tsx
@@ -0,0 +1,10 @@
+import { Properties } from "./Properties.tsx";
+import { Editable } from './Editable.tsx';
+
+export const Detail = ({id}:{id: string}) => {
+ return (
+
+
+
+ );
+}
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/[id]/References.tsx b/design-system-manager/src/app/components/[id]/References.tsx
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/References.tsx
@@ -0,0 +1 @@
+
diff --git a/design-system-manager/src/app/components/[id]/Resources/Edit.tsx b/design-system-manager/src/app/components/[id]/Resources/Edit.tsx
new file mode 100644
index 000000000..a4271c5c7
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Resources/Edit.tsx
@@ -0,0 +1,228 @@
+'use client';
+
+import { useState, JSX } from 'react';
+import { Box, Button, Form, FormField, Notification, Select, TextArea, TextInput } from 'grommet';
+import { ButtonGroup, FormChildObjects } from 'aries-core';
+import type { LevelType, ResourceType } from '@/utilities/types.d.ts';
+import { updateResources } from '../actions';
+
+const RESOURCE_TYPES = [
+ 'Code',
+ 'Documentation',
+ 'Design'
+];
+
+interface InputMap {
+ [key: string]: ({ ...rest }: { [x: string]: any }) => JSX.Element | null;
+}
+
+const INPUT_MAP = {
+ name: ({ key, index, ...rest } : InputMap) => (
+
+
+
+ ),
+ type: ({ key, index, ...rest } : InputMap) => (
+
+
+
+ ),
+ url: ({ key, index, ...rest } : InputMap) => (
+
+
+
+ ),
+}
+
+const resourceTemplate = {
+ name: '',
+ type: '',
+ url: '',
+};
+
+const touchedValues = (
+ curr: { [key: string]: any },
+ acc: { [key: string]: any },
+ keys: string[],
+ index: number
+) => {
+ if (index === keys.length - 1) {
+ acc[keys[index]] = curr[keys[index]];
+ } else {
+ acc[keys[index]] = { ...acc[keys[index]] };
+ touchedValues(curr[keys[index]], acc[keys[index]], keys, index + 1);
+ }
+ return acc;
+}
+
+export const Edit = (
+ {
+ resources,
+ componentId,
+ onClose,
+ level
+ } : {
+ resources: ResourceType[],
+ componentId: string,
+ onClose: () => void,
+ level: LevelType
+ }) => {
+ const [formValue, setFormValue] = useState({resources});
+ const [saving, setSaving] = useState(false);
+ const [success, setSuccess] = useState(false);
+ const [validationError, setValidationError] = useState({title: '', message: {}});
+
+ const handleAdd = () => {
+ const nextResources = [...formValue.resources, { ...resourceTemplate }];
+ setFormValue({ ...formValue, resources: nextResources });
+ };
+
+ const handleRemove = (index: number) => {
+ if (formValue.resources?.length > 0) {
+ const nextResources = [...formValue.resources];
+ nextResources.splice(index, 1);
+ setFormValue({ ...formValue, resources: nextResources });
+ }
+ };
+
+ const handleRemoveAll = () => {
+ setFormValue({ ...formValue, resources: [] });
+ }
+
+ const onChange = (value: { resources: ResourceType[] }) => {
+ setFormValue(value);
+ };
+
+ const onSubmit = ({
+ value,
+ touched
+ } : {
+ value: {resources: ResourceType[]},
+ touched: {}
+ }) => {
+ const SUCCESS_ANIMATION_DELAY = 1000;
+
+ const modifiedValues = {
+ resources: [] as ResourceType[]
+ };
+
+ // Isolate touched values from untouched.
+ Object.keys(touched).forEach((key) => {
+ // Split the key by '[]' and '.'.
+ const regex =/\[(.*?)\]\./;
+ const keys = key.split(regex);
+ touchedValues(value, modifiedValues, keys, 0);
+ });
+
+ // Add the resource id to the modifiedValues object and convert to an array.
+ modifiedValues.resources = Object.entries(modifiedValues.resources)
+ .map((resource) => {
+ const index = parseInt(resource[0], 10);
+ modifiedValues.resources[index].id = value.resources[index].id;
+ return resource[1];
+ });
+
+ setSaving(true);
+
+ updateResources(modifiedValues.resources, componentId)
+ .then((updatedResources) => {
+ if (updatedResources.errors) {
+ throw new Error('Validation rules were not met.', {cause: updatedResources});
+ }
+ setFormValue({...formValue, resources: updatedResources});
+ })
+ .then(() => {
+ setSaving(false);
+ setSuccess(true);
+ })
+ .then(() => {
+ setTimeout(() => {
+ onClose();
+ setSuccess(false);
+ }, SUCCESS_ANIMATION_DELAY);
+ }).catch((error) => {
+ console.error(error, 'Validation rules:', error.cause.errors);
+ setValidationError({title: error.message, message: error.cause.errors});
+ setSaving(false);
+ setSuccess(false);
+ }
+ );
+ };
+
+ const onReset = () => {
+ setFormValue({resources});
+ onClose();
+ }
+
+ return (
+
+ );
+}
+
diff --git a/design-system-manager/src/app/components/[id]/Resources/Editable.tsx b/design-system-manager/src/app/components/[id]/Resources/Editable.tsx
new file mode 100644
index 000000000..7f7e216d1
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Resources/Editable.tsx
@@ -0,0 +1,45 @@
+'use client';
+
+import { useState } from 'react';
+import { Button } from 'grommet';
+import { Close, Edit as EditIcon } from 'grommet-icons';
+import type { LevelType, ResourceType } from '@/utilities/types';
+import { Pane } from '../../../../components/Pane.tsx';
+import { Edit } from './Edit.tsx';
+
+export const Editable = (
+ { children, level, componentId, resources } :
+ { children: any, level: LevelType, componentId: string, resources: ResourceType[] }
+) => {
+ const [edit, setEdit] = useState(false);
+ const toggleEdit = () => setEdit(!edit);
+
+ const content = !edit ?
+ children
+ : (
+ setEdit(false)}
+ />
+ );
+
+ return (
+ :
+
+ }
+ onClick={toggleEdit}
+ />}
+ >
+ {content}
+
+ );
+}
+
diff --git a/design-system-manager/src/app/components/[id]/Resources/ResourcesList.tsx b/design-system-manager/src/app/components/[id]/Resources/ResourcesList.tsx
new file mode 100644
index 000000000..e8100f729
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Resources/ResourcesList.tsx
@@ -0,0 +1,65 @@
+'use client';
+
+import { Box, Button, List, Text } from 'grommet';
+import { Document, Figma, Grommet, ShareRounded } from 'grommet-icons';
+import { TextEmphasis } from 'aries-core';
+
+
+const RESOURCE_MAP = {
+ name: {
+ figma: {
+ icon: ({ ...props }) => ,
+ },
+ 'grommet docs': {
+ icon: ({ ...props }) => ,
+ },
+ },
+ type: {
+ documentation: {
+ icon: ({ ...props }) => ,
+ },
+ },
+};
+
+export const ResourcesList = ({ ...rest }) => (
+
+ {(resource) => {
+ const icon =
+ RESOURCE_MAP.name[resource.name.toLowerCase()]?.icon ||
+ RESOURCE_MAP.type[resource.type.toLowerCase()]?.icon ||
+ (() => null);
+
+ return (
+
+ );
+ }}
+
+);
diff --git a/design-system-manager/src/app/components/[id]/Resources/index.tsx b/design-system-manager/src/app/components/[id]/Resources/index.tsx
new file mode 100644
index 000000000..60ce8967a
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/Resources/index.tsx
@@ -0,0 +1,18 @@
+import type { LevelType } from '@/utilities/types';
+import { getResources } from '../actions.ts';
+import { Editable } from './Editable.tsx';
+import { ResourcesList } from './ResourcesList.tsx';
+
+
+export const Resources = async (
+ { id, level } :
+ { id: string, level: LevelType }
+) => {
+ const resources = await getResources(id);
+
+ return (
+
+
+
+ );
+}
diff --git a/design-system-manager/src/app/components/[id]/Usage.tsx b/design-system-manager/src/app/components/[id]/Usage.tsx
new file mode 100644
index 000000000..e69de29bb
diff --git a/design-system-manager/src/app/components/[id]/actions.ts b/design-system-manager/src/app/components/[id]/actions.ts
new file mode 100644
index 000000000..b4d8abd44
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/actions.ts
@@ -0,0 +1,147 @@
+'use server';
+
+import { revalidatePath } from 'next/cache';
+import type { ComponentType, ResourceType } from '@/utilities/types.d.ts';
+
+class ValidationError extends Error {
+ validation: { errors: any; };
+
+ constructor(message: string, validation: { errors: any }) {
+ super(message);
+ this.name = 'ValidationError';
+ this.validation = validation;
+ }
+}
+
+export async function getComponent(id: string) {
+ const url = `${process.env.API_URL}/components/${id}`;
+ const options = {
+ method: 'GET',
+ headers: { 'Content-Type': 'application/json' },
+ };
+
+ try {
+ const res = await fetch(url, options);
+ return res.json();
+ }
+ catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function updateComponent(component: ComponentType) {
+ const path = `/components/${component.id}`;
+ const url = `${process.env.API_URL}${path}`;
+ const options = {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(component),
+ };
+
+ try {
+ const res = await fetch(url, options);
+ revalidatePath(path);
+ return res.json();
+ }
+ catch (error) {
+ console.error(error);
+ return null;
+ }
+
+}
+
+export async function getResources(id: string) {
+ const url = `${process.env.API_URL}/components/${id}/resources`;
+ const options = {
+ method: 'GET',
+ headers: { 'Content-Type': 'application/json' },
+ };
+
+ try {
+ const res = await fetch(url, options);
+ return res.json();
+ }
+ catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function addResource(id: string, resource: ResourceType) {
+ const url = `${process.env.API_URL}/components/${id}/resources`;
+ const options = {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(resource),
+ };
+
+ try {
+ const res = await fetch(url, options);
+ return res.json();
+ }
+ catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function updateResource(resource: ResourceType) {
+ const path = `/resources/${resource.id}`;
+ const url = `${process.env.API_URL}${path}`;
+ const options = {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(resource),
+ };
+
+ try {
+ const res = await fetch(url, options);
+ revalidatePath(path);
+ return res.json();
+ }
+ catch (error) {
+ console.error(error);
+ return null;
+ }
+}
+
+export async function updateResources(
+ resourcesProp: ResourceType[],
+ componentId: string)
+ {
+ const path = '/resources';
+ const url = `${process.env.API_URL}${path}`;
+
+ const resources = resourcesProp.map(resource => {
+ return {
+ id: resource.id,
+ name: resource.name,
+ type: typeof resource.type === 'object' ?
+ resource.type.value : resource.type,
+ url: resource.url,
+ };
+ });
+
+ const options = {
+ method: 'PUT',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify(resources),
+ };
+
+ try {
+ const res = await fetch(url, options);
+ if (res.status === 422) {
+ const validation = await res.json();
+ throw new ValidationError('Validation error', validation);
+ }
+ revalidatePath(path);
+ if (componentId) revalidatePath(`/components/${componentId}/resources`);
+ return res.json();
+ }
+ catch (error: any) {
+ console.error(error);
+ return error.validation;
+ }
+}
+
diff --git a/design-system-manager/src/app/components/[id]/layout.tsx b/design-system-manager/src/app/components/[id]/layout.tsx
new file mode 100644
index 000000000..fbfb5d2d4
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/layout.tsx
@@ -0,0 +1,7 @@
+import React from 'react';
+
+const ComponentLayout = ({ children }: { children: React.ReactNode }) => (
+ children
+);
+
+export default ComponentLayout;
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/[id]/page.tsx b/design-system-manager/src/app/components/[id]/page.tsx
new file mode 100644
index 000000000..e40e7d2db
--- /dev/null
+++ b/design-system-manager/src/app/components/[id]/page.tsx
@@ -0,0 +1,56 @@
+import { Suspense } from 'react';
+import Link from 'next/link';
+import { Box, Heading, PageHeader } from 'grommet';
+import { Panel, ReverseAnchor } from 'aries-core';
+import type { ComponentType } from '@/utilities/types';
+import { Detail } from './Detail/index.tsx';
+import { Resources } from './Resources/index.tsx';
+import { getComponent } from './actions.ts';
+
+
+const Component = async ({
+ params,
+}: {
+ params: { id: string };
+}) => {
+ const component: ComponentType = await getComponent(params.id);
+
+ return (
+ <>
+
+
+ }
+ />
+
+
+
+
+
+
+ Design
+ Anatomy
+ Interactive states
+ Color
+ Behaviors
+
+
+ Usage
+ Modifiers and configurations
+ Use case examples
+
+
+ References
+ Documentation
+ Research
+ Design criteria
+ Design rationale
+
+
+ >
+ );
+};
+
+export default Component;
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/layout.tsx b/design-system-manager/src/app/components/layout.tsx
new file mode 100644
index 000000000..f8ff74008
--- /dev/null
+++ b/design-system-manager/src/app/components/layout.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import { Page, PageContent } from 'grommet';
+
+const ComponentsLayout = ({ children }: { children: React.ReactNode }) => (
+
+
+ {children}
+
+
+);
+
+export default ComponentsLayout;
\ No newline at end of file
diff --git a/design-system-manager/src/app/components/page.tsx b/design-system-manager/src/app/components/page.tsx
new file mode 100644
index 000000000..573705d0e
--- /dev/null
+++ b/design-system-manager/src/app/components/page.tsx
@@ -0,0 +1,36 @@
+import Link from 'next/link';
+import { Grid, PageHeader } from 'grommet';
+import { ReverseAnchor } from 'aries-core';
+import { Collection } from './Collection.tsx'
+import { Insights } from './Insights.tsx';
+
+async function getComponents() {
+ const res = await fetch(`${process.env.API_URL}/components`);
+ return res.json();
+}
+
+const Page = async () => {
+ const components = await getComponents();
+
+ return (
+ <>
+
+
+
+ }
+ />
+
+
+
+
+ >
+)};
+
+export default Page;
\ No newline at end of file
diff --git a/design-system-manager/src/app/favicon.ico b/design-system-manager/src/app/favicon.ico
new file mode 100644
index 000000000..c78080c91
Binary files /dev/null and b/design-system-manager/src/app/favicon.ico differ
diff --git a/design-system-manager/src/app/layout.tsx b/design-system-manager/src/app/layout.tsx
new file mode 100644
index 000000000..06e62af3e
--- /dev/null
+++ b/design-system-manager/src/app/layout.tsx
@@ -0,0 +1,49 @@
+import React from 'react'
+import type { Metadata } from 'next'
+import { Avatar, Footer, Grommet, Header, Main, SkipLink, SkipLinkTarget, SkipLinks, Text } from 'grommet';
+import { hpe } from '../themes/hpe.ts'
+
+export const metadata: Metadata = {
+ title: {
+ template: '%s | HPE Design System Manager',
+ default: 'HPE Design System Manager'
+ },
+ description: 'Manage design system assets and supporting resources.',
+}
+
+export default function RootLayout({
+ children,
+}: {
+ children: React.ReactNode
+}) {
+ return (
+
+
+
+
+
+
+
+ HPE Design System Manager
+
+
+
+
+ {children}
+
+
+
+
+
+ )
+}
diff --git a/design-system-manager/src/app/page.tsx b/design-system-manager/src/app/page.tsx
new file mode 100644
index 000000000..dabffa40f
--- /dev/null
+++ b/design-system-manager/src/app/page.tsx
@@ -0,0 +1,35 @@
+import Link from 'next/link'
+import { Box, Card, CardHeader, Heading, Page, PageContent, PageHeader, Text } from 'grommet'
+
+export default function Home() {
+ return (
+
+
+
+
+
+
+
+
+
+ Manage
+ components
+
+
+
+
+
+
+
+
+ )
+}
diff --git a/design-system-manager/src/components/Pane.tsx b/design-system-manager/src/components/Pane.tsx
new file mode 100644
index 000000000..58adc9d2c
--- /dev/null
+++ b/design-system-manager/src/components/Pane.tsx
@@ -0,0 +1,36 @@
+import React from 'react';
+import { Box, Header, Heading } from 'grommet';
+import type { LevelType } from '@/utilities/types';
+
+export const Pane = ({
+ actions,
+ children,
+ heading,
+ level,
+ skeleton,
+ ...boxProps
+}: {
+ actions?: React.ReactNode,
+ children: React.ReactNode,
+ heading: string | React.ReactNode,
+ level: LevelType,
+ skeleton?: boolean,
+} ) => {
+ return (
+
+
+ {heading}
+ {actions}
+
+
+ {children}
+
+
+ );
+}
\ No newline at end of file
diff --git a/design-system-manager/src/themes/hpe.ts b/design-system-manager/src/themes/hpe.ts
new file mode 100644
index 000000000..ba7c71bbb
--- /dev/null
+++ b/design-system-manager/src/themes/hpe.ts
@@ -0,0 +1,3 @@
+'use client';
+
+export * from 'grommet-theme-hpe';
\ No newline at end of file
diff --git a/design-system-manager/src/utilities/types.d.ts b/design-system-manager/src/utilities/types.d.ts
new file mode 100644
index 000000000..c720ae25e
--- /dev/null
+++ b/design-system-manager/src/utilities/types.d.ts
@@ -0,0 +1,21 @@
+export interface ComponentType {
+ id: string;
+ name: string;
+ status?: string;
+ state?: string;
+ description?: string;
+ keywords?: string[];
+}
+
+export type LevelType = 1 | 2 | 3 | 4 | 5 | 6;
+
+type ResourceTypeType = 'Code' | 'Design kit' | 'Documentation' | string;
+export interface ResourceType {
+ id?: string;
+ name: string;
+ type?: ResourceTypeType | {
+ label: string;
+ value: ResourceTypeType;
+ };
+ url?: string;
+}
\ No newline at end of file
diff --git a/design-system-manager/tsconfig.json b/design-system-manager/tsconfig.json
new file mode 100644
index 000000000..299d6cd76
--- /dev/null
+++ b/design-system-manager/tsconfig.json
@@ -0,0 +1,28 @@
+{
+ "compilerOptions": {
+ "target": "es5",
+ "lib": ["dom", "dom.iterable", "esnext"],
+ "allowJs": true,
+ "allowImportingTsExtensions": true,
+ "skipLibCheck": true,
+ "strict": true,
+ "noEmit": true,
+ "esModuleInterop": true,
+ "module": "esnext",
+ "moduleResolution": "bundler",
+ "resolveJsonModule": true,
+ "isolatedModules": true,
+ "jsx": "preserve",
+ "incremental": true,
+ "plugins": [
+ {
+ "name": "next"
+ }
+ ],
+ "paths": {
+ "@/*": ["./src/*"]
+ }
+ },
+ "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
+ "exclude": ["node_modules"]
+}
diff --git a/package.json b/package.json
index 1740a9123..3be0784aa 100644
--- a/package.json
+++ b/package.json
@@ -27,7 +27,9 @@
},
"workspaces": [
"aries-core",
- "aries-site"
+ "aries-site",
+ "demo-api",
+ "design-system-manager"
],
"dependencies": {
"grommet": "https://github.com/grommet/grommet/tarball/stable",
diff --git a/yarn.lock b/yarn.lock
index f0b4123fd..65bd307a4 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1382,6 +1382,13 @@
resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39"
integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==
+"@cspotcode/source-map-support@^0.8.0":
+ version "0.8.1"
+ resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1"
+ integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==
+ dependencies:
+ "@jridgewell/trace-mapping" "0.3.9"
+
"@devexpress/bin-v8-flags-filter@^1.3.0":
version "1.3.0"
resolved "https://registry.yarnpkg.com/@devexpress/bin-v8-flags-filter/-/bin-v8-flags-filter-1.3.0.tgz#3069f2525c0c5fb940810e9ec10fc592c47552db"
@@ -1687,6 +1694,11 @@
"@jridgewell/sourcemap-codec" "^1.4.10"
"@jridgewell/trace-mapping" "^0.3.9"
+"@jridgewell/resolve-uri@^3.0.3":
+ version "3.1.2"
+ resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6"
+ integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==
+
"@jridgewell/resolve-uri@^3.1.0":
version "3.1.1"
resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz#c08679063f279615a3326583ba3a90d1d82cc721"
@@ -1710,6 +1722,14 @@
resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32"
integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==
+"@jridgewell/trace-mapping@0.3.9":
+ version "0.3.9"
+ resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9"
+ integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==
+ dependencies:
+ "@jridgewell/resolve-uri" "^3.0.3"
+ "@jridgewell/sourcemap-codec" "^1.4.10"
+
"@jridgewell/trace-mapping@^0.3.17", "@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.9":
version "0.3.22"
resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz#72a621e5de59f5f1ef792d0793a82ee20f645e4c"
@@ -1784,6 +1804,18 @@
resolved "https://registry.yarnpkg.com/@next/env/-/env-13.4.4.tgz#46b620f6bef97fe67a1566bf570dbb791d40c50a"
integrity sha512-q/y7VZj/9YpgzDe64Zi6rY1xPizx80JjlU2BTevlajtaE3w1LqweH1gGgxou2N7hdFosXHjGrI4OUvtFXXhGLg==
+"@next/env@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/env/-/env-14.0.3.tgz#9a58b296e7ae04ffebce8a4e5bd0f87f71de86bd"
+ integrity sha512-7xRqh9nMvP5xrW4/+L0jgRRX+HoNRGnfJpD+5Wq6/13j3dsdzxO3BCXn7D3hMqsDb+vjZnJq+vI7+EtgrYZTeA==
+
+"@next/eslint-plugin-next@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/eslint-plugin-next/-/eslint-plugin-next-14.0.3.tgz#f32413be4db69f698538c38fd6f4091a2feb54c6"
+ integrity sha512-j4K0n+DcmQYCVnSAM+UByTVfIHnYQy2ODozfQP+4RdwtRDfobrIvKq1K4Exb2koJ79HSSa7s6B2SA8T/1YR3RA==
+ dependencies:
+ glob "7.1.7"
+
"@next/mdx@^13.4.4":
version "13.5.6"
resolved "https://registry.yarnpkg.com/@next/mdx/-/mdx-13.5.6.tgz#c70c96b2f7078c312bb18a29979476b74708d382"
@@ -1796,46 +1828,91 @@
resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-13.4.4.tgz#8c14083c2478e2a9a8d140cce5900f76b75667ff"
integrity sha512-xfjgXvp4KalNUKZMHmsFxr1Ug+aGmmO6NWP0uoh4G3WFqP/mJ1xxfww0gMOeMeSq/Jyr5k7DvoZ2Pv+XOITTtw==
+"@next/swc-darwin-arm64@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-arm64/-/swc-darwin-arm64-14.0.3.tgz#b1a0440ffbf69056451947c4aea5b6d887e9fbbc"
+ integrity sha512-64JbSvi3nbbcEtyitNn2LEDS/hcleAFpHdykpcnrstITFlzFgB/bW0ER5/SJJwUPj+ZPY+z3e+1jAfcczRLVGw==
+
"@next/swc-darwin-x64@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-13.4.4.tgz#5fe01c65c80fcb833c8789fd70f074ea99893864"
integrity sha512-ZY9Ti1hkIwJsxGus3nlubIkvYyB0gNOYxKrfsOrLEqD0I2iCX8D7w8v6QQZ2H+dDl6UT29oeEUdDUNGk4UEpfg==
+"@next/swc-darwin-x64@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-darwin-x64/-/swc-darwin-x64-14.0.3.tgz#48b527ef7eb5dbdcaf62fd107bc3a78371f36f09"
+ integrity sha512-RkTf+KbAD0SgYdVn1XzqE/+sIxYGB7NLMZRn9I4Z24afrhUpVJx6L8hsRnIwxz3ERE2NFURNliPjJ2QNfnWicQ==
+
"@next/swc-linux-arm64-gnu@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-13.4.4.tgz#f2e071f38e8a6cdadf507cc5d28956f73360d064"
integrity sha512-+KZnDeMShYkpkqAvGCEDeqYTRADJXc6SY1jWXz+Uo6qWQO/Jd9CoyhTJwRSxvQA16MoYzvILkGaDqirkRNctyA==
+"@next/swc-linux-arm64-gnu@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-gnu/-/swc-linux-arm64-gnu-14.0.3.tgz#0a36475a38b2855ab8ea0fe8b56899bc90184c0f"
+ integrity sha512-3tBWGgz7M9RKLO6sPWC6c4pAw4geujSwQ7q7Si4d6bo0l6cLs4tmO+lnSwFp1Tm3lxwfMk0SgkJT7EdwYSJvcg==
+
"@next/swc-linux-arm64-musl@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-13.4.4.tgz#23bf75c544e54562bc24ec1be036e4bd9cf89e2c"
integrity sha512-evC1twrny2XDT4uOftoubZvW3EG0zs0ZxMwEtu/dDGVRO5n5pT48S8qqEIBGBUZYu/Xx4zzpOkIxx1vpWdE+9A==
+"@next/swc-linux-arm64-musl@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-arm64-musl/-/swc-linux-arm64-musl-14.0.3.tgz#25328a9f55baa09fde6364e7e47ade65c655034f"
+ integrity sha512-v0v8Kb8j8T23jvVUWZeA2D8+izWspeyeDGNaT2/mTHWp7+37fiNfL8bmBWiOmeumXkacM/AB0XOUQvEbncSnHA==
+
"@next/swc-linux-x64-gnu@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-13.4.4.tgz#bd42590950a01957952206f89cf5622e7c9e4196"
integrity sha512-PX706XcCHr2FfkyhP2lpf+pX/tUvq6/ke7JYnnr0ykNdEMo+sb7cC/o91gnURh4sPYSiZJhsF2gbIqg9rciOHQ==
+"@next/swc-linux-x64-gnu@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-gnu/-/swc-linux-x64-gnu-14.0.3.tgz#594b747e3c8896b2da67bba54fcf8a6b5a410e5e"
+ integrity sha512-VM1aE1tJKLBwMGtyBR21yy+STfl0MapMQnNrXkxeyLs0GFv/kZqXS5Jw/TQ3TSUnbv0QPDf/X8sDXuMtSgG6eg==
+
"@next/swc-linux-x64-musl@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-13.4.4.tgz#907d81feb1abec3daec0ecb61e3f39b56e7aeafe"
integrity sha512-TKUUx3Ftd95JlHV6XagEnqpT204Y+IsEa3awaYIjayn0MOGjgKZMZibqarK3B1FsMSPaieJf2FEAcu9z0yT5aA==
+"@next/swc-linux-x64-musl@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-linux-x64-musl/-/swc-linux-x64-musl-14.0.3.tgz#a02da58fc6ecad8cf5c5a2a96a7f6030ec7f6215"
+ integrity sha512-64EnmKy18MYFL5CzLaSuUn561hbO1Gk16jM/KHznYP3iCIfF9e3yULtHaMy0D8zbHfxset9LTOv6cuYKJgcOxg==
+
"@next/swc-win32-arm64-msvc@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-13.4.4.tgz#1d754d2bb10bdf9907c0acc83711438697c3b5fe"
integrity sha512-FP8AadgSq4+HPtim7WBkCMGbhr5vh9FePXiWx9+YOdjwdQocwoCK5ZVC3OW8oh3TWth6iJ0AXJ/yQ1q1cwSZ3A==
+"@next/swc-win32-arm64-msvc@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-arm64-msvc/-/swc-win32-arm64-msvc-14.0.3.tgz#bf2be23d3ba2ebd0d4a9376a31f783efdb677b48"
+ integrity sha512-WRDp8QrmsL1bbGtsh5GqQ/KWulmrnMBgbnb+59qNTW1kVi1nG/2ndZLkcbs2GX7NpFLlToLRMWSQXmPzQm4tog==
+
"@next/swc-win32-ia32-msvc@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-13.4.4.tgz#77b2c7f7534b675d46e46301869e08d504d23956"
integrity sha512-3WekVmtuA2MCdcAOrgrI+PuFiFURtSyyrN1I3UPtS0ckR2HtLqyqmS334Eulf15g1/bdwMteePdK363X/Y9JMg==
+"@next/swc-win32-ia32-msvc@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-ia32-msvc/-/swc-win32-ia32-msvc-14.0.3.tgz#839f8de85a4bf2c3c69242483ab87cb916427551"
+ integrity sha512-EKffQeqCrj+t6qFFhIFTRoqb2QwX1mU7iTOvMyLbYw3QtqTw9sMwjykyiMlZlrfm2a4fA84+/aeW+PMg1MjuTg==
+
"@next/swc-win32-x64-msvc@13.4.4":
version "13.4.4"
resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-13.4.4.tgz#faab69239f8a9d0be7cd473e65f5a07735ef7b0e"
integrity sha512-AHRITu/CrlQ+qzoqQtEMfaTu7GHaQ6bziQln/pVWpOYC1wU+Mq6VQQFlsDtMCnDztPZtppAXdvvbNS7pcfRzlw==
+"@next/swc-win32-x64-msvc@14.0.3":
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/@next/swc-win32-x64-msvc/-/swc-win32-x64-msvc-14.0.3.tgz#27b623612b1d0cea6efe0a0d31aa1a335fc99647"
+ integrity sha512-ERhKPSJ1vQrPiwrs15Pjz/rvDHZmkmvbf/BjPN/UCOI++ODftT0GtasDPi0j+y6PPJi5HsXw+dpRaXUaw4vjuQ==
+
"@nicolo-ribaudo/chokidar-2@2.1.8-no-fsevents.3":
version "2.1.8-no-fsevents.3"
resolved "https://registry.yarnpkg.com/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz#323d72dd25103d0c4fbdce89dadf574a787b1f9b"
@@ -1869,6 +1946,59 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
+"@prisma/client@5.5.2":
+ version "5.5.2"
+ resolved "https://registry.yarnpkg.com/@prisma/client/-/client-5.5.2.tgz#ce6389e7ad9e9cf0fc2a7c6a0032ad2e12a9fd61"
+ integrity sha512-54XkqR8M+fxbzYqe+bIXimYnkkcGqgOh0dn0yWtIk6CQT4IUCAvNFNcQZwk2KqaLU+/1PHTSWrcHtx4XjluR5w==
+ dependencies:
+ "@prisma/engines-version" "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a"
+
+"@prisma/debug@5.9.1":
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/@prisma/debug/-/debug-5.9.1.tgz#906274e73d3267f88b69459199fa3c51cd9511a3"
+ integrity sha512-yAHFSFCg8KVoL0oRUno3m60GAjsUKYUDkQ+9BA2X2JfVR3kRVSJFc/GpQ2fSORi4pSHZR9orfM4UC9OVXIFFTA==
+
+"@prisma/engines-version@5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a":
+ version "5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a"
+ resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.5.1-1.aebc046ce8b88ebbcb45efe31cbe7d06fd6abc0a.tgz#35cd59ed65ee1f9e333f4865ec86a4432c4d0a9c"
+ integrity sha512-O+qHFnZvAyOFk1tUco2/VdiqS0ym42a3+6CYLScllmnpbyiTplgyLt2rK/B9BTjYkSHjrgMhkG47S0oqzdIckA==
+
+"@prisma/engines-version@5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64":
+ version "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64"
+ resolved "https://registry.yarnpkg.com/@prisma/engines-version/-/engines-version-5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64.tgz#54d2164f28d23e09d41cf9eb0bddbbe7f3aaa660"
+ integrity sha512-HFl7275yF0FWbdcNvcSRbbu9JCBSLMcurYwvWc8WGDnpu7APxQo2ONtZrUggU3WxLxUJ2uBX+0GOFIcJeVeOOQ==
+
+"@prisma/engines@5.9.1":
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/@prisma/engines/-/engines-5.9.1.tgz#767539afc6f193a182d0495b30b027f61f279073"
+ integrity sha512-gkdXmjxQ5jktxWNdDA5aZZ6R8rH74JkoKq6LD5mACSvxd2vbqWeWIOV0Py5wFC8vofOYShbt6XUeCIUmrOzOnQ==
+ dependencies:
+ "@prisma/debug" "5.9.1"
+ "@prisma/engines-version" "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64"
+ "@prisma/fetch-engine" "5.9.1"
+ "@prisma/get-platform" "5.9.1"
+
+"@prisma/fetch-engine@5.9.1":
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/@prisma/fetch-engine/-/fetch-engine-5.9.1.tgz#5d3b2c9af54a242e37b3f9561b59ab72f8e92818"
+ integrity sha512-l0goQOMcNVOJs1kAcwqpKq3ylvkD9F04Ioe1oJoCqmz05mw22bNAKKGWuDd3zTUoUZr97va0c/UfLNru+PDmNA==
+ dependencies:
+ "@prisma/debug" "5.9.1"
+ "@prisma/engines-version" "5.9.0-32.23fdc5965b1e05fc54e5f26ed3de66776b93de64"
+ "@prisma/get-platform" "5.9.1"
+
+"@prisma/get-platform@5.9.1":
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/@prisma/get-platform/-/get-platform-5.9.1.tgz#a66bb46ab4d30db786c84150ef074ab0aad4549e"
+ integrity sha512-6OQsNxTyhvG+T2Ksr8FPFpuPeL4r9u0JF0OZHUBI/Uy9SS43sPyAIutt4ZEAyqWQt104ERh70EZedkHZKsnNbg==
+ dependencies:
+ "@prisma/debug" "5.9.1"
+
+"@rushstack/eslint-patch@^1.3.3":
+ version "1.7.2"
+ resolved "https://registry.yarnpkg.com/@rushstack/eslint-patch/-/eslint-patch-1.7.2.tgz#2d4260033e199b3032a08b41348ac10de21c47e9"
+ integrity sha512-RbhOOTCNoCrbfkRyoXODZp75MlpiHMgbE5MEBZAnnnLyQNgrigEj4p0lzsMDyc1zVsJDLrivB58tgg3emX0eEA==
+
"@sideway/address@^4.1.5":
version "4.1.5"
resolved "https://registry.yarnpkg.com/@sideway/address/-/address-4.1.5.tgz#4bc149a0076623ced99ca8208ba780d65a99b9d5"
@@ -1907,6 +2037,13 @@
dependencies:
tslib "^2.4.0"
+"@swc/helpers@0.5.2":
+ version "0.5.2"
+ resolved "https://registry.yarnpkg.com/@swc/helpers/-/helpers-0.5.2.tgz#85ea0c76450b61ad7d10a37050289eded783c27d"
+ integrity sha512-E4KcWTpoLHqwPHLxidpOqQbcrZVgi0rsmmZXUle1jXmJfuIf/UWpczUJ7MZZ5tlxytgJXyp0w4PGkkeLiuIdZw==
+ dependencies:
+ tslib "^2.4.0"
+
"@testing-library/dom@^8.19.0":
version "8.20.1"
resolved "https://registry.yarnpkg.com/@testing-library/dom/-/dom-8.20.1.tgz#2e52a32e46fc88369eef7eef634ac2a192decd9f"
@@ -1938,6 +2075,26 @@
resolved "https://registry.yarnpkg.com/@tootallnate/once/-/once-2.0.0.tgz#f544a148d3ab35801c1f633a7441fd87c2e484bf"
integrity sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==
+"@tsconfig/node10@^1.0.7":
+ version "1.0.9"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.9.tgz#df4907fc07a886922637b15e02d4cebc4c0021b2"
+ integrity sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==
+
+"@tsconfig/node12@^1.0.7":
+ version "1.0.11"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d"
+ integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==
+
+"@tsconfig/node14@^1.0.0":
+ version "1.0.3"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1"
+ integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==
+
+"@tsconfig/node16@^1.0.2":
+ version "1.0.4"
+ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9"
+ integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==
+
"@types/acorn@^4.0.0":
version "4.0.6"
resolved "https://registry.yarnpkg.com/@types/acorn/-/acorn-4.0.6.tgz#d61ca5480300ac41a7d973dd5b84d0a591154a22"
@@ -2013,6 +2170,13 @@
dependencies:
"@types/node" "*"
+"@types/cors@^2.8.15":
+ version "2.8.17"
+ resolved "https://registry.yarnpkg.com/@types/cors/-/cors-2.8.17.tgz#5d718a5e494a8166f569d986794e49c48b216b2b"
+ integrity sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==
+ dependencies:
+ "@types/node" "*"
+
"@types/debug@^4.0.0":
version "4.1.12"
resolved "https://registry.yarnpkg.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
@@ -2063,7 +2227,14 @@
"@types/range-parser" "*"
"@types/send" "*"
-"@types/express@*", "@types/express@^4.17.13":
+"@types/express-validator@^3.0.0":
+ version "3.0.0"
+ resolved "https://registry.yarnpkg.com/@types/express-validator/-/express-validator-3.0.0.tgz#e6f3cab842e5ae376a1cfa11295202ec380b68d1"
+ integrity sha512-LusnB0YhTXpBT25PXyGPQlK7leE1e41Vezq1hHEUwjfkopM1Pkv2X2Ppxqh9c+w/HZ6Udzki8AJotKNjDTGdkQ==
+ dependencies:
+ express-validator "*"
+
+"@types/express@*", "@types/express@^4.17.13", "@types/express@^4.17.20":
version "4.17.21"
resolved "https://registry.yarnpkg.com/@types/express/-/express-4.17.21.tgz#c26d4a151e60efe0084b23dc3369ebc631ed192d"
integrity sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==
@@ -2192,6 +2363,13 @@
resolved "https://registry.yarnpkg.com/@types/node/-/node-12.20.55.tgz#c329cbd434c42164f846b909bd6f85b5537f6240"
integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==
+"@types/node@^20", "@types/node@^20.8.9":
+ version "20.11.19"
+ resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.19.tgz#b466de054e9cb5b3831bee38938de64ac7f81195"
+ integrity sha512-7xMnVEcZFu0DikYjWOlRq7NTPETrm7teqUT2WkQjrTIkEgUyyGdWsj/Zg8bEJt5TNklzbPD1X3fqfsHw3SpapQ==
+ dependencies:
+ undici-types "~5.26.4"
+
"@types/prettier@^2.1.5":
version "2.7.3"
resolved "https://registry.yarnpkg.com/@types/prettier/-/prettier-2.7.3.tgz#3e51a17e291d01d17d3fc61422015a933af7a08f"
@@ -2212,7 +2390,14 @@
resolved "https://registry.yarnpkg.com/@types/range-parser/-/range-parser-1.2.7.tgz#50ae4353eaaddc04044279812f52c8c65857dbcb"
integrity sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==
-"@types/react@>=16":
+"@types/react-dom@^18":
+ version "18.2.19"
+ resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-18.2.19.tgz#b84b7c30c635a6c26c6a6dfbb599b2da9788be58"
+ integrity sha512-aZvQL6uUbIJpjZk4U8JZGbau9KDeAwMfmhyWorxgBkqDIEf6ROjRozcmPIicqsUwPUjbkDfHKgGee1Lq65APcA==
+ dependencies:
+ "@types/react" "*"
+
+"@types/react@*", "@types/react@>=16", "@types/react@^18":
version "18.2.55"
resolved "https://registry.yarnpkg.com/@types/react/-/react-18.2.55.tgz#38141821b7084404b5013742bc4ae08e44da7a67"
integrity sha512-Y2Tz5P4yz23brwm2d7jNon39qoAtMMmalOQv6+fEFt1mT+FcM3D841wDpoUvFXhaYenuROCy3FZYqdTjM7qVyA==
@@ -2291,6 +2476,52 @@
dependencies:
"@types/yargs-parser" "*"
+"@typescript-eslint/parser@^5.4.2 || ^6.0.0":
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.21.0.tgz#af8fcf66feee2edc86bc5d1cf45e33b0630bf35b"
+ integrity sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==
+ dependencies:
+ "@typescript-eslint/scope-manager" "6.21.0"
+ "@typescript-eslint/types" "6.21.0"
+ "@typescript-eslint/typescript-estree" "6.21.0"
+ "@typescript-eslint/visitor-keys" "6.21.0"
+ debug "^4.3.4"
+
+"@typescript-eslint/scope-manager@6.21.0":
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz#ea8a9bfc8f1504a6ac5d59a6df308d3a0630a2b1"
+ integrity sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==
+ dependencies:
+ "@typescript-eslint/types" "6.21.0"
+ "@typescript-eslint/visitor-keys" "6.21.0"
+
+"@typescript-eslint/types@6.21.0":
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.21.0.tgz#205724c5123a8fef7ecd195075fa6e85bac3436d"
+ integrity sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==
+
+"@typescript-eslint/typescript-estree@6.21.0":
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz#c47ae7901db3b8bddc3ecd73daff2d0895688c46"
+ integrity sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==
+ dependencies:
+ "@typescript-eslint/types" "6.21.0"
+ "@typescript-eslint/visitor-keys" "6.21.0"
+ debug "^4.3.4"
+ globby "^11.1.0"
+ is-glob "^4.0.3"
+ minimatch "9.0.3"
+ semver "^7.5.4"
+ ts-api-utils "^1.0.1"
+
+"@typescript-eslint/visitor-keys@6.21.0":
+ version "6.21.0"
+ resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz#87a99d077aa507e20e238b11d56cc26ade45fe47"
+ integrity sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==
+ dependencies:
+ "@typescript-eslint/types" "6.21.0"
+ eslint-visitor-keys "^3.4.1"
+
"@ungap/structured-clone@^1.2.0":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406"
@@ -2447,6 +2678,11 @@ abab@^2.0.3, abab@^2.0.5, abab@^2.0.6:
resolved "https://registry.yarnpkg.com/abab/-/abab-2.0.6.tgz#41b80f2c871d19686216b82309231cfd3cb3d291"
integrity sha512-j2afSsaIENvHZN2B8GOpF566vZ5WVk5opAiMTvWgaQT8DkbOqsTfvNAvHoRGU2zzP8cPoqys+xHTRDWW8L+/BA==
+abbrev@1:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
+ integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
+
abort-controller@3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/abort-controller/-/abort-controller-3.0.0.tgz#eaf54d53b62bae4138e809ca225c8439a6efb392"
@@ -2492,7 +2728,7 @@ acorn-walk@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-7.2.0.tgz#0de889a601203909b0fbe07b8938dc21d2e967bc"
integrity sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==
-acorn-walk@^8.2.0:
+acorn-walk@^8.1.1, acorn-walk@^8.2.0:
version "8.3.2"
resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.2.tgz#7703af9415f1b6db9315d6895503862e231d34aa"
integrity sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==
@@ -2502,7 +2738,7 @@ acorn@^7.1.1:
resolved "https://registry.yarnpkg.com/acorn/-/acorn-7.4.1.tgz#feaed255973d2e77555b83dbc08851a6c63520fa"
integrity sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==
-acorn@^8.0.0, acorn@^8.2.4, acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0:
+acorn@^8.0.0, acorn@^8.2.4, acorn@^8.4.1, acorn@^8.5.0, acorn@^8.7.0, acorn@^8.7.1, acorn@^8.8.2, acorn@^8.9.0:
version "8.11.3"
resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.3.tgz#71e0b14e13a4ec160724b38fb7b0f233b1b81d7a"
integrity sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==
@@ -2617,6 +2853,11 @@ anymatch@^3.0.3, anymatch@~3.1.2:
normalize-path "^3.0.0"
picomatch "^2.0.4"
+arg@^4.1.0:
+ version "4.1.3"
+ resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089"
+ integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==
+
arg@^5.0.2:
version "5.0.2"
resolved "https://registry.yarnpkg.com/arg/-/arg-5.0.2.tgz#c81433cc427c92c4dcf4865142dbca6f15acd59c"
@@ -3287,7 +3528,7 @@ check-more-types@2.24.0:
resolved "https://registry.yarnpkg.com/check-more-types/-/check-more-types-2.24.0.tgz#1420ffb10fd444dcfc79b43891bbfffd32a84600"
integrity sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==
-chokidar@^3.4.0, chokidar@^3.5.3:
+chokidar@^3.4.0, chokidar@^3.5.2, chokidar@^3.5.3:
version "3.6.0"
resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b"
integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==
@@ -3538,6 +3779,19 @@ core-util-is@~1.0.0:
resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.3.tgz#a6042d3634c2b27e9328f837b965fac83808db85"
integrity sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==
+cors@^2.8.5:
+ version "2.8.5"
+ resolved "https://registry.yarnpkg.com/cors/-/cors-2.8.5.tgz#eac11da51592dd86b9f06f6e7ac293b3df875d29"
+ integrity sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==
+ dependencies:
+ object-assign "^4"
+ vary "^1"
+
+create-require@^1.1.0:
+ version "1.1.1"
+ resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333"
+ integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==
+
cross-spawn@^7.0.0, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
version "7.0.3"
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
@@ -3646,7 +3900,7 @@ debug@2.6.9:
dependencies:
ms "2.0.0"
-debug@4, debug@4.3.4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
+debug@4, debug@4.3.4, debug@^4, debug@^4.0.0, debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -3873,7 +4127,7 @@ diff-sequences@^27.5.1:
resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-27.5.1.tgz#eaecc0d327fd68c8d9672a1e64ab8dccb2ef5327"
integrity sha512-k1gCAXAsNgLwEL+Y8Wvl+M6oEFj5bgazfZULpS5CneoPPXRaCCW7dm+q21Ky2VEE5X+VeRDBVg1Pcvvsr4TtNQ==
-diff@^4.0.2:
+diff@^4.0.1, diff@^4.0.2:
version "4.0.2"
resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d"
integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==
@@ -4005,7 +4259,7 @@ endpoint-utils@^1.0.2:
ip "^1.1.3"
pinkie-promise "^1.0.0"
-enhanced-resolve@^5.10.0, enhanced-resolve@^5.15.0:
+enhanced-resolve@^5.10.0, enhanced-resolve@^5.12.0, enhanced-resolve@^5.15.0:
version "5.15.0"
resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz#1af946c7d93603eb88e9896cee4904dc012e9c35"
integrity sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==
@@ -4239,12 +4493,32 @@ eslint-config-airbnb@^19.0.4:
object.assign "^4.1.2"
object.entries "^1.1.5"
+eslint-config-next@14.0.3:
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/eslint-config-next/-/eslint-config-next-14.0.3.tgz#7a01d23e4ff143ef87b520fab9efc440fa5879f3"
+ integrity sha512-IKPhpLdpSUyKofmsXUfrvBC49JMUTdeaD8ZIH4v9Vk0sC1X6URTuTJCLtA0Vwuj7V/CQh0oISuSTvNn5//Buew==
+ dependencies:
+ "@next/eslint-plugin-next" "14.0.3"
+ "@rushstack/eslint-patch" "^1.3.3"
+ "@typescript-eslint/parser" "^5.4.2 || ^6.0.0"
+ eslint-import-resolver-node "^0.3.6"
+ eslint-import-resolver-typescript "^3.5.2"
+ eslint-plugin-import "^2.28.1"
+ eslint-plugin-jsx-a11y "^6.7.1"
+ eslint-plugin-react "^7.33.2"
+ eslint-plugin-react-hooks "^4.5.0 || 5.0.0-canary-7118f5dd7-20230705"
+
eslint-config-prettier@^8.5.0:
version "8.10.0"
resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-8.10.0.tgz#3a06a662130807e2502fc3ff8b4143d8a0658e11"
integrity sha512-SM8AMJdeQqRYT9O9zguiruQZaN7+z+E4eAP9oiLNGKMtomwaB1E9dcgUD6ZAn/eQAb52USbvezbiljfZUhbJcg==
-eslint-import-resolver-node@^0.3.9:
+eslint-config-prettier@^9.1.0:
+ version "9.1.0"
+ resolved "https://registry.yarnpkg.com/eslint-config-prettier/-/eslint-config-prettier-9.1.0.tgz#31af3d94578645966c082fcb71a5846d3c94867f"
+ integrity sha512-NSWl5BFQWEPi1j4TjVNItzYV7dZXZ+wP6I6ZhrBGpChQhZRUaElihE9uRRkcbRnNb76UMKDF3r+WTmNcGPKsqw==
+
+eslint-import-resolver-node@^0.3.6, eslint-import-resolver-node@^0.3.9:
version "0.3.9"
resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac"
integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==
@@ -4253,7 +4527,20 @@ eslint-import-resolver-node@^0.3.9:
is-core-module "^2.13.0"
resolve "^1.22.4"
-eslint-module-utils@^2.8.0:
+eslint-import-resolver-typescript@^3.5.2:
+ version "3.6.1"
+ resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa"
+ integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg==
+ dependencies:
+ debug "^4.3.4"
+ enhanced-resolve "^5.12.0"
+ eslint-module-utils "^2.7.4"
+ fast-glob "^3.3.1"
+ get-tsconfig "^4.5.0"
+ is-core-module "^2.11.0"
+ is-glob "^4.0.3"
+
+eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0:
version "2.8.0"
resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49"
integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw==
@@ -4266,7 +4553,7 @@ eslint-module-utils@^2.8.0:
dependencies:
requireindex "~1.1.0"
-eslint-plugin-import@^2.26.0:
+eslint-plugin-import@^2.26.0, eslint-plugin-import@^2.28.1:
version "2.29.1"
resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643"
integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==
@@ -4289,7 +4576,7 @@ eslint-plugin-import@^2.26.0:
semver "^6.3.1"
tsconfig-paths "^3.15.0"
-eslint-plugin-jsx-a11y@^6.4.1:
+eslint-plugin-jsx-a11y@^6.4.1, eslint-plugin-jsx-a11y@^6.7.1:
version "6.8.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-jsx-a11y/-/eslint-plugin-jsx-a11y-6.8.0.tgz#2fa9c701d44fcd722b7c771ec322432857fcbad2"
integrity sha512-Hdh937BS3KdwwbBaKd5+PLCOmYY6U4f2h9Z2ktwtNKvIdIEu137rjYbcb9ApSbVJfWxANNuiKTD/9tOKjK9qOA==
@@ -4327,7 +4614,7 @@ eslint-plugin-prettier@^4.2.1:
dependencies:
prettier-linter-helpers "^1.0.0"
-eslint-plugin-react-hooks@^4.6.0:
+"eslint-plugin-react-hooks@^4.5.0 || 5.0.0-canary-7118f5dd7-20230705", eslint-plugin-react-hooks@^4.6.0:
version "4.6.0"
resolved "https://registry.yarnpkg.com/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-4.6.0.tgz#4c3e697ad95b77e93f8646aaa1630c1ba607edd3"
integrity sha512-oFc7Itz9Qxh2x4gNHStv3BqJq54ExXmfC+a1NjAta66IAN87Wu0R/QArgIS9qKzX3dXKPI9H5crl9QchNMY9+g==
@@ -4337,7 +4624,7 @@ eslint-plugin-react@3.4.2:
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-3.4.2.tgz#9e6ef8a8054f8ac3b87b97236e7b849e5835dc6c"
integrity sha512-rIhweRuQMLxNOOHHl9pEkQR+6QiKt9wUHpBvjSefSzUg5qdhC08jc2rxsSm1TAXii9rxabhzK5MUu+YBJxn6sA==
-eslint-plugin-react@^7.31.11:
+eslint-plugin-react@^7.31.11, eslint-plugin-react@^7.33.2:
version "7.33.2"
resolved "https://registry.yarnpkg.com/eslint-plugin-react/-/eslint-plugin-react-7.33.2.tgz#69ee09443ffc583927eafe86ffebb470ee737608"
integrity sha512-73QQMKALArI8/7xGLNI/3LylrEYrlKZSb5C9+q3OtOewTnMQi5cT+aE9E41sLCmli3I9PGGmD1yiZydyo4FEPw==
@@ -4385,7 +4672,7 @@ eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1, eslint-visitor-keys@^3.4
resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800"
integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==
-eslint@^8.30.0:
+eslint@^8, eslint@^8.30.0:
version "8.56.0"
resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15"
integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ==
@@ -4625,7 +4912,15 @@ expect@^27.5.1:
jest-matcher-utils "^27.5.1"
jest-message-util "^27.5.1"
-express@^4.17.3:
+express-validator@*, express-validator@^7.0.1:
+ version "7.0.1"
+ resolved "https://registry.yarnpkg.com/express-validator/-/express-validator-7.0.1.tgz#435fac6b5fa838763f78eca05d2206317b92106e"
+ integrity sha512-oB+z9QOzQIE8FnlINqyIFA8eIckahC6qc8KtqLdLJcU3/phVyuhXH3bA4qzcrhme+1RYaCSwrq+TlZ/kAKIARA==
+ dependencies:
+ lodash "^4.17.21"
+ validator "^13.9.0"
+
+express@^4.17.3, express@^4.18.2:
version "4.18.2"
resolved "https://registry.yarnpkg.com/express/-/express-4.18.2.tgz#3fabe08296e930c796c19e3c516979386ba9fd59"
integrity sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==
@@ -4677,7 +4972,7 @@ fast-diff@^1.1.2:
resolved "https://registry.yarnpkg.com/fast-diff/-/fast-diff-1.3.0.tgz#ece407fa550a64d638536cd727e129c61616e0f0"
integrity sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==
-fast-glob@^3.0.3, fast-glob@^3.2.9:
+fast-glob@^3.0.3, fast-glob@^3.2.9, fast-glob@^3.3.1:
version "3.3.2"
resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129"
integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==
@@ -5023,6 +5318,13 @@ get-symbol-description@^1.0.2:
es-errors "^1.3.0"
get-intrinsic "^1.2.4"
+get-tsconfig@^4.5.0:
+ version "4.7.2"
+ resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.7.2.tgz#0dcd6fb330391d46332f4c6c1bf89a6514c2ddce"
+ integrity sha512-wuMsz4leaj5hbGgg4IvDU0bqJagpftG5l5cXIAvo8uZrqn0NJqwtfupTN00VnkQJPcIRrxYrm1Ue24btpCha2A==
+ dependencies:
+ resolve-pkg-maps "^1.0.0"
+
get-uri@3:
version "3.0.2"
resolved "https://registry.yarnpkg.com/get-uri/-/get-uri-3.0.2.tgz#f0ef1356faabc70e1f9404fa3b66b2ba9bfc725c"
@@ -5061,6 +5363,18 @@ glob-to-regexp@^0.4.1:
resolved "https://registry.yarnpkg.com/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz#c75297087c851b9a578bd217dd59a92f59fe546e"
integrity sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==
+glob@7.1.7:
+ version "7.1.7"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.7.tgz#3b193e9233f01d42d0b3f78294bbeeb418f94a90"
+ integrity sha512-OvD9ENzPLbegENnYP5UUfJIirTg4+XwMWGaQfQTY0JenxNvvIKP3U3/tAQSPIu/lHxXYSZmpXlUHeqAIdKzBLQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^3.0.4"
+ once "^1.3.0"
+ path-is-absolute "^1.0.0"
+
glob@^7.0.3, glob@^7.1.1, glob@^7.1.2, glob@^7.1.3, glob@^7.1.4, glob@^7.1.6, glob@^7.2.0:
version "7.2.3"
resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b"
@@ -5117,7 +5431,7 @@ globby@^10.0.1:
merge2 "^1.2.3"
slash "^3.0.0"
-globby@^11.0.1, globby@^11.0.4:
+globby@^11.0.1, globby@^11.0.4, globby@^11.1.0:
version "11.1.0"
resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b"
integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==
@@ -5164,14 +5478,9 @@ graphlib@^2.1.5:
dependencies:
lodash "^4.17.15"
-grommet-icons@^4.10.0:
- version "4.12.0"
- resolved "https://registry.yarnpkg.com/grommet-icons/-/grommet-icons-4.12.0.tgz#122c1f09c100f2ea6321c401107038caeda8a6b8"
- integrity sha512-aPFVjdCBLbaUOpxzrNakxYz6DNYxS5lJeLP4tI6nZFfOzLhWH5LBf+tfkL/ZkLMNZC1Uqsw9awPvyvT03xLOsA==
-
-"grommet-icons@https://github.com/grommet/grommet-icons/tarball/stable":
- version "4.12.0"
- resolved "https://github.com/grommet/grommet-icons/tarball/stable#7d9b0e5924603eefe05690e317ac9d27a3ab7a50"
+grommet-icons@^4.10.0, "grommet-icons@https://github.com/grommet/grommet-icons/tarball/stable":
+ version "4.11.0"
+ resolved "https://github.com/grommet/grommet-icons/tarball/stable#ba8cb353999b8c1436d56c4fea10cd57da634b5a"
"grommet-theme-hpe@https://github.com/grommet/grommet-theme-hpe/tarball/stable":
version "0.0.0"
@@ -5496,6 +5805,11 @@ iconv-lite@0.6.3:
dependencies:
safer-buffer ">= 2.1.2 < 3.0.0"
+ignore-by-default@^1.0.1:
+ version "1.0.1"
+ resolved "https://registry.yarnpkg.com/ignore-by-default/-/ignore-by-default-1.0.1.tgz#48ca6d72f6c6a3af00a9ad4ae6876be3889e2b09"
+ integrity sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==
+
ignore@^5.1.1, ignore@^5.2.0:
version "5.3.1"
resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef"
@@ -5694,7 +6008,7 @@ is-ci@^1.0.10:
dependencies:
ci-info "^1.5.0"
-is-core-module@^2.13.0, is-core-module@^2.13.1:
+is-core-module@^2.11.0, is-core-module@^2.13.0, is-core-module@^2.13.1:
version "2.13.1"
resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384"
integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw==
@@ -6816,6 +7130,11 @@ make-dir@^4.0.0:
dependencies:
semver "^7.5.3"
+make-error@^1.1.1:
+ version "1.3.6"
+ resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2"
+ integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==
+
makeerror@1.0.12:
version "1.0.12"
resolved "https://registry.yarnpkg.com/makeerror/-/makeerror-1.0.12.tgz#3e5dd2079a82e812e983cc6610c4a2cb0eaa801a"
@@ -7495,6 +7814,13 @@ minimalistic-assert@^1.0.0:
resolved "https://registry.yarnpkg.com/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz#2e194de044626d4a10e7f7fbc00ce73e83e4d5c7"
integrity sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==
+minimatch@9.0.3:
+ version "9.0.3"
+ resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825"
+ integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==
+ dependencies:
+ brace-expansion "^2.0.1"
+
minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2:
version "3.1.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b"
@@ -7564,7 +7890,7 @@ mustache@^2.1.1, mustache@^2.1.2, mustache@^2.2.1:
resolved "https://registry.yarnpkg.com/mustache/-/mustache-2.3.2.tgz#a6d4d9c3f91d13359ab889a812954f9230a3d0c5"
integrity sha512-KpMNwdQsYz3O/SBS1qJ/o3sqUJ5wSb8gb0pul8CO0S56b9Y2ALm8zCfsjPXsqGFfoNBkDwZuZIAjhsZI03gYVQ==
-nanoid@^3.1.12, nanoid@^3.1.31, nanoid@^3.3.4:
+nanoid@^3.1.12, nanoid@^3.1.31, nanoid@^3.3.4, nanoid@^3.3.6:
version "3.3.7"
resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8"
integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==
@@ -7619,6 +7945,29 @@ next@13.4.4:
"@next/swc-win32-ia32-msvc" "13.4.4"
"@next/swc-win32-x64-msvc" "13.4.4"
+next@14.0.3:
+ version "14.0.3"
+ resolved "https://registry.yarnpkg.com/next/-/next-14.0.3.tgz#8d801a08eaefe5974203d71092fccc463103a03f"
+ integrity sha512-AbYdRNfImBr3XGtvnwOxq8ekVCwbFTv/UJoLwmaX89nk9i051AEY4/HAWzU0YpaTDw8IofUpmuIlvzWF13jxIw==
+ dependencies:
+ "@next/env" "14.0.3"
+ "@swc/helpers" "0.5.2"
+ busboy "1.6.0"
+ caniuse-lite "^1.0.30001406"
+ postcss "8.4.31"
+ styled-jsx "5.1.1"
+ watchpack "2.4.0"
+ optionalDependencies:
+ "@next/swc-darwin-arm64" "14.0.3"
+ "@next/swc-darwin-x64" "14.0.3"
+ "@next/swc-linux-arm64-gnu" "14.0.3"
+ "@next/swc-linux-arm64-musl" "14.0.3"
+ "@next/swc-linux-x64-gnu" "14.0.3"
+ "@next/swc-linux-x64-musl" "14.0.3"
+ "@next/swc-win32-arm64-msvc" "14.0.3"
+ "@next/swc-win32-ia32-msvc" "14.0.3"
+ "@next/swc-win32-x64-msvc" "14.0.3"
+
node-environment-flags@^1.0.5:
version "1.0.6"
resolved "https://registry.yarnpkg.com/node-environment-flags/-/node-environment-flags-1.0.6.tgz#a30ac13621f6f7d674260a54dede048c3982c088"
@@ -7656,6 +8005,29 @@ node-releases@^2.0.14:
resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.14.tgz#2ffb053bceb8b2be8495ece1ab6ce600c4461b0b"
integrity sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==
+nodemon@^3.0.2:
+ version "3.0.3"
+ resolved "https://registry.yarnpkg.com/nodemon/-/nodemon-3.0.3.tgz#244a62d1c690eece3f6165c6cdb0db03ebd80b76"
+ integrity sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==
+ dependencies:
+ chokidar "^3.5.2"
+ debug "^4"
+ ignore-by-default "^1.0.1"
+ minimatch "^3.1.2"
+ pstree.remy "^1.1.8"
+ semver "^7.5.3"
+ simple-update-notifier "^2.0.0"
+ supports-color "^5.5.0"
+ touch "^3.1.0"
+ undefsafe "^2.0.5"
+
+nopt@~1.0.10:
+ version "1.0.10"
+ resolved "https://registry.yarnpkg.com/nopt/-/nopt-1.0.10.tgz#6ddd21bd2a31417b92727dd585f8a6f37608ebee"
+ integrity sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==
+ dependencies:
+ abbrev "1"
+
normalize-path@^3.0.0, normalize-path@~3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65"
@@ -7673,7 +8045,7 @@ nwsapi@^2.2.0:
resolved "https://registry.yarnpkg.com/nwsapi/-/nwsapi-2.2.7.tgz#738e0707d3128cb750dddcfe90e4610482df0f30"
integrity sha512-ub5E4+FBPKwAZx0UwIQOjYWGHTEq5sPqHQNRN8Z9e4A7u3Tj1weLJsL59yH9vmvqEtBHaOmT6cYQKIZOxp35FQ==
-object-assign@^4.0.1, object-assign@^4.1.1:
+object-assign@^4, object-assign@^4.0.1, object-assign@^4.1.1:
version "4.1.1"
resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863"
integrity sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==
@@ -8185,6 +8557,15 @@ postcss@8.4.14:
picocolors "^1.0.0"
source-map-js "^1.0.2"
+postcss@8.4.31:
+ version "8.4.31"
+ resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.31.tgz#92b451050a9f914da6755af352bdc0192508656d"
+ integrity sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==
+ dependencies:
+ nanoid "^3.3.6"
+ picocolors "^1.0.0"
+ source-map-js "^1.0.2"
+
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@@ -8221,6 +8602,13 @@ pretty-hrtime@^1.0.3:
resolved "https://registry.yarnpkg.com/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz#b7e3ea42435a4c9b2759d99e0f201eb195802ee1"
integrity sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==
+prisma@^5.5.2:
+ version "5.9.1"
+ resolved "https://registry.yarnpkg.com/prisma/-/prisma-5.9.1.tgz#baa3dd635fbf71504980978f10f55ea11068f6aa"
+ integrity sha512-Hy/8KJZz0ELtkw4FnG9MS9rNWlXcJhf98Z2QMqi0QiVMoS8PzsBkpla0/Y5hTlob8F3HeECYphBjqmBxrluUrQ==
+ dependencies:
+ "@prisma/engines" "5.9.1"
+
prismjs@^1.27.0:
version "1.29.0"
resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.29.0.tgz#f113555a8fa9b57c35e637bba27509dcf802dd12"
@@ -8311,6 +8699,11 @@ psl@^1.1.33:
resolved "https://registry.yarnpkg.com/psl/-/psl-1.9.0.tgz#d0df2a137f00794565fcaf3b2c00cd09f8d5a5a7"
integrity sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==
+pstree.remy@^1.1.8:
+ version "1.1.8"
+ resolved "https://registry.yarnpkg.com/pstree.remy/-/pstree.remy-1.1.8.tgz#c242224f4a67c21f686839bbdb4ac282b8373d3a"
+ integrity sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==
+
pump@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64"
@@ -8650,6 +9043,11 @@ resolve-from@^5.0.0:
resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69"
integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==
+resolve-pkg-maps@^1.0.0:
+ version "1.0.0"
+ resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f"
+ integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw==
+
resolve-url@^0.2.1:
version "0.2.1"
resolved "https://registry.yarnpkg.com/resolve-url/-/resolve-url-0.2.1.tgz#2c637fe77c893afd2a663fe21aa9080068e2052a"
@@ -8841,7 +9239,7 @@ semver@^6.0.0, semver@^6.3.0, semver@^6.3.1:
resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4"
integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==
-semver@^7.3.2, semver@^7.5.3:
+semver@^7.3.2, semver@^7.5.3, semver@^7.5.4:
version "7.6.0"
resolved "https://registry.yarnpkg.com/semver/-/semver-7.6.0.tgz#1a46a4db4bffcccd97b743b5005c8325f23d4e2d"
integrity sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==
@@ -8986,6 +9384,13 @@ simple-git@^3.15.1:
"@kwsites/promise-deferred" "^1.1.1"
debug "^4.3.4"
+simple-update-notifier@^2.0.0:
+ version "2.0.0"
+ resolved "https://registry.yarnpkg.com/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz#d70b92bdab7d6d90dfd73931195a30b6e3d7cebb"
+ integrity sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==
+ dependencies:
+ semver "^7.5.3"
+
sisteransi@^1.0.5:
version "1.0.5"
resolved "https://registry.yarnpkg.com/sisteransi/-/sisteransi-1.0.5.tgz#134d681297756437cc05ca01370d3a7a571075ed"
@@ -9731,6 +10136,13 @@ toidentifier@1.0.1:
resolved "https://registry.yarnpkg.com/toidentifier/-/toidentifier-1.0.1.tgz#3be34321a88a820ed1bd80dfaa33e479fbb8dd35"
integrity sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==
+touch@^3.1.0:
+ version "3.1.0"
+ resolved "https://registry.yarnpkg.com/touch/-/touch-3.1.0.tgz#fe365f5f75ec9ed4e56825e0bb76d24ab74af83b"
+ integrity sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==
+ dependencies:
+ nopt "~1.0.10"
+
tough-cookie@4.0.0:
version "4.0.0"
resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-4.0.0.tgz#d822234eeca882f991f0f908824ad2622ddbece4"
@@ -9791,6 +10203,30 @@ truncate-utf8-bytes@^1.0.0:
dependencies:
utf8-byte-length "^1.0.1"
+ts-api-utils@^1.0.1:
+ version "1.2.1"
+ resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.2.1.tgz#f716c7e027494629485b21c0df6180f4d08f5e8b"
+ integrity sha512-RIYA36cJn2WiH9Hy77hdF9r7oEwxAtB/TS9/S4Qd90Ap4z5FSiin5zEiTL44OII1Y3IIlEvxwxFUVgrHSZ/UpA==
+
+ts-node@^10.9.1:
+ version "10.9.2"
+ resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f"
+ integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==
+ dependencies:
+ "@cspotcode/source-map-support" "^0.8.0"
+ "@tsconfig/node10" "^1.0.7"
+ "@tsconfig/node12" "^1.0.7"
+ "@tsconfig/node14" "^1.0.0"
+ "@tsconfig/node16" "^1.0.2"
+ acorn "^8.4.1"
+ acorn-walk "^8.1.1"
+ arg "^4.1.0"
+ create-require "^1.1.0"
+ diff "^4.0.1"
+ make-error "^1.1.1"
+ v8-compile-cache-lib "^3.0.1"
+ yn "3.1.1"
+
tsconfig-paths@^3.15.0:
version "3.15.0"
resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4"
@@ -9906,6 +10342,11 @@ typescript@4.7.4:
resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.4.tgz#1a88596d1cf47d59507a1bcdfb5b9dfe4d488235"
integrity sha512-C0WQT0gezHuw6AdY1M2jxUO83Rjf0HP7Sk1DtXj6j1EwkQNZrHAg2XPWlq62oqEhYvONq5pkC2Y9oPljWToLmQ==
+typescript@^5, typescript@^5.2.2:
+ version "5.3.3"
+ resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37"
+ integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==
+
unbox-primitive@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e"
@@ -9916,6 +10357,11 @@ unbox-primitive@^1.0.2:
has-symbols "^1.0.3"
which-boxed-primitive "^1.0.2"
+undefsafe@^2.0.5:
+ version "2.0.5"
+ resolved "https://registry.yarnpkg.com/undefsafe/-/undefsafe-2.0.5.tgz#38733b9327bdcd226db889fb723a6efd162e6e2c"
+ integrity sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==
+
underscore@~1.12.1:
version "1.12.1"
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.12.1.tgz#7bb8cc9b3d397e201cf8553336d262544ead829e"
@@ -10108,6 +10554,11 @@ uvu@^0.5.0:
kleur "^4.0.3"
sade "^1.7.3"
+v8-compile-cache-lib@^3.0.1:
+ version "3.0.1"
+ resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf"
+ integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==
+
v8-to-istanbul@^8.1.0:
version "8.1.1"
resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-8.1.1.tgz#77b752fd3975e31bbcef938f85e9bd1c7a8d60ed"
@@ -10124,7 +10575,12 @@ v8flags@^3.1.1:
dependencies:
homedir-polyfill "^1.0.1"
-vary@~1.1.2:
+validator@^13.9.0:
+ version "13.11.0"
+ resolved "https://registry.yarnpkg.com/validator/-/validator-13.11.0.tgz#23ab3fd59290c61248364eabf4067f04955fbb1b"
+ integrity sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==
+
+vary@^1, vary@~1.1.2:
version "1.1.2"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
@@ -10194,7 +10650,7 @@ walker@^1.0.7:
dependencies:
makeerror "1.0.12"
-watchpack@^2.4.0:
+watchpack@2.4.0, watchpack@^2.4.0:
version "2.4.0"
resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d"
integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==
@@ -10615,6 +11071,11 @@ yargs@^16.2.0:
y18n "^5.0.5"
yargs-parser "^20.2.2"
+yn@3.1.1:
+ version "3.1.1"
+ resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"
+ integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==
+
yocto-queue@^0.1.0:
version "0.1.0"
resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b"