Compare commits
14 Commits
@nhost/apo
...
feat/add-e
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f539713e10 | ||
|
|
9b150c786e | ||
|
|
3d917b6e12 | ||
|
|
7574504cd5 | ||
|
|
be9f6b6967 | ||
|
|
affe9db42a | ||
|
|
15421321f4 | ||
|
|
a4790c6eac | ||
|
|
992aa997d5 | ||
|
|
382dc11aaa | ||
|
|
1976bc48a5 | ||
|
|
38696f5e88 | ||
|
|
064ea6a337 | ||
|
|
0d323e10f5 |
5
.changeset/dry-kids-chew.md
Normal file
5
.changeset/dry-kids-chew.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@nhost/dashboard': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
feat: add empty string as default value for text in databases
|
||||||
5
.changeset/quick-keys-carry.md
Normal file
5
.changeset/quick-keys-carry.md
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
'@nhost/dashboard': minor
|
||||||
|
---
|
||||||
|
|
||||||
|
fix: update babel dependencies to address security audit vulnerabilities
|
||||||
@@ -73,7 +73,7 @@ const nhost = new NhostClient({
|
|||||||
region: '<your-region>'
|
region: '<your-region>'
|
||||||
})
|
})
|
||||||
|
|
||||||
await nhost.auth.signIn({ email: 'elon@musk.com', password: 'spaceX' })
|
await nhost.auth.signIn({ email: 'user@domain.com', password: 'userPassword' })
|
||||||
|
|
||||||
await nhost.graphql.request(`{
|
await nhost.graphql.request(`{
|
||||||
users {
|
users {
|
||||||
@@ -150,4 +150,4 @@ Here are some ways of contributing to making Nhost better:
|
|||||||
<p align="center">
|
<p align="center">
|
||||||
<img width="720" src="https://contrib.rocks/image?repo=nhost/nhost" alt="A table of avatars from the project's contributors" />
|
<img width="720" src="https://contrib.rocks/image?repo=nhost/nhost" alt="A table of avatars from the project's contributors" />
|
||||||
</p>
|
</p>
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ const { version } = require('./package.json');
|
|||||||
const cspHeader = `
|
const cspHeader = `
|
||||||
default-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run;
|
default-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run;
|
||||||
script-src 'self' 'unsafe-eval' 'unsafe-inline' cdn.segment.com js.stripe.com;
|
script-src 'self' 'unsafe-eval' 'unsafe-inline' cdn.segment.com js.stripe.com;
|
||||||
connect-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com;
|
connect-src 'self' *.nhost.run ws://*.nhost.run nhost.run ws://nhost.run discord.com api.segment.io api.segment.com cdn.segment.com nhost.zendesk.com;
|
||||||
style-src 'self' 'unsafe-inline';
|
style-src 'self' 'unsafe-inline';
|
||||||
img-src 'self' blob: data: avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run;
|
img-src 'self' blob: data: avatars.githubusercontent.com s.gravatar.com *.nhost.run nhost.run;
|
||||||
font-src 'self' data:;
|
font-src 'self' data:;
|
||||||
@@ -38,10 +38,10 @@ module.exports = withBundleAnalyzer({
|
|||||||
{
|
{
|
||||||
source: '/(.*)',
|
source: '/(.*)',
|
||||||
headers: [
|
headers: [
|
||||||
{
|
// {
|
||||||
key: 'Content-Security-Policy',
|
// key: 'Content-Security-Policy',
|
||||||
value: cspHeader.replace(/\s+/g, ' ').trim(),
|
// hgvalue: cspHeader.replace(/\s+/g, ' ').trim(),
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
key: 'X-Frame-Options',
|
key: 'X-Frame-Options',
|
||||||
value: 'DENY',
|
value: 'DENY',
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@nhost/dashboard",
|
"name": "@nhost/dashboard",
|
||||||
"version": "2.22.0",
|
"version": "2.24.0",
|
||||||
"private": true,
|
"private": true,
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"preinstall": "npx only-allow pnpm",
|
"preinstall": "npx only-allow pnpm",
|
||||||
|
|||||||
@@ -44,7 +44,10 @@ export default function BaseRecordForm({
|
|||||||
(accumulator, column) => {
|
(accumulator, column) => {
|
||||||
if (
|
if (
|
||||||
column.isPrimary ||
|
column.isPrimary ||
|
||||||
(!column.isNullable && !column.defaultValue && !column.isIdentity)
|
(!column.isNullable &&
|
||||||
|
!column.defaultValue &&
|
||||||
|
!column.isDefaultValueCustom &&
|
||||||
|
!column.isIdentity)
|
||||||
) {
|
) {
|
||||||
return {
|
return {
|
||||||
...accumulator,
|
...accumulator,
|
||||||
@@ -96,7 +99,12 @@ export default function BaseRecordForm({
|
|||||||
const gridColumn = gridColumnMap.get(columnId);
|
const gridColumn = gridColumnMap.get(columnId);
|
||||||
const value = columnValues[columnId];
|
const value = columnValues[columnId];
|
||||||
|
|
||||||
if (!value && (gridColumn?.defaultValue || gridColumn?.isIdentity)) {
|
if (
|
||||||
|
!value &&
|
||||||
|
(gridColumn?.defaultValue ||
|
||||||
|
gridColumn?.defaultValue === '' ||
|
||||||
|
gridColumn?.isIdentity)
|
||||||
|
) {
|
||||||
return {
|
return {
|
||||||
...options,
|
...options,
|
||||||
[columnId]: {
|
[columnId]: {
|
||||||
@@ -147,7 +155,7 @@ export default function BaseRecordForm({
|
|||||||
{optionalColumns.length > 0 && (
|
{optionalColumns.length > 0 && (
|
||||||
<DatabaseRecordInputGroup
|
<DatabaseRecordInputGroup
|
||||||
title="Optional columns"
|
title="Optional columns"
|
||||||
description="These columns are nullable and don't require a value."
|
description="These columns are nullable or have a default value."
|
||||||
columns={optionalColumns}
|
columns={optionalColumns}
|
||||||
autoFocusFirstInput={requiredColumns.length === 0}
|
autoFocusFirstInput={requiredColumns.length === 0}
|
||||||
sx={{ borderTopWidth: requiredColumns.length > 0 ? 1 : 0 }}
|
sx={{ borderTopWidth: requiredColumns.length > 0 ? 1 : 0 }}
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import {
|
|||||||
} from '@/features/orgs/projects/database/dataGrid/utils/postgresqlConstants';
|
} from '@/features/orgs/projects/database/dataGrid/utils/postgresqlConstants';
|
||||||
import clsx from 'clsx';
|
import clsx from 'clsx';
|
||||||
import type { PropsWithoutRef } from 'react';
|
import type { PropsWithoutRef } from 'react';
|
||||||
import { memo, useEffect, useState } from 'react';
|
import { memo, useEffect, useMemo, useState } from 'react';
|
||||||
import type { FieldError } from 'react-hook-form';
|
import type { FieldError } from 'react-hook-form';
|
||||||
import { useFormContext, useFormState, useWatch } from 'react-hook-form';
|
import { useFormContext, useFormState, useWatch } from 'react-hook-form';
|
||||||
|
|
||||||
@@ -150,6 +150,13 @@ function DefaultValueAutocomplete({ index }: FieldArrayInputProps) {
|
|||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const formattedInputValue = useMemo(() => {
|
||||||
|
if (defaultValue?.value === '') {
|
||||||
|
return "''::text";
|
||||||
|
}
|
||||||
|
return isIdentity ? '' : inputValue;
|
||||||
|
}, [isIdentity, defaultValue?.value, inputValue]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!defaultValue) {
|
if (!defaultValue) {
|
||||||
setInputValue('');
|
setInputValue('');
|
||||||
@@ -176,7 +183,7 @@ function DefaultValueAutocomplete({ index }: FieldArrayInputProps) {
|
|||||||
placeholder="NULL"
|
placeholder="NULL"
|
||||||
error={Boolean(errors?.columns?.[index]?.defaultValue)}
|
error={Boolean(errors?.columns?.[index]?.defaultValue)}
|
||||||
helperText={errors?.columns?.[index]?.defaultValue?.message}
|
helperText={errors?.columns?.[index]?.defaultValue?.message}
|
||||||
inputValue={isIdentity ? '' : inputValue}
|
inputValue={formattedInputValue}
|
||||||
onInputChange={(_event, value) => setInputValue(value)}
|
onInputChange={(_event, value) => setInputValue(value)}
|
||||||
onBlur={(event) => {
|
onBlur={(event) => {
|
||||||
if (event.target instanceof HTMLInputElement && !event.target.value) {
|
if (event.target instanceof HTMLInputElement && !event.target.value) {
|
||||||
|
|||||||
@@ -53,10 +53,10 @@ export default function CreateRecordForm({
|
|||||||
return (
|
return (
|
||||||
<FormProvider {...form}>
|
<FormProvider {...form}>
|
||||||
{error && error instanceof Error && (
|
{error && error instanceof Error && (
|
||||||
<div className="-mt-3 mb-4 px-6">
|
<div className="px-6 mb-4 -mt-3">
|
||||||
<Alert
|
<Alert
|
||||||
severity="error"
|
severity="error"
|
||||||
className="grid grid-flow-col items-center justify-between px-4 py-3"
|
className="grid items-center justify-between grid-flow-col px-4 py-3"
|
||||||
>
|
>
|
||||||
<span className="text-left">
|
<span className="text-left">
|
||||||
<strong>Error:</strong> {error.message}
|
<strong>Error:</strong> {error.message}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ export interface DatabaseRecordInputGroupProps extends BoxProps {
|
|||||||
|
|
||||||
function getPlaceholder(
|
function getPlaceholder(
|
||||||
defaultValue?: string,
|
defaultValue?: string,
|
||||||
|
isDefaultValueCustom?: boolean,
|
||||||
isIdentity?: boolean,
|
isIdentity?: boolean,
|
||||||
isNullable?: boolean,
|
isNullable?: boolean,
|
||||||
) {
|
) {
|
||||||
@@ -45,6 +46,10 @@ function getPlaceholder(
|
|||||||
return 'NULL';
|
return 'NULL';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (defaultValue === '' && isDefaultValueCustom) {
|
||||||
|
return `Automatically generated value: ''`;
|
||||||
|
}
|
||||||
|
|
||||||
if (!defaultValue) {
|
if (!defaultValue) {
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
@@ -102,6 +107,7 @@ export default function DatabaseRecordInputGroup({
|
|||||||
specificType,
|
specificType,
|
||||||
maxLength,
|
maxLength,
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
isDefaultValueCustom,
|
||||||
isPrimary,
|
isPrimary,
|
||||||
isNullable,
|
isNullable,
|
||||||
isIdentity,
|
isIdentity,
|
||||||
@@ -118,6 +124,7 @@ export default function DatabaseRecordInputGroup({
|
|||||||
|
|
||||||
const placeholder = getPlaceholder(
|
const placeholder = getPlaceholder(
|
||||||
defaultValue,
|
defaultValue,
|
||||||
|
isDefaultValueCustom,
|
||||||
isIdentity,
|
isIdentity,
|
||||||
isNullable,
|
isNullable,
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ export const dateFunctions = [
|
|||||||
* Relevant functions for PostgreSQL types.
|
* Relevant functions for PostgreSQL types.
|
||||||
*/
|
*/
|
||||||
export const postgresFunctions = {
|
export const postgresFunctions = {
|
||||||
text: ['version()', 'timeofday()'],
|
text: ['version()', 'timeofday()', "''::text"],
|
||||||
json: ['json_build_object()', 'json_build_array()'],
|
json: ['json_build_object()', 'json_build_array()'],
|
||||||
jsonb: ['jsonb_build_object()', 'jsonb_build_array()'],
|
jsonb: ['jsonb_build_object()', 'jsonb_build_array()'],
|
||||||
date: dateFunctions,
|
date: dateFunctions,
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import { Box } from '@/components/ui/v2/Box';
|
||||||
import { Button } from '@/components/ui/v2/Button';
|
import { Button } from '@/components/ui/v2/Button';
|
||||||
import { CopyIcon } from '@/components/ui/v2/icons/CopyIcon';
|
import { CopyIcon } from '@/components/ui/v2/icons/CopyIcon';
|
||||||
import { Input, inputClasses } from '@/components/ui/v2/Input';
|
import { Input, inputClasses } from '@/components/ui/v2/Input';
|
||||||
@@ -57,6 +58,14 @@ export default function DataGridTextCell<TData extends object>({
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async function handleSetToNull() {
|
||||||
|
if (onSave) {
|
||||||
|
await onSave(null);
|
||||||
|
// Unfocus the cell
|
||||||
|
cancelEditCell();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function handleInputKeyDown(event: KeyboardEvent<HTMLInputElement>) {
|
async function handleInputKeyDown(event: KeyboardEvent<HTMLInputElement>) {
|
||||||
if (
|
if (
|
||||||
event.key === 'ArrowLeft' ||
|
event.key === 'ArrowLeft' ||
|
||||||
@@ -122,36 +131,58 @@ export default function DataGridTextCell<TData extends object>({
|
|||||||
|
|
||||||
if (isEditing && isMultiline) {
|
if (isEditing && isMultiline) {
|
||||||
return (
|
return (
|
||||||
<Input
|
<Box
|
||||||
multiline
|
className="absolute top-0 z-10 -mx-0.5 h-full min-h-36 w-full"
|
||||||
ref={inputRef as Ref<HTMLInputElement>}
|
|
||||||
value={(normalizedTemporaryValue || '').replace(/\\n/gi, `\n`)}
|
|
||||||
onChange={handleChange}
|
|
||||||
onKeyDown={handleTextAreaKeyDown}
|
|
||||||
fullWidth
|
|
||||||
className="absolute top-0 z-10 -mx-0.5 h-full min-h-38"
|
|
||||||
rows={5}
|
|
||||||
sx={{
|
sx={{
|
||||||
[`&.${inputClasses.focused}`]: {
|
backgroundColor: (theme) =>
|
||||||
boxShadow: `inset 0 0 0 1.5px rgba(0, 82, 205, 1)`,
|
theme.palette.mode === 'dark'
|
||||||
borderColor: 'transparent !important',
|
? `${theme.palette.secondary[100]} !important`
|
||||||
borderRadius: 0,
|
: `${theme.palette.common.white} !important`,
|
||||||
backgroundColor: (theme) =>
|
|
||||||
theme.palette.mode === 'dark'
|
|
||||||
? `${theme.palette.secondary[100]} !important`
|
|
||||||
: `${theme.palette.common.white} !important`,
|
|
||||||
},
|
|
||||||
[`& .${inputClasses.input}`]: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
>
|
||||||
inputRoot: {
|
<Input
|
||||||
className:
|
multiline
|
||||||
'resize-none outline-none focus:outline-none !text-xs focus:ring-0',
|
ref={inputRef as Ref<HTMLInputElement>}
|
||||||
},
|
value={(normalizedTemporaryValue || '').replace(/\\n/gi, `\n`)}
|
||||||
}}
|
onChange={handleChange}
|
||||||
/>
|
onKeyDown={handleTextAreaKeyDown}
|
||||||
|
fullWidth
|
||||||
|
autoFocus
|
||||||
|
className="z-10"
|
||||||
|
rows={5}
|
||||||
|
sx={{
|
||||||
|
[`&.${inputClasses.focused}`]: {
|
||||||
|
boxShadow: `inset 0 0 0 1.5px rgba(0, 82, 205, 1)`,
|
||||||
|
borderColor: 'transparent !important',
|
||||||
|
borderRadius: 0,
|
||||||
|
backgroundColor: (theme) =>
|
||||||
|
theme.palette.mode === 'dark'
|
||||||
|
? `${theme.palette.secondary[100]} !important`
|
||||||
|
: `${theme.palette.common.white} !important`,
|
||||||
|
},
|
||||||
|
[`& .${inputClasses.input}`]: {
|
||||||
|
backgroundColor: 'transparent',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
slotProps={{
|
||||||
|
inputRoot: {
|
||||||
|
className:
|
||||||
|
'resize-none outline-none focus:outline-none !text-xs focus:ring-0',
|
||||||
|
},
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<div className="my-0 flex flex-1 items-center justify-end p-2">
|
||||||
|
<Button
|
||||||
|
className="z-10"
|
||||||
|
size="small"
|
||||||
|
variant="outlined"
|
||||||
|
color="secondary"
|
||||||
|
onClick={handleSetToNull}
|
||||||
|
>
|
||||||
|
Set to NULL
|
||||||
|
</Button>
|
||||||
|
</div>
|
||||||
|
</Box>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,9 +205,6 @@ export default function DataGridTextCell<TData extends object>({
|
|||||||
? `${theme.palette.secondary[100]} !important`
|
? `${theme.palette.secondary[100]} !important`
|
||||||
: `${theme.palette.common.white} !important`,
|
: `${theme.palette.common.white} !important`,
|
||||||
},
|
},
|
||||||
[`& .${inputClasses.input}`]: {
|
|
||||||
backgroundColor: 'transparent',
|
|
||||||
},
|
|
||||||
}}
|
}}
|
||||||
slotProps={{
|
slotProps={{
|
||||||
inputWrapper: { className: 'h-full' },
|
inputWrapper: { className: 'h-full' },
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ or
|
|||||||
```js
|
```js
|
||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
import { NhostClient, NhostProvider } from '@nhost/react'
|
||||||
import { NhostApolloProvider } from '@nhost/react-apollo'
|
import { NhostApolloProvider } from '@nhost/react-apollo'
|
||||||
|
|
||||||
import App from './App'
|
import App from './App'
|
||||||
@@ -38,11 +38,11 @@ const nhost = new NhostClient({
|
|||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<NhostReactProvider nhost={nhost}>
|
<NhostProvider nhost={nhost}>
|
||||||
<NhostApolloProvider nhost={nhost}>
|
<NhostApolloProvider nhost={nhost}>
|
||||||
<App />
|
<App />
|
||||||
</NhostApolloProvider>
|
</NhostApolloProvider>
|
||||||
</NhostReactProvider>
|
</NhostProvider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
)
|
)
|
||||||
|
|||||||
10
package.json
10
package.json
@@ -56,10 +56,10 @@
|
|||||||
"dashboard"
|
"dashboard"
|
||||||
],
|
],
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@babel/core": "^7.24.7",
|
"@babel/core": "^7.26.10",
|
||||||
"@babel/eslint-parser": "^7.24.7",
|
"@babel/eslint-parser": "^7.26.10",
|
||||||
"@babel/plugin-syntax-flow": "^7.24.7",
|
"@babel/plugin-syntax-flow": "^7.26.0",
|
||||||
"@babel/plugin-transform-react-jsx": "^7.24.7",
|
"@babel/plugin-transform-react-jsx": "^7.25.9",
|
||||||
"@changesets/cli": "^2.27.5",
|
"@changesets/cli": "^2.27.5",
|
||||||
"@faker-js/faker": "^7.6.0",
|
"@faker-js/faker": "^7.6.0",
|
||||||
"@rollup/plugin-replace": "^5.0.7",
|
"@rollup/plugin-replace": "^5.0.7",
|
||||||
@@ -137,6 +137,8 @@
|
|||||||
"tough-cookie@<4.1.3": ">=4.1.3",
|
"tough-cookie@<4.1.3": ">=4.1.3",
|
||||||
"protobufjs@>=7.0.0 <7.2.4": ">=7.2.4",
|
"protobufjs@>=7.0.0 <7.2.4": ">=7.2.4",
|
||||||
"vite@=4.5.0": ">=4.5.1",
|
"vite@=4.5.0": ">=4.5.1",
|
||||||
|
"@babel/runtime@<7.26.10": ">=7.26.10",
|
||||||
|
"@babel/helpers@<7.26.10": ">=7.26.10",
|
||||||
"@babel/traverse@<7.23.2": ">=7.23.2",
|
"@babel/traverse@<7.23.2": ">=7.23.2",
|
||||||
"@adobe/css-tools@<4.3.2": ">=4.3.2",
|
"@adobe/css-tools@<4.3.2": ">=4.3.2",
|
||||||
"semver@<5.7.2": ">=5.7.2",
|
"semver@<5.7.2": ">=5.7.2",
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ export type CreateServerSideClientParams = Partial<
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an Nhost client that runs on the server side.
|
* Creates an Nhost client that runs on the server side.
|
||||||
* It will try to get the refesh token in cookies, or from the request URL
|
* It will try to get the refresh token in cookies, or from the request URL
|
||||||
* If a refresh token is found, it uses it to get an up to date access token (JWT) and a user session
|
* If a refresh token is found, it uses it to get an up to date access token (JWT) and a user session
|
||||||
* This method resolves when the authentication status is known eventually
|
* This method resolves when the authentication status is known eventually
|
||||||
* @param config - An object containing connection information
|
* @param config - An object containing connection information
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ Initialize a single `nhost` instance and wrap your app with the `NhostReactProvi
|
|||||||
import React from 'react'
|
import React from 'react'
|
||||||
import ReactDOM from 'react-dom'
|
import ReactDOM from 'react-dom'
|
||||||
|
|
||||||
import { NhostClient, NhostReactProvider } from '@nhost/react'
|
import { NhostClient, NhostProvider } from '@nhost/react'
|
||||||
|
|
||||||
import App from './App'
|
import App from './App'
|
||||||
|
|
||||||
@@ -38,9 +38,9 @@ const nhost = new NhostClient({
|
|||||||
|
|
||||||
ReactDOM.render(
|
ReactDOM.render(
|
||||||
<React.StrictMode>
|
<React.StrictMode>
|
||||||
<NhostReactProvider nhost={nhost}>
|
<NhostProvider nhost={nhost}>
|
||||||
<App />
|
<App />
|
||||||
</NhostReactProvider>
|
</NhostProvider>
|
||||||
</React.StrictMode>,
|
</React.StrictMode>,
|
||||||
document.getElementById('root')
|
document.getElementById('root')
|
||||||
)
|
)
|
||||||
|
|||||||
2139
pnpm-lock.yaml
generated
2139
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user