From 4fbdd9c839fe24107d5c425d5aca0af0e2c02bf5 Mon Sep 17 00:00:00 2001 From: Jovi De Croock Date: Sun, 20 Oct 2024 08:56:21 +0200 Subject: [PATCH] Styling fixes (#4249) Checked for broken styles and fixed them and also went over the links by using linkinator. I did check a lot of tools but looks like there isn't a good way at the moment to check for broken links that is maintained. Resolves https://github.com/graphql/graphql-js/issues/4242 --- cspell.yml | 1 + .../authentication-and-express-middleware.md | 53 - website/docs/tutorials/basic-types.md | 58 - website/docs/tutorials/constructing-types.md | 122 -- website/docs/tutorials/express-graphql.md | 30 - website/docs/tutorials/going-to-production.md | 127 -- website/docs/tutorials/graphql-clients.md | 84 -- website/docs/tutorials/hello.png | Bin 25470 -> 0 bytes website/docs/tutorials/index.md | 61 - .../tutorials/mutations-and-input-types.md | 189 --- website/docs/tutorials/object-types.md | 145 -- website/docs/tutorials/passing-arguments.md | 130 -- .../running-an-express-graphql-server.md | 59 - website/package-lock.json | 1325 ++++++++++++++++- website/package.json | 4 + website/pages/_app.tsx | 1 + website/pages/_document.tsx | 2 +- website/pages/index.mdx | 5 +- website/postcss.config.js | 7 + website/tailwind.config.js | 41 + website/theme.config.tsx | 51 +- 21 files changed, 1408 insertions(+), 1087 deletions(-) delete mode 100644 website/docs/tutorials/authentication-and-express-middleware.md delete mode 100644 website/docs/tutorials/basic-types.md delete mode 100644 website/docs/tutorials/constructing-types.md delete mode 100644 website/docs/tutorials/express-graphql.md delete mode 100644 website/docs/tutorials/going-to-production.md delete mode 100644 website/docs/tutorials/graphql-clients.md delete mode 100644 website/docs/tutorials/hello.png delete mode 100644 website/docs/tutorials/index.md delete mode 100644 website/docs/tutorials/mutations-and-input-types.md delete mode 100644 website/docs/tutorials/object-types.md delete mode 100644 website/docs/tutorials/passing-arguments.md delete mode 100644 website/docs/tutorials/running-an-express-graphql-server.md create mode 100644 website/postcss.config.js create mode 100644 website/tailwind.config.js diff --git a/cspell.yml b/cspell.yml index 254bd2a20c..f5639f52f2 100644 --- a/cspell.yml +++ b/cspell.yml @@ -105,6 +105,7 @@ words: - Nextra - headlessui - Fastify + - tailwindcss - svgr - ruru diff --git a/website/docs/tutorials/authentication-and-express-middleware.md b/website/docs/tutorials/authentication-and-express-middleware.md deleted file mode 100644 index 06e3adcf95..0000000000 --- a/website/docs/tutorials/authentication-and-express-middleware.md +++ /dev/null @@ -1,53 +0,0 @@ ---- -title: Authentication and Express Middleware -sidebar_label: Authentication & Middleware ---- - -It's simple to use any Express middleware in conjunction with `express-graphql`. In particular, this is a great pattern for handling authentication. - -To use middleware with a GraphQL resolver, just use the middleware like you would with a normal Express app. The `request` object is then available as the second argument in any resolver. - -For example, let's say we wanted our server to log the IP address of every request, and we also want to write an API that returns the IP address of the caller. We can do the former with middleware, and the latter by accessing the `request` object in a resolver. Here's server code that implements this: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let { buildSchema } = require('graphql'); - -let schema = buildSchema(` - type Query { - ip: String - } -`); - -function loggingMiddleware(req, res, next) { - console.log('ip:', req.ip); - next(); -} - -let root = { - ip: function (args, request) { - return request.ip; - }, -}; - -let app = express(); -app.use(loggingMiddleware); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -In a REST API, authentication is often handled with a header, that contains an auth token which proves what user is making this request. Express middleware processes these headers and puts authentication data on the Express `request` object. Some middleware modules that handle authentication like this are [Passport](http://passportjs.org/), [express-jwt](https://github.com/auth0/express-jwt), and [express-session](https://github.com/expressjs/session). Each of these modules works with `express-graphql`. - -If you aren't familiar with any of these authentication mechanisms, we recommend using `express-jwt` because it's simple without sacrificing any future flexibility. - -If you've read through the docs linearly to get to this point, congratulations! You now know everything you need to build a practical GraphQL API server. diff --git a/website/docs/tutorials/basic-types.md b/website/docs/tutorials/basic-types.md deleted file mode 100644 index 7eeb21d495..0000000000 --- a/website/docs/tutorials/basic-types.md +++ /dev/null @@ -1,58 +0,0 @@ ---- -title: Basic Types ---- - -In most situations, all you need to do is to specify the types for your API using the GraphQL schema language, taken as an argument to the `buildSchema` function. - -The GraphQL schema language supports the scalar types of `String`, `Int`, `Float`, `Boolean`, and `ID`, so you can use these directly in the schema you pass to `buildSchema`. - -By default, every type is nullable - it's legitimate to return `null` as any of the scalar types. Use an exclamation point to indicate a type cannot be nullable, so `String!` is a non-nullable string. - -To use a list type, surround the type in square brackets, so `[Int]` is a list of integers. - -Each of these types maps straightforwardly to JavaScript, so you can just return plain old JavaScript objects in APIs that return these types. Here's an example that shows how to use some of these basic types: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - type Query { - quoteOfTheDay: String - random: Float! - rollThreeDice: [Int] - } -`); - -// The root provides a resolver function for each API endpoint -let root = { - quoteOfTheDay: () => { - return Math.random() < 0.5 ? 'Take it easy' : 'Salvation lies within'; - }, - random: () => { - return Math.random(); - }, - rollThreeDice: () => { - return [1, 2, 3].map((_) => 1 + Math.floor(Math.random() * 6)); - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs. - -These examples show you how to call APIs that return different types. To send different types of data into an API, you will also need to learn about [passing arguments to a GraphQL API](./passing-arguments.md). diff --git a/website/docs/tutorials/constructing-types.md b/website/docs/tutorials/constructing-types.md deleted file mode 100644 index 5d2fe502a7..0000000000 --- a/website/docs/tutorials/constructing-types.md +++ /dev/null @@ -1,122 +0,0 @@ ---- -title: Constructing Types -category: Advanced Guides ---- - -For many apps, you can define a fixed schema when the application starts, and define it using GraphQL schema language. In some cases, it's useful to construct a schema programmatically. You can do this using the `GraphQLSchema` constructor. - -When you are using the `GraphQLSchema` constructor to create a schema, instead of defining `Query` and `Mutation` types solely using schema language, you create them as separate object types. - -For example, let's say we are building a simple API that lets you fetch user data for a few hardcoded users based on an id. Using `buildSchema` we could write a server with: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let { buildSchema } = require('graphql'); - -let schema = buildSchema(` - type User { - id: String - name: String - } - - type Query { - user(id: String): User - } -`); - -// Maps id to User object -let fakeDatabase = { - a: { - id: 'a', - name: 'alice', - }, - b: { - id: 'b', - name: 'bob', - }, -}; - -let root = { - user: function ({ id }) { - return fakeDatabase[id]; - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -We can implement this same API without using GraphQL schema language: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let graphql = require('graphql'); - -// Maps id to User object -let fakeDatabase = { - a: { - id: 'a', - name: 'alice', - }, - b: { - id: 'b', - name: 'bob', - }, -}; - -// Define the User type -let userType = new graphql.GraphQLObjectType({ - name: 'User', - fields: { - id: { type: graphql.GraphQLString }, - name: { type: graphql.GraphQLString }, - }, -}); - -// Define the Query type -let queryType = new graphql.GraphQLObjectType({ - name: 'Query', - fields: { - user: { - type: userType, - // `args` describes the arguments that the `user` query accepts - args: { - id: { type: graphql.GraphQLString }, - }, - resolve: function (_, { id }) { - return fakeDatabase[id]; - }, - }, - }, -}); - -let schema = new graphql.GraphQLSchema({ query: queryType }); - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -When we use this method of creating the API, the root level resolvers are implemented on the `Query` and `Mutation` types rather than on a `root` object. - -This is particularly useful if you want to create a GraphQL schema automatically from something else, like a database schema. You might have a common format for something like creating and updating database records. This is also useful for implementing features like union types which don't map cleanly to ES6 classes and schema language. diff --git a/website/docs/tutorials/express-graphql.md b/website/docs/tutorials/express-graphql.md deleted file mode 100644 index d9975b1bb1..0000000000 --- a/website/docs/tutorials/express-graphql.md +++ /dev/null @@ -1,30 +0,0 @@ ---- -title: express-graphql ---- - -The `express-graphql` module provides a simple way to create an [Express](https://expressjs.com/) server that runs a GraphQL API. - -```js -import { graphqlHTTP } from 'express-graphql'; // ES6 -const { graphqlHTTP } = require('express-graphql'); // CommonJS -``` - -### graphqlHTTP - -```js -graphqlHTTP({ - schema: GraphQLSchema, - graphiql?: ?boolean, - rootValue?: ?any, - context?: ?any, - pretty?: ?boolean, - formatError?: ?Function, - validationRules?: ?Array, -}): Middleware -``` - -Constructs an Express application based on a GraphQL schema. - -See the [express-graphql tutorial](./running-an-express-graphql-server.md) for sample usage. - -See the [GitHub README](https://github.com/graphql/express-graphql) for more extensive documentation of the details of this method. diff --git a/website/docs/tutorials/going-to-production.md b/website/docs/tutorials/going-to-production.md deleted file mode 100644 index fcc4a9ca37..0000000000 --- a/website/docs/tutorials/going-to-production.md +++ /dev/null @@ -1,127 +0,0 @@ ---- -title: Going to production -category: FAQ ---- - -GraphQL.JS contains a few development checks which in production will cause slower performance and -an increase in bundle-size. Every bundler goes about these changes different, in here we'll list -out the most popular ones. - -## Bundler-specific configuration - -Here are some bundler-specific suggestions for configuring your bundler to remove `globalThis.process` and `process.env.NODE_ENV` on build time. - -### Vite - -```js -export default defineConfig({ - // ... - define: { - 'globalThis.process': JSON.stringify(true), - 'process.env.NODE_ENV': JSON.stringify('production'), - }, -}); -``` - -### Next.js - -```js -// ... -/** @type {import('next').NextConfig} */ -const nextConfig = { - webpack(config, { webpack }) { - config.plugins.push( - new webpack.DefinePlugin({ - 'globalThis.process': JSON.stringify(true), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - ); - return config; - }, -}; - -module.exports = nextConfig; -``` - -### create-react-app - -With `create-react-app`, you need to use a third-party package like [`craco`](https://craco.js.org/) to modify the bundler configuration. - -```js -const webpack = require('webpack'); -module.exports = { - webpack: { - plugins: [ - new webpack.DefinePlugin({ - 'globalThis.process': JSON.stringify(true), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), - ], - }, -}; -``` - -### esbuild - -```json -{ - "define": { - "globalThis.process": true, - "process.env.NODE_ENV": "production" - } -} -``` - -### Webpack - -```js -config.plugins.push( - new webpack.DefinePlugin({ - 'globalThis.process': JSON.stringify(true), - 'process.env.NODE_ENV': JSON.stringify('production'), - }), -); -``` - -### Rollup - -```js -export default [ - { - // ... input, output, etc. - plugins: [ - minify({ - mangle: { - toplevel: true, - }, - compress: { - toplevel: true, - global_defs: { - '@globalThis.process': JSON.stringify(true), - '@process.env.NODE_ENV': JSON.stringify('production'), - }, - }, - }), - ], - }, -]; -``` - -### SWC - -```json title=".swcrc" -{ - "jsc": { - "transform": { - "optimizer": { - "globals": { - "vars": { - "globalThis.process": true, - "process.env.NODE_ENV": "production" - } - } - } - } - } -} -``` diff --git a/website/docs/tutorials/graphql-clients.md b/website/docs/tutorials/graphql-clients.md deleted file mode 100644 index cecab28536..0000000000 --- a/website/docs/tutorials/graphql-clients.md +++ /dev/null @@ -1,84 +0,0 @@ ---- -title: GraphQL Clients -category: GraphQL.js Tutorial ---- - -Since a GraphQL API has more underlying structure than a REST API, there are more powerful clients like [Relay](https://facebook.github.io/relay/) which can automatically handle batching, caching, and other features. But you don't need a complex client to call a GraphQL server. With `express-graphql`, you can just send an HTTP POST request to the endpoint you mounted your GraphQL server on, passing the GraphQL query as the `query` field in a JSON payload. - -For example, let's say we mounted a GraphQL server on http://localhost:4000/graphql as in the example code for [running an Express GraphQL server](./running-an-express-graphql-server.md), and we want to send the GraphQL query `{ hello }`. We can do this from the command line with `curl`. If you paste this into a terminal: - -```bash -curl -X POST \ --H "Content-Type: application/json" \ --d '{"query": "{ hello }"}' \ -http://localhost:4000/graphql -``` - -You should see the output returned as JSON: - -``` -{"data":{"hello":"Hello world!"}} -``` - -If you prefer to use a graphical user interface to send a test query, you can use clients such as [GraphiQL](https://github.com/graphql/graphiql) and [Insomnia](https://github.com/getinsomnia/insomnia). - -It's also simple to send GraphQL from the browser. Open up http://localhost:4000, open a developer console, and paste in: - -```js -fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ query: '{ hello }' }), -}) - .then((r) => r.json()) - .then((data) => console.log('data returned:', data)); -``` - -You should see the data returned, logged in the console: - -``` -data returned: Object { hello: "Hello world!" } -``` - -In this example, the query was just a hardcoded string. As your application becomes more complex, and you add GraphQL endpoints that take arguments as described in [Passing Arguments](./passing-arguments.md), you will want to construct GraphQL queries using variables in client code. You can do this by including a keyword prefixed with a dollar sign in the query, and passing an extra `variables` field on the payload. - -For example, let's say you're running the example server from [Passing Arguments](./passing-arguments.md) that has a schema of - -```graphql -type Query { - rollDice(numDice: Int!, numSides: Int): [Int] -} -``` - -You could access this from JavaScript with the code: - -```js -let dice = 3; -let sides = 6; -let query = `query RollDice($dice: Int!, $sides: Int) { - rollDice(numDice: $dice, numSides: $sides) -}`; - -fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - query, - variables: { dice, sides }, - }), -}) - .then((r) => r.json()) - .then((data) => console.log('data returned:', data)); -``` - -Using this syntax for variables is a good idea because it automatically prevents bugs due to escaping, and it makes it easier to monitor your server. - -In general, it will take a bit more time to set up a GraphQL client like Relay, but it's worth it to get more features as your application grows. You might want to start out just using HTTP requests as the underlying transport layer, and switching to a more complex client as your application gets more complex. - -At this point you can write a client and server in GraphQL for an API that receives a single string. To do more, you will want to [learn how to use the other basic data types](./basic-types.md). diff --git a/website/docs/tutorials/hello.png b/website/docs/tutorials/hello.png deleted file mode 100644 index e1d56100da6b061b19270e7639c22d9ee3630c23..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 25470 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 { - return 'Hello world!'; - }, -}; - -// Run the GraphQL query '{ hello }' and print out the response -graphql({ schema, source: '{ hello }', rootValue: root }).then((response) => { - console.log(JSON.stringify(response, null, 2)); -}); -``` - -If you run this with: - -```bash -node server.js -``` - -You should see the GraphQL response printed out: - -```js -{ - "data": { - "hello": "Hello world!" - } -} -``` - -Congratulations - you just executed a GraphQL query! - -For practical applications, you'll probably want to run GraphQL queries from an API server, rather than executing GraphQL with a command line tool. To use GraphQL for an API server over HTTP, check out [Running an Express GraphQL Server](./running-an-express-graphql-server.md). diff --git a/website/docs/tutorials/mutations-and-input-types.md b/website/docs/tutorials/mutations-and-input-types.md deleted file mode 100644 index f7607caf45..0000000000 --- a/website/docs/tutorials/mutations-and-input-types.md +++ /dev/null @@ -1,189 +0,0 @@ ---- -title: Mutations and Input Types ---- - -If you have an API endpoint that alters data, like inserting data into a database or altering data already in a database, you should make this endpoint a `Mutation` rather than a `Query`. This is as simple as making the API endpoint part of the top-level `Mutation` type instead of the top-level `Query` type. - -Let's say we have a “message of the day” server, where anyone can update the message of the day, and anyone can read the current one. The GraphQL schema for this is simply: - -```graphql -type Mutation { - setMessage(message: String): String -} - -type Query { - getMessage: String -} -``` - -It's often convenient to have a mutation that maps to a database create or update operation, like `setMessage`, return the same thing that the server stored. That way, if you modify the data on the server, the client can learn about those modifications. - -Both mutations and queries can be handled by root resolvers, so the root that implements this schema can simply be: - -```js -let fakeDatabase = {}; -let root = { - setMessage: function ({ message }) { - fakeDatabase.message = message; - return message; - }, - getMessage: function () { - return fakeDatabase.message; - }, -}; -``` - -You don't need anything more than this to implement mutations. But in many cases, you will find a number of different mutations that all accept the same input parameters. A common example is that creating an object in a database and updating an object in a database often take the same parameters. To make your schema simpler, you can use “input types” for this, by using the `input` keyword instead of the `type` keyword. - -For example, instead of a single message of the day, let's say we have many messages, indexed in a database by the `id` field, and each message has both a `content` string and an `author` string. We want a mutation API both for creating a new message and for updating an old message. We could use the schema: - -```graphql -input MessageInput { - content: String - author: String -} - -type Message { - id: ID! - content: String - author: String -} - -type Query { - getMessage(id: ID!): Message -} - -type Mutation { - createMessage(input: MessageInput): Message - updateMessage(id: ID!, input: MessageInput): Message -} -``` - -Here, the mutations return a `Message` type, so that the client can get more information about the newly-modified `Message` in the same request as the request that mutates it. - -Input types can't have fields that are other objects, only basic scalar types, list types, and other input types. - -Naming input types with `Input` on the end is a useful convention, because you will often want both an input type and an output type that are slightly different for a single conceptual object. - -Here's some runnable code that implements this schema, keeping the data in memory: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - input MessageInput { - content: String - author: String - } - - type Message { - id: ID! - content: String - author: String - } - - type Query { - getMessage(id: ID!): Message - } - - type Mutation { - createMessage(input: MessageInput): Message - updateMessage(id: ID!, input: MessageInput): Message - } -`); - -// If Message had any complex fields, we'd put them on this object. -class Message { - constructor(id, { content, author }) { - this.id = id; - this.content = content; - this.author = author; - } -} - -// Maps username to content -let fakeDatabase = {}; - -let root = { - getMessage: function ({ id }) { - if (!fakeDatabase[id]) { - throw new Error('no message exists with id ' + id); - } - return new Message(id, fakeDatabase[id]); - }, - createMessage: function ({ input }) { - // Create a random id for our "database". - let id = require('crypto').randomBytes(10).toString('hex'); - - fakeDatabase[id] = input; - return new Message(id, input); - }, - updateMessage: function ({ id, input }) { - if (!fakeDatabase[id]) { - throw new Error('no message exists with id ' + id); - } - // This replaces all old data, but some apps might want partial update. - fakeDatabase[id] = input; - return new Message(id, input); - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -To call a mutation, you must use the keyword `mutation` before your GraphQL query. To pass an input type, provide the data written as if it's a JSON object. For example, with the server defined above, you can create a new message and return the `id` of the new message with this operation: - -```graphql -mutation { - createMessage(input: { author: "andy", content: "hope is a good thing" }) { - id - } -} -``` - -You can use variables to simplify mutation client logic just like you can with queries. For example, some JavaScript code that calls the server to execute this mutation is: - -```js -let author = 'andy'; -let content = 'hope is a good thing'; -let query = `mutation CreateMessage($input: MessageInput) { - createMessage(input: $input) { - id - } -}`; - -fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - query, - variables: { - input: { - author, - content, - }, - }, - }), -}) - .then((r) => r.json()) - .then((data) => console.log('data returned:', data)); -``` - -One particular type of mutation is operations that change users, like signing up a new user. While you can implement this using GraphQL mutations, you can reuse many existing libraries if you learn about [GraphQL with authentication and Express middleware](./authentication-and-express-middleware.md). diff --git a/website/docs/tutorials/object-types.md b/website/docs/tutorials/object-types.md deleted file mode 100644 index a3257826b7..0000000000 --- a/website/docs/tutorials/object-types.md +++ /dev/null @@ -1,145 +0,0 @@ ---- -title: Object Types -category: GraphQL.js Tutorial ---- - -In many cases, you don't want to return a number or a string from an API. You want to return an object that has its own complex behavior. GraphQL is a perfect fit for this. - -In GraphQL schema language, the way you define a new object type is the same way we have been defining the `Query` type in our examples. Each object can have fields that return a particular type, and methods that take arguments. For example, in the [Passing Arguments](./passing-arguments.md) documentation, we had a method to roll some random dice: - -```graphql -type Query { - rollDice(numDice: Int!, numSides: Int): [Int] -} -``` - -If we wanted to have more and more methods based on a random die over time, we could implement this with a `RandomDie` object type instead. - -```graphql -type RandomDie { - roll(numRolls: Int!): [Int] -} - -type Query { - getDie(numSides: Int): RandomDie -} -``` - -Instead of a root-level resolver for the `RandomDie` type, we can instead use an ES6 class, where the resolvers are instance methods. This code shows how the `RandomDie` schema above can be implemented: - -```js -class RandomDie { - constructor(numSides) { - this.numSides = numSides; - } - - rollOnce() { - return 1 + Math.floor(Math.random() * this.numSides); - } - - roll({ numRolls }) { - let output = []; - for (let i = 0; i < numRolls; i++) { - output.push(this.rollOnce()); - } - return output; - } -} - -let root = { - getDie: function ({ numSides }) { - return new RandomDie(numSides || 6); - }, -}; -``` - -For fields that don't use any arguments, you can use either properties on the object or instance methods. So for the example code above, both `numSides` and `rollOnce` can actually be used to implement GraphQL fields, so that code also implements the schema of: - -```graphql -type RandomDie { - numSides: Int! - rollOnce: Int! - roll(numRolls: Int!): [Int] -} - -type Query { - getDie(numSides: Int): RandomDie -} -``` - -Putting this all together, here is some sample code that runs a server with this GraphQL API: - -```js -let express = require('express'); -let { graphqlHTTP } = require('express-graphql'); -let { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - type RandomDie { - numSides: Int! - rollOnce: Int! - roll(numRolls: Int!): [Int] - } - - type Query { - getDie(numSides: Int): RandomDie - } -`); - -// This class implements the RandomDie GraphQL type -class RandomDie { - constructor(numSides) { - this.numSides = numSides; - } - - rollOnce() { - return 1 + Math.floor(Math.random() * this.numSides); - } - - roll({ numRolls }) { - let output = []; - for (let i = 0; i < numRolls; i++) { - output.push(this.rollOnce()); - } - return output; - } -} - -// The root provides the top-level API endpoints -let root = { - getDie: function ({ numSides }) { - return new RandomDie(numSides || 6); - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -When you issue a GraphQL query against an API that returns object types, you can call multiple methods on the object at once by nesting the GraphQL field names. For example, if you wanted to call both `rollOnce` to roll a die once, and `roll` to roll a die three times, you could do it with this query: - -```graphql -{ - getDie(numSides: 6) { - rollOnce - roll(numRolls: 3) - } -} -``` - -If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out these APIs with GraphiQL. - -This way of defining object types often provides advantages over a traditional REST API. Instead of doing one API request to get basic information about an object, and then multiple subsequent API requests to find out more information about that object, you can get all of that information in one API request. That saves bandwidth, makes your app run faster, and simplifies your client-side logic. - -So far, every API we've looked at is designed for returning data. In order to modify stored data or handle complex input, it helps to [learn about mutations and input types](./mutations-and-input-types.md). diff --git a/website/docs/tutorials/passing-arguments.md b/website/docs/tutorials/passing-arguments.md deleted file mode 100644 index 783e529a33..0000000000 --- a/website/docs/tutorials/passing-arguments.md +++ /dev/null @@ -1,130 +0,0 @@ ---- -title: Passing Arguments ---- - -Just like a REST API, it's common to pass arguments to an endpoint in a GraphQL API. By defining the arguments in the schema language, type checking happens automatically. Each argument must be named and have a type. For example, in the [Basic Types documentation](./basic-types.md) we had an endpoint called `rollThreeDice`: - -```graphql -type Query { - rollThreeDice: [Int] -} -``` - -Instead of hard-coding “three”, we might want a more general function that rolls `numDice` dice, each of which have `numSides` sides. We can add arguments to the GraphQL schema language like this: - -```graphql -type Query { - rollDice(numDice: Int!, numSides: Int): [Int] -} -``` - -The exclamation point in `Int!` indicates that `numDice` can't be null, which means we can skip a bit of validation logic to make our server code simpler. We can let `numSides` be null and assume that by default a die has 6 sides. - -So far, our resolver functions took no arguments. When a resolver takes arguments, they are passed as one “args” object, as the first argument to the function. So rollDice could be implemented as: - -```js -let root = { - rollDice: function (args) { - let output = []; - for (let i = 0; i < args.numDice; i++) { - output.push(1 + Math.floor(Math.random() * (args.numSides || 6))); - } - return output; - }, -}; -``` - -It's convenient to use [ES6 destructuring assignment](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment) for these parameters, since you know what format they will be. So we can also write `rollDice` as - -```js -let root = { - rollDice: function ({ numDice, numSides }) { - let output = []; - for (let i = 0; i < numDice; i++) { - output.push(1 + Math.floor(Math.random() * (numSides || 6))); - } - return output; - }, -}; -``` - -If you're familiar with destructuring, this is a bit nicer because the line of code where `rollDice` is defined tells you about what the arguments are. - -The entire code for a server that hosts this `rollDice` API is: - -```js -const express = require('express'); -const { graphqlHTTP } = require('express-graphql'); -const { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - type Query { - rollDice(numDice: Int!, numSides: Int): [Int] - } -`); - -// The root provides a resolver function for each API endpoint -let root = { - rollDice: function ({ numDice, numSides }) { - let output = []; - for (let i = 0; i < numDice; i++) { - output.push(1 + Math.floor(Math.random() * (numSides || 6))); - } - return output; - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -When you call this API, you have to pass each argument by name. So for the server above, you could issue this GraphQL query to roll three six-sided dice: - -```graphql -{ - rollDice(numDice: 3, numSides: 6) -} -``` - -If you run this code with `node server.js` and browse to http://localhost:4000/graphql you can try out this API. - -When you're passing arguments in code, it's generally better to avoid constructing the whole query string yourself. Instead, you can use `$` syntax to define variables in your query, and pass the variables as a separate map. - -For example, some JavaScript code that calls our server above is: - -```js -let dice = 3; -let sides = 6; -let query = `query RollDice($dice: Int!, $sides: Int) { - rollDice(numDice: $dice, numSides: $sides) -}`; - -fetch('/graphql', { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - Accept: 'application/json', - }, - body: JSON.stringify({ - query, - variables: { dice, sides }, - }), -}) - .then((r) => r.json()) - .then((data) => console.log('data returned:', data)); -``` - -Using `$dice` and `$sides` as variables in GraphQL means we don't have to worry about escaping on the client side. - -With basic types and argument passing, you can implement anything you can implement in a REST API. But GraphQL supports even more powerful queries. You can replace multiple API calls with a single API call if you learn how to [define your own object types](./object-types.md). diff --git a/website/docs/tutorials/running-an-express-graphql-server.md b/website/docs/tutorials/running-an-express-graphql-server.md deleted file mode 100644 index 1f2a33b31b..0000000000 --- a/website/docs/tutorials/running-an-express-graphql-server.md +++ /dev/null @@ -1,59 +0,0 @@ ---- -title: Running an Express GraphQL Server -sidebar_label: Running Express + GraphQL ---- - -The simplest way to run a GraphQL API server is to use [Express](https://expressjs.com), a popular web application framework for Node.js. You will need to install two additional dependencies: - -```bash -npm install express express-graphql graphql --save -``` - -Let's modify our “hello world” example so that it's an API server rather than a script that runs a single query. We can use the 'express' module to run a web server, and instead of executing a query directly with the `graphql` function, we can use the `express-graphql` library to mount a GraphQL API server on the “/graphql” HTTP endpoint: - -```js -const express = require('express'); -const { graphqlHTTP } = require('express-graphql'); -const { buildSchema } = require('graphql'); - -// Construct a schema, using GraphQL schema language -let schema = buildSchema(` - type Query { - hello: String - } -`); - -// The root provides a resolver function for each API endpoint -let root = { - hello: () => { - return 'Hello world!'; - }, -}; - -let app = express(); -app.use( - '/graphql', - graphqlHTTP({ - schema: schema, - rootValue: root, - graphiql: true, - }), -); -app.listen(4000, () => { - console.log('Running a GraphQL API server at localhost:4000/graphql'); -}); -``` - -You can run this GraphQL server with: - -```bash -node server.js -``` - -Since we configured `graphqlHTTP` with `graphiql: true`, you can use the GraphiQL tool to manually issue GraphQL queries. If you navigate in a web browser to `http://localhost:4000/graphql`, you should see an interface that lets you enter queries. It should look like: - -![hello world graphql example](./hello.png) - -This screen shot shows the GraphQL query `{ hello }` being issued and giving a result of `{ data: { hello: 'Hello world!' } }`. GraphiQL is a great tool for debugging and inspecting a server, so we recommend running it whenever your application is in development mode. - -At this point you have learned how to run a GraphQL server and how to use GraphiQL interface to issue queries. The next step is to learn how to [issue GraphQL queries from client code](./graphql-clients.md). diff --git a/website/package-lock.json b/website/package-lock.json index 11c94d168a..4bdfc8cfe7 100644 --- a/website/package-lock.json +++ b/website/package-lock.json @@ -9,15 +9,31 @@ "version": "0.0.0", "devDependencies": { "@svgr/webpack": "^8.1.0", + "@tailwindcss/typography": "^0.5.10", "@types/node": "^22.7.5", + "autoprefixer": "^10.4.20", "next": "^14.2.15", "nextra": "^3.0.13", "nextra-theme-docs": "^3.0.13", + "postcss": "^8.4.47", "react": "^18.3.1", "react-dom": "^18.3.1", + "tailwindcss": "^3.4.14", "typescript": "^5.6.3" } }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -1862,6 +1878,23 @@ "mlly": "^1.7.1" } }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", @@ -2370,6 +2403,51 @@ "node": ">= 10" } }, + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", + "dev": true, + "dependencies": { + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "dev": true, + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@react-aria/focus": { "version": "3.18.4", "resolved": "https://registry.npmjs.org/@react-aria/focus/-/focus-3.18.4.tgz", @@ -2788,6 +2866,21 @@ "tslib": "^2.4.0" } }, + "node_modules/@tailwindcss/typography": { + "version": "0.5.15", + "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz", + "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==", + "dev": true, + "dependencies": { + "lodash.castarray": "^4.4.0", + "lodash.isplainobject": "^4.0.6", + "lodash.merge": "^4.6.2", + "postcss-selector-parser": "6.0.10" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20" + } + }, "node_modules/@tanstack/react-virtual": { "version": "3.10.8", "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.8.tgz", @@ -2997,6 +3090,18 @@ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" } }, + "node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, "node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", @@ -3009,6 +3114,25 @@ "node": ">=4" } }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "dev": true + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/arch": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", @@ -3063,6 +3187,43 @@ "astring": "bin/astring" } }, + "node_modules/autoprefixer": { + "version": "10.4.20", + "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz", + "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/autoprefixer" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "browserslist": "^4.23.3", + "caniuse-lite": "^1.0.30001646", + "fraction.js": "^4.3.7", + "normalize-range": "^0.1.2", + "picocolors": "^1.0.1", + "postcss-value-parser": "^4.2.0" + }, + "bin": { + "autoprefixer": "bin/autoprefixer" + }, + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, "node_modules/babel-plugin-polyfill-corejs2": { "version": "0.4.11", "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz", @@ -3112,6 +3273,12 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "dev": true + }, "node_modules/better-react-mathjax": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/better-react-mathjax/-/better-react-mathjax-2.0.3.tgz", @@ -3124,12 +3291,45 @@ "react": ">=16.8" } }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dev": true, + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/browserslist": { "version": "4.24.0", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.0.tgz", @@ -3195,6 +3395,15 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/camelcase-css": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", + "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/caniuse-lite": { "version": "1.0.30001669", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001669.tgz", @@ -3314,6 +3523,42 @@ "chevrotain": "^11.0.0" } }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/client-only": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/client-only/-/client-only-0.0.1.tgz", @@ -3522,6 +3767,18 @@ "url": "https://github.com/sponsors/fb55" } }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "dev": true, + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/csso": { "version": "5.0.5", "resolved": "https://registry.npmjs.org/csso/-/csso-5.0.5.tgz", @@ -4146,6 +4403,18 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/didyoumean": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz", + "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==", + "dev": true + }, + "node_modules/dlv": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", + "dev": true + }, "node_modules/dom-serializer": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", @@ -4217,12 +4486,24 @@ "tslib": "^2.0.3" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true + }, "node_modules/electron-to-chromium": { "version": "1.5.39", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.39.tgz", "integrity": "sha512-4xkpSR6CjuiaNyvwiWDI85N9AxsvbPawB8xc7yzLPonYTuP19BVgYweKyUMFtHEZgIcHWMt1ks5Cqx2m+6/Grg==", "dev": true }, + "node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true + }, "node_modules/entities": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", @@ -4421,6 +4702,43 @@ "node": ">=0.10.0" } }, + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, + "dependencies": { + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" + } + }, + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "dependencies": { + "reusify": "^1.0.4" + } + }, "node_modules/fault": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/fault/-/fault-2.0.1.tgz", @@ -4434,12 +4752,111 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/flexsearch": { "version": "0.7.43", "resolved": "https://registry.npmjs.org/flexsearch/-/flexsearch-0.7.43.tgz", "integrity": "sha512-c5o/+Um8aqCSOXGcZoqZOm+NqtVwNsvVpWv6lfmSclU954O3wvQKxxK8zj74fPaSJbXpSLTs4PRhh+wnoCXnKg==", "dev": true }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dev": true, + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/foreground-child/node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dev": true, + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dev": true, + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, "node_modules/format": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/format/-/format-0.2.2.tgz", @@ -4449,6 +4866,33 @@ "node": ">=0.4.x" } }, + "node_modules/fraction.js": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz", + "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==", + "dev": true, + "engines": { + "node": "*" + }, + "funding": { + "type": "patreon", + "url": "https://github.com/sponsors/rawify" + } + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", @@ -4482,9 +4926,41 @@ "integrity": "sha512-IaOQ9puYtjrkq7Y0Ygl9KDZnrf/aiUJYUpVf89y8kyaxbRG7Y1SrX/jaumrv81vc61+kiMempujsM3Yw7w5qcw==", "dev": true }, - "node_modules/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.3" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "engines": { @@ -4913,6 +5389,18 @@ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", @@ -4947,6 +5435,36 @@ "node": ">=0.10.0" } }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/is-hexadecimal": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/is-hexadecimal/-/is-hexadecimal-2.0.1.tgz", @@ -4957,6 +5475,15 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-plain-obj": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-4.1.0.tgz", @@ -4993,6 +5520,30 @@ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jiti": { + "version": "1.21.6", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz", + "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==", + "dev": true, + "bin": { + "jiti": "bin/jiti.js" + } + }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -5101,6 +5652,15 @@ "integrity": "sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==", "dev": true }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "dev": true, + "engines": { + "node": ">=10" + } + }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", @@ -5129,12 +5689,30 @@ "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "dev": true }, + "node_modules/lodash.castarray": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz", + "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==", + "dev": true + }, "node_modules/lodash.debounce": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", "dev": true }, + "node_modules/lodash.isplainobject": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz", + "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==", + "dev": true + }, + "node_modules/lodash.merge": { + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz", + "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==", + "dev": true + }, "node_modules/longest-streak": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/longest-streak/-/longest-streak-3.1.0.tgz", @@ -5551,6 +6129,15 @@ "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==", "dev": true }, + "node_modules/merge2": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", + "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", + "dev": true, + "engines": { + "node": ">= 8" + } + }, "node_modules/mermaid": { "version": "11.3.0", "resolved": "https://registry.npmjs.org/mermaid/-/mermaid-11.3.0.tgz", @@ -6338,6 +6925,43 @@ } ] }, + "node_modules/micromatch": { + "version": "4.0.8", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", + "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", + "dev": true, + "dependencies": { + "braces": "^3.0.3", + "picomatch": "^2.3.1" + }, + "engines": { + "node": ">=8.6" + } + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/mj-context-menu": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/mj-context-menu/-/mj-context-menu-0.6.1.tgz", @@ -6362,6 +6986,17 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "dev": true }, + "node_modules/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.0" + } + }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -6449,6 +7084,34 @@ "react-dom": "^16.8 || ^17 || ^18" } }, + "node_modules/next/node_modules/postcss": { + "version": "8.4.31", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", + "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.6", + "picocolors": "^1.0.0", + "source-map-js": "^1.0.2" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, "node_modules/nextra": { "version": "3.0.13", "resolved": "https://registry.npmjs.org/nextra/-/nextra-3.0.13.tgz", @@ -6550,6 +7213,24 @@ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-range": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz", + "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", @@ -6586,6 +7267,24 @@ "url": "https://github.com/fb55/nth-check?sponsor=1" } }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-hash": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz", + "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/oniguruma-to-js": { "version": "0.4.3", "resolved": "https://registry.npmjs.org/oniguruma-to-js/-/oniguruma-to-js-0.4.3.tgz", @@ -6622,6 +7321,12 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true + }, "node_modules/package-manager-detector": { "version": "0.2.2", "resolved": "https://registry.npmjs.org/package-manager-detector/-/package-manager-detector-0.2.2.tgz", @@ -6741,6 +7446,28 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true + }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", @@ -6773,6 +7500,27 @@ "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true }, + "node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pirates": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", + "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/pkg-types": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-1.2.1.tgz", @@ -6801,9 +7549,9 @@ } }, "node_modules/postcss": { - "version": "8.4.31", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz", - "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -6820,14 +7568,116 @@ } ], "dependencies": { - "nanoid": "^3.3.6", - "picocolors": "^1.0.0", - "source-map-js": "^1.0.2" + "nanoid": "^3.3.7", + "picocolors": "^1.1.0", + "source-map-js": "^1.2.1" }, "engines": { "node": "^10 || ^12 || >=14" } }, + "node_modules/postcss-import": { + "version": "15.1.0", + "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz", + "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==", + "dev": true, + "dependencies": { + "postcss-value-parser": "^4.0.0", + "read-cache": "^1.0.0", + "resolve": "^1.1.7" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "postcss": "^8.0.0" + } + }, + "node_modules/postcss-js": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", + "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", + "dev": true, + "dependencies": { + "camelcase-css": "^2.0.1" + }, + "engines": { + "node": "^12 || ^14 || >= 16" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": "^8.4.21" + } + }, + "node_modules/postcss-load-config": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz", + "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "lilconfig": "^3.0.0", + "yaml": "^2.3.4" + }, + "engines": { + "node": ">= 14" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-load-config/node_modules/lilconfig": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz", + "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==", + "dev": true, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antonk52" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.0.10", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz", + "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", + "dev": true + }, "node_modules/property-information": { "version": "6.5.0", "resolved": "https://registry.npmjs.org/property-information/-/property-information-6.5.0.tgz", @@ -6844,6 +7694,26 @@ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==", "dev": true }, + "node_modules/queue-microtask": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", + "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, "node_modules/react": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz", @@ -6869,6 +7739,36 @@ "react": "^18.3.1" } }, + "node_modules/read-cache": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", + "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", + "dev": true, + "dependencies": { + "pify": "^2.3.0" + } + }, + "node_modules/read-cache/node_modules/pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, "node_modules/reading-time": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/reading-time/-/reading-time-1.5.0.tgz", @@ -7326,6 +8226,16 @@ "url": "https://opencollective.com/unified" } }, + "node_modules/reusify": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", + "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", + "dev": true, + "engines": { + "iojs": ">=1.0.0", + "node": ">=0.10.0" + } + }, "node_modules/robust-predicates": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz", @@ -7344,6 +8254,29 @@ "points-on-path": "^0.2.1" } }, + "node_modules/run-parallel": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", + "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "queue-microtask": "^1.2.2" + } + }, "node_modules/rw": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz", @@ -7525,6 +8458,65 @@ "node": ">=10.0.0" } }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/stringify-entities": { "version": "4.0.4", "resolved": "https://registry.npmjs.org/stringify-entities/-/stringify-entities-4.0.4.tgz", @@ -7539,6 +8531,43 @@ "url": "https://github.com/sponsors/wooorm" } }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dev": true, + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, "node_modules/strip-bom-string": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/strip-bom-string/-/strip-bom-string-1.0.0.tgz", @@ -7595,6 +8624,37 @@ "integrity": "sha512-osIBl6BGUmSfDkyH2mB7EFvCJntXDrLhKjHTRj/rK6xLH0yuPrHULDRQzKokSOD4VoorhtKpfcfW1GAntu8now==", "dev": true }, + "node_modules/sucrase": { + "version": "3.35.0", + "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz", + "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==", + "dev": true, + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.2", + "commander": "^4.0.0", + "glob": "^10.3.10", + "lines-and-columns": "^1.1.6", + "mz": "^2.7.0", + "pirates": "^4.0.1", + "ts-interface-checker": "^0.1.9" + }, + "bin": { + "sucrase": "bin/sucrase", + "sucrase-node": "bin/sucrase-node" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/sucrase/node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "engines": { + "node": ">= 6" + } + }, "node_modules/supports-color": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-4.5.0.tgz", @@ -7665,6 +8725,108 @@ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==", "dev": true }, + "node_modules/tailwindcss": { + "version": "3.4.14", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz", + "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "arg": "^5.0.2", + "chokidar": "^3.5.3", + "didyoumean": "^1.2.2", + "dlv": "^1.1.3", + "fast-glob": "^3.3.0", + "glob-parent": "^6.0.2", + "is-glob": "^4.0.3", + "jiti": "^1.21.0", + "lilconfig": "^2.1.0", + "micromatch": "^4.0.5", + "normalize-path": "^3.0.0", + "object-hash": "^3.0.0", + "picocolors": "^1.0.0", + "postcss": "^8.4.23", + "postcss-import": "^15.1.0", + "postcss-js": "^4.0.1", + "postcss-load-config": "^4.0.1", + "postcss-nested": "^6.0.1", + "postcss-selector-parser": "^6.0.11", + "resolve": "^1.22.2", + "sucrase": "^3.32.0" + }, + "bin": { + "tailwind": "lib/cli.js", + "tailwindcss": "lib/cli.js" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/tailwindcss/node_modules/arg": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz", + "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==", + "dev": true + }, + "node_modules/tailwindcss/node_modules/postcss-nested": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz", + "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "postcss-selector-parser": "^6.1.1" + }, + "engines": { + "node": ">=12.0" + }, + "peerDependencies": { + "postcss": "^8.2.14" + } + }, + "node_modules/tailwindcss/node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dev": true, + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dev": true, + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dev": true, + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, "node_modules/tinyexec": { "version": "0.3.1", "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.1.tgz", @@ -7704,6 +8866,18 @@ "node": ">=4" } }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -7733,6 +8907,12 @@ "node": ">=6.10" } }, + "node_modules/ts-interface-checker": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz", + "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==", + "dev": true + }, "node_modules/tslib": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", @@ -8023,6 +9203,12 @@ "browserslist": ">= 4.21.0" } }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", + "dev": true + }, "node_modules/uuid": { "version": "9.0.1", "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", @@ -8155,6 +9341,127 @@ "integrity": "sha512-Gd9+TUn5nXdwj/hFsPVx5cuHHiF5Bwuc30jZ4+ronF1qHK5O7HD0sgmXWSEgwKquT3ClLoKPVbO6qGwVwLzvAw==", "dev": true }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dev": true, + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dev": true, + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "dev": true + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, "node_modules/xmldom-sre": { "version": "0.1.31", "resolved": "https://registry.npmjs.org/xmldom-sre/-/xmldom-sre-0.1.31.tgz", diff --git a/website/package.json b/website/package.json index bd8c58df90..a69e6e4043 100644 --- a/website/package.json +++ b/website/package.json @@ -12,12 +12,16 @@ }, "devDependencies": { "@svgr/webpack": "^8.1.0", + "@tailwindcss/typography": "^0.5.10", "@types/node": "^22.7.5", + "autoprefixer": "^10.4.20", "next": "^14.2.15", "nextra": "^3.0.13", "nextra-theme-docs": "^3.0.13", + "postcss": "^8.4.47", "react": "^18.3.1", "react-dom": "^18.3.1", + "tailwindcss": "^3.4.14", "typescript": "^5.6.3" } } diff --git a/website/pages/_app.tsx b/website/pages/_app.tsx index c50ff45c1e..e2a04b06f1 100644 --- a/website/pages/_app.tsx +++ b/website/pages/_app.tsx @@ -2,6 +2,7 @@ import type { AppProps } from 'next/app'; import { Roboto_Flex, Roboto_Mono } from 'next/font/google'; import '../css/globals.css'; +console.log('hi'); const robotoFlex = Roboto_Flex({ subsets: ['latin'], diff --git a/website/pages/_document.tsx b/website/pages/_document.tsx index e1e9cbbb75..a5d7d88684 100644 --- a/website/pages/_document.tsx +++ b/website/pages/_document.tsx @@ -4,7 +4,7 @@ export default function Document() { return ( - +
diff --git a/website/pages/index.mdx b/website/pages/index.mdx index 8d7bc216b5..0b1f9737e0 100644 --- a/website/pages/index.mdx +++ b/website/pages/index.mdx @@ -9,7 +9,10 @@ sidebarTitle: Getting Started ## Prerequisites -Before getting started, you should have Node v6 installed, although the examples should mostly work in previous versions of Node as well. For this guide, we won't use any language features that require transpilation, but we will use some ES6 features like [Promises](http://www.html5rocks.com/en/tutorials/es6/promises/), [classes](http://javascriptplayground.com/blog/2014/07/introduction-to-es6-classes-tutorial/), and [fat arrow functions](https://strongloop.com/strongblog/an-introduction-to-javascript-es6-arrow-functions/), so if you aren't familiar with them you might want to read up on them first. +Before getting started, you should have Node v6 installed, although the examples should mostly work in previous versions of Node as well. +For this guide, we won't use any language features that require transpilation, but we will use some ES6 features like +[Promises](http://www.html5rocks.com/en/tutorials/es6/promises/), classes, +and arrow functions, so if you aren't familiar with them you might want to read up on them first. To create a new project and install GraphQL.js in your current directory: diff --git a/website/postcss.config.js b/website/postcss.config.js new file mode 100644 index 0000000000..cdbe50f3a4 --- /dev/null +++ b/website/postcss.config.js @@ -0,0 +1,7 @@ +module.exports = { + plugins: { + 'tailwindcss/nesting': {}, + tailwindcss: {}, + autoprefixer: {}, + }, +}; diff --git a/website/tailwind.config.js b/website/tailwind.config.js new file mode 100644 index 0000000000..4cc2c447a2 --- /dev/null +++ b/website/tailwind.config.js @@ -0,0 +1,41 @@ +import typography from '@tailwindcss/typography'; + +module.exports = { + content: [ + './pages/**/*.{ts,tsx,mdx}', + './icons/**/*.{ts,tsx,mdx}', + './css/**/*.css', + './theme.config.tsx', + ], + theme: { + container: { + center: true, + padding: '1rem', + }, + extend: { + colors: { + primary: '#e10098', + 'conf-black': '#0e031c', + black: '#1b1b1b', + }, + backgroundImage: { + 'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))', + 'gradient-conic': + 'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))', + }, + animation: { + scroll: + 'scroll var(--animation-duration, 40s) var(--animation-direction, forwards) linear infinite', + }, + keyframes: { + scroll: { + to: { + transform: 'translate(calc(-50% - .5rem))', + }, + }, + }, + }, + }, + plugins: [typography], + darkMode: ['class', 'html[class~="dark"]'], +}; diff --git a/website/theme.config.tsx b/website/theme.config.tsx index ba6e90665d..5d8d5ff3a7 100644 --- a/website/theme.config.tsx +++ b/website/theme.config.tsx @@ -9,8 +9,6 @@ import { TwitterIcon, } from './icons/index'; import { useRouter } from 'next/router'; -// import { createElement } from "react" -// import NextImage from "next-image-export-optimizer" const graphQLLogo = ( @@ -51,12 +49,14 @@ function Footer() { @@ -68,8 +68,11 @@ function Footer() { title: 'GraphQL Specification', url: 'https://spec.graphql.org', }, - { title: 'Libraries & Tools', url: '/code' }, - { title: 'Services & Vendors', url: '/code/?tags=services' }, + { title: 'Libraries & Tools', url: 'https://graphql.org/code' }, + { + title: 'Services & Vendors', + url: 'https://graphql.org/code/?tags=services', + }, ]} /> @@ -123,7 +138,7 @@ function Footer() { {[ { url: 'https://github.com/graphql', icon: GitHubIcon }, { url: 'https://discord.graphql.org', icon: DiscordIcon }, - { url: 'https://twitter.com/graphql', icon: TwitterIcon }, + { url: 'https://x.com/graphql', icon: TwitterIcon }, { url: 'http://stackoverflow.com/questions/tagged/graphql', icon: StackOverflowIcon, @@ -199,7 +214,7 @@ const cfg: DocsThemeConfig = { <> 🎬 That's a Wrap for GraphQLConf 2024! • Watch the Videos •{' '} Check out the recorded talks and workshops