Compare commits
7 Commits
auth@0.42.
...
storage@0.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5b53c568ad | ||
|
|
24c5db943d | ||
|
|
ea87b81db6 | ||
|
|
226a22e322 | ||
|
|
9c58b4307a | ||
|
|
7ecfa41790 | ||
|
|
2633747992 |
1
.github/workflows/gen_ai_review.yaml
vendored
1
.github/workflows/gen_ai_review.yaml
vendored
@@ -24,4 +24,5 @@ jobs:
|
||||
config.model: ${{ vars.GEN_AI_MODEL }}
|
||||
config.model_turbo: $${{ vars.GEN_AI_MODEL_TURBO }}
|
||||
config.max_model_tokens: 200000
|
||||
config.custom_model_max_tokens: 200000
|
||||
ignore.glob: "['pnpm-lock.yaml','**/pnpm-lock.yaml', 'vendor/**','**/client_gen.go','**/models_gen.go','**/generated.go','**/*.gen.go']"
|
||||
|
||||
@@ -2,5 +2,7 @@
|
||||
// $schema provides code completion hints to IDEs.
|
||||
"$schema": "https://github.com/IBM/audit-ci/raw/main/docs/schema.json",
|
||||
"moderate": true,
|
||||
"allowlist": ["vue-template-compiler", { "id": "CVE-2025-48068", "path": "next" }]
|
||||
"allowlist": [
|
||||
"GHSA-9965-vmph-33xx" // https://github.com/advisories/GHSA-9965-vmph-33xx Update package once have a fix
|
||||
]
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ if [[ "$version" == "latest" ]]; then
|
||||
release=$(curl --silent https://api.github.com/repos/nhost/nhost/releases\?per_page=100 | grep tag_name | grep \"cli\@ | head -n 1 | sed 's/.*"tag_name": "\([^"]*\)".*/\1/')
|
||||
version=$( echo $release | sed 's/.*@//')
|
||||
else
|
||||
release="cli@$release"
|
||||
release="cli@$version"
|
||||
fi
|
||||
|
||||
# check version exists
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
const TsconfigPathsPlugin = require('tsconfig-paths-webpack-plugin');
|
||||
|
||||
module.exports = {
|
||||
stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'],
|
||||
addons: [
|
||||
'@storybook/addon-links',
|
||||
'@storybook/addon-essentials',
|
||||
'@storybook/addon-interactions',
|
||||
'storybook-addon-next-router',
|
||||
{
|
||||
/**
|
||||
* Fix Storybook issue with PostCSS@8
|
||||
* @see https://github.com/storybookjs/storybook/issues/12668#issuecomment-773958085
|
||||
*/
|
||||
name: '@storybook/addon-postcss',
|
||||
options: {
|
||||
postcssLoaderOptions: {
|
||||
implementation: require('postcss'),
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
framework: '@storybook/react',
|
||||
core: {
|
||||
builder: '@storybook/builder-webpack5',
|
||||
},
|
||||
features: {
|
||||
emotionAlias: true,
|
||||
},
|
||||
webpackFinal: async (config) => {
|
||||
return {
|
||||
...config,
|
||||
resolve: {
|
||||
...config?.resolve,
|
||||
plugins: [
|
||||
...(config?.resolve?.plugins || []),
|
||||
new TsconfigPathsPlugin(),
|
||||
],
|
||||
},
|
||||
};
|
||||
},
|
||||
env: (config) => ({
|
||||
...config,
|
||||
NEXT_PUBLIC_ENV: 'dev',
|
||||
NEXT_PUBLIC_NHOST_PLATFORM: 'false',
|
||||
}),
|
||||
};
|
||||
@@ -1,69 +0,0 @@
|
||||
import { NhostProvider } from '@/providers/nhost';
|
||||
import '@fontsource/inter';
|
||||
import '@fontsource/inter/500.css';
|
||||
import '@fontsource/inter/700.css';
|
||||
import { CssBaseline, ThemeProvider } from '@mui/material';
|
||||
import { createClient } from '@nhost/nhost-js-beta';
|
||||
import { NhostApolloProvider } from '@nhost/react-apollo';
|
||||
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
|
||||
import { Buffer } from 'buffer';
|
||||
import { initialize, mswDecorator } from 'msw-storybook-addon';
|
||||
import { RouterContext } from 'next/dist/shared/lib/router-context';
|
||||
import { createTheme } from '../src/components/ui/v2/createTheme';
|
||||
import '../src/styles/globals.css';
|
||||
|
||||
global.Buffer = Buffer;
|
||||
|
||||
initialize({ onUnhandledRequest: 'bypass' });
|
||||
|
||||
const queryClient = new QueryClient();
|
||||
|
||||
export const parameters = {
|
||||
nextRouter: {
|
||||
Provider: RouterContext.Provider,
|
||||
isReady: true,
|
||||
},
|
||||
actions: { argTypesRegex: '^on[A-Z].*' },
|
||||
controls: {
|
||||
matchers: {
|
||||
color: /(background|color)$/i,
|
||||
date: /Date$/,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
export const decorators = [
|
||||
(Story, context) => {
|
||||
const isDarkMode = !context.globals?.backgrounds?.value
|
||||
?.toLowerCase()
|
||||
?.startsWith('#f');
|
||||
|
||||
return (
|
||||
<ThemeProvider theme={createTheme(isDarkMode ? 'dark' : 'light')}>
|
||||
<CssBaseline />
|
||||
<Story />
|
||||
</ThemeProvider>
|
||||
);
|
||||
},
|
||||
(Story) => (
|
||||
<QueryClientProvider client={queryClient}>
|
||||
<Story />
|
||||
</QueryClientProvider>
|
||||
),
|
||||
(Story) => (
|
||||
<NhostApolloProvider
|
||||
fetchPolicy="cache-first"
|
||||
graphqlUrl="https://local.graphql.nhost.run/v1"
|
||||
>
|
||||
<Story />
|
||||
</NhostApolloProvider>
|
||||
),
|
||||
(Story) => (
|
||||
<NhostProvider
|
||||
nhost={createClient({ subdomain: 'local', region: 'local' })}
|
||||
>
|
||||
<Story />
|
||||
</NhostProvider>
|
||||
),
|
||||
mswDecorator,
|
||||
];
|
||||
@@ -62,20 +62,6 @@ NEXT_PUBLIC_NHOST_HASURA_API_URL=https://local.hasura.local.nhost.run
|
||||
|
||||
This will connect the Nhost Dashboard to your locally running Nhost backend.
|
||||
|
||||
### Storybook
|
||||
|
||||
Components are documented using [Storybook](https://storybook.js.org/). To run Storybook, run the following command:
|
||||
|
||||
```bash
|
||||
pnpm storybook
|
||||
```
|
||||
|
||||
By default, Storybook will run on port `6006`. You can change this by passing the `--port` flag:
|
||||
|
||||
```bash
|
||||
pnpm storybook --port 6007
|
||||
```
|
||||
|
||||
### General Environment Variables
|
||||
|
||||
| Name | Description |
|
||||
|
||||
@@ -9,15 +9,14 @@
|
||||
"analyze": "ANALYZE=true pnpm build --no-lint",
|
||||
"start": "next start",
|
||||
"lint": "next lint --max-warnings 0",
|
||||
"test": "vitest --run",
|
||||
"test": "pnpm lint && pnpm test:vitest",
|
||||
"test:vitest": "vitest --run",
|
||||
"test:watch": "vitest",
|
||||
"generate": "echo 'This needs to be fixed.'",
|
||||
"codegen": "DOTENV_CONFIG_PATH=./.env.local graphql-codegen -r dotenv/config --config graphql.config.yaml --errors-only",
|
||||
"codegen-graphite": "graphql-codegen --config graphite.graphql.config.yaml --errors-only",
|
||||
"codegen-hasura-api": "orval --config src/utils/hasura-api/orval.config.ts",
|
||||
"format": "prettier --write \"src/**/*.{js,ts,tsx,jsx,json,md}\" --plugin-search-dir=.",
|
||||
"storybook": "start-storybook -p 6006 -s public",
|
||||
"build-storybook": "build-storybook",
|
||||
"install-browsers": "pnpm playwright install && pnpm playwright install-deps",
|
||||
"e2e:tests": "pnpm playwright test --config=playwright.config.ts -x",
|
||||
"e2e": "pnpm e2e:tests --project=main",
|
||||
@@ -111,7 +110,6 @@
|
||||
"react-hot-toast": "^2.4.1",
|
||||
"react-intersection-observer": "^9.8.1",
|
||||
"react-is": "18.2.0",
|
||||
"react-loading-skeleton": "^2.2.0",
|
||||
"react-markdown": "^9.0.1",
|
||||
"react-merge-refs": "^3.0.2",
|
||||
"react-resizable-layout": "^0.7.2",
|
||||
@@ -136,21 +134,12 @@
|
||||
"@babel/core": "^7.24.3",
|
||||
"@eslint/js": "9.26.0",
|
||||
"@faker-js/faker": "^7.6.0",
|
||||
"@graphql-codegen/cli": "^5.0.2",
|
||||
"@graphql-codegen/cli": "^6.0.0",
|
||||
"@graphql-codegen/typescript": "^3.0.4",
|
||||
"@graphql-codegen/typescript-operations": "^3.0.4",
|
||||
"@graphql-codegen/typescript-react-apollo": "^3.3.7",
|
||||
"@next/bundle-analyzer": "^12.3.4",
|
||||
"@playwright/test": "1.54.1",
|
||||
"@storybook/addon-actions": "^6.5.16",
|
||||
"@storybook/addon-essentials": "^6.5.16",
|
||||
"@storybook/addon-interactions": "^6.5.16",
|
||||
"@storybook/addon-links": "^6.5.16",
|
||||
"@storybook/addon-postcss": "^2.0.0",
|
||||
"@storybook/builder-webpack5": "^6.5.16",
|
||||
"@storybook/manager-webpack5": "^6.5.16",
|
||||
"@storybook/react": "^7.6.17",
|
||||
"@storybook/testing-library": "^0.2.2",
|
||||
"@tailwindcss/typography": "^0.5.12",
|
||||
"@testing-library/dom": "^9.3.4",
|
||||
"@testing-library/jest-dom": "^5.17.0",
|
||||
@@ -160,7 +149,7 @@
|
||||
"@types/bcryptjs": "^2.4.6",
|
||||
"@types/jest": "^29.5.12",
|
||||
"@types/lodash.debounce": "^4.0.9",
|
||||
"@types/node": "^16.18.93",
|
||||
"@types/node": "^20.14.8",
|
||||
"@types/pluralize": "^0.0.30",
|
||||
"@types/react": "18.2.73",
|
||||
"@types/react-dom": "^18.2.23",
|
||||
@@ -170,8 +159,8 @@
|
||||
"@types/validator": "^13.11.9",
|
||||
"@typescript-eslint/eslint-plugin": "^6.21.0",
|
||||
"@typescript-eslint/parser": "^6.21.0",
|
||||
"@vitejs/plugin-react": "^4.2.1",
|
||||
"@vitest/coverage-v8": "^0.32.4",
|
||||
"@vitejs/plugin-react": "^4.7.0",
|
||||
"@vitest/coverage-v8": "^3.2.4",
|
||||
"audit-ci": "^6.6.1",
|
||||
"autoprefixer": "^10.4.19",
|
||||
"babel-loader": "^8.3.0",
|
||||
@@ -195,24 +184,21 @@
|
||||
"eslint-plugin-vue": "^9.26.0",
|
||||
"jsdom": "^22.1.0",
|
||||
"lint-staged": "^15.2.2",
|
||||
"msw": "^1.3.5",
|
||||
"msw-storybook-addon": "^1.10.0",
|
||||
"msw": "^2.11.4",
|
||||
"node-fetch": "^3.3.2",
|
||||
"orval": "^7.11.2",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.4.2",
|
||||
"prettier-plugin-organize-imports": "^4.1.0",
|
||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||
"react-date-fns-hooks": "^0.9.4",
|
||||
"require-from-string": "^2.0.2",
|
||||
"snake-case": "^3.0.4",
|
||||
"storybook-addon-next-router": "^4.0.2",
|
||||
"tailwindcss": "^3.4.12",
|
||||
"ts-node": "^10.9.2",
|
||||
"tsconfig-paths-webpack-plugin": "^4.1.0",
|
||||
"vite": "^5.4.20",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^0.32.4"
|
||||
"vitest": "^3.2.4"
|
||||
},
|
||||
"browserslist": {
|
||||
"production": [
|
||||
@@ -243,6 +229,9 @@
|
||||
"@lezer/highlight": "^1.0.0"
|
||||
}
|
||||
}
|
||||
},
|
||||
"overrides": {
|
||||
"esbuild@<=0.24.2": ">=0.25.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
10004
dashboard/pnpm-lock.yaml
generated
10004
dashboard/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -66,7 +66,6 @@ let
|
||||
"${submodule}/tsconfig.test.json"
|
||||
"${submodule}/vitest.config.ts"
|
||||
"${submodule}/vitest.global-setup.ts"
|
||||
(inDirectory "${submodule}/.storybook")
|
||||
(inDirectory "${submodule}/e2e")
|
||||
(inDirectory "${submodule}/public")
|
||||
(inDirectory "${submodule}/src")
|
||||
@@ -213,5 +212,3 @@ rec {
|
||||
}).copyTo}/bin/copy-to dir:$out
|
||||
'';
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,48 +0,0 @@
|
||||
import type { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import type { PropsWithoutRef } from 'react';
|
||||
|
||||
import type { ReadOnlyToggleProps } from './ReadOnlyToggle';
|
||||
import ReadOnlyToggle from './ReadOnlyToggle';
|
||||
|
||||
export default {
|
||||
title: 'Common Components / ReadOnlyToggle',
|
||||
component: ReadOnlyToggle,
|
||||
argTypes: {
|
||||
checked: {
|
||||
options: [null, true, false],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ReadOnlyToggle>;
|
||||
|
||||
const Template: ComponentStory<typeof ReadOnlyToggle> = function Template(
|
||||
args: PropsWithoutRef<ReadOnlyToggleProps>,
|
||||
) {
|
||||
return <ReadOnlyToggle {...args} />;
|
||||
};
|
||||
|
||||
export const Null = Template.bind({});
|
||||
Null.args = {
|
||||
checked: null,
|
||||
};
|
||||
|
||||
export const True = Template.bind({});
|
||||
True.args = {
|
||||
checked: true,
|
||||
};
|
||||
|
||||
export const False = Template.bind({});
|
||||
False.args = {
|
||||
checked: false,
|
||||
};
|
||||
|
||||
export const CustomClasses = Template.bind({});
|
||||
CustomClasses.args = {
|
||||
checked: true,
|
||||
className: '!bg-red-500',
|
||||
slotProps: {
|
||||
label: {
|
||||
className: '!text-sm !text-white',
|
||||
},
|
||||
},
|
||||
};
|
||||
@@ -1,125 +0,0 @@
|
||||
import { PlusCircleIcon } from '@/components/ui/v2/icons/PlusCircleIcon';
|
||||
import { PlusIcon } from '@/components/ui/v2/icons/PlusIcon';
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import type { ButtonProps } from './Button';
|
||||
import Button from './Button';
|
||||
|
||||
export default {
|
||||
title: 'UI Library / Button',
|
||||
component: Button,
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: ['contained', 'outlined', 'borderless'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
color: {
|
||||
options: ['primary', 'secondary', 'error'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
disabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
size: {
|
||||
options: ['small', 'medium', 'large'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
},
|
||||
} as Meta<typeof Button>;
|
||||
|
||||
const Template: StoryFn<ButtonProps> = function TemplateFunction(
|
||||
args: ButtonProps,
|
||||
) {
|
||||
return <Button {...args} />;
|
||||
};
|
||||
|
||||
export const Primary = Template.bind({});
|
||||
Primary.args = {
|
||||
children: 'Button',
|
||||
color: 'primary',
|
||||
};
|
||||
|
||||
export const PrimaryOutlined = Template.bind({});
|
||||
PrimaryOutlined.args = {
|
||||
children: 'Button',
|
||||
variant: 'outlined',
|
||||
color: 'primary',
|
||||
};
|
||||
|
||||
export const PrimaryBorderless = Template.bind({});
|
||||
PrimaryBorderless.args = {
|
||||
children: 'Button',
|
||||
variant: 'borderless',
|
||||
color: 'primary',
|
||||
};
|
||||
|
||||
export const Secondary = Template.bind({});
|
||||
Secondary.args = {
|
||||
children: 'Button',
|
||||
color: 'secondary',
|
||||
};
|
||||
|
||||
export const SecondaryOutlined = Template.bind({});
|
||||
SecondaryOutlined.args = {
|
||||
children: 'Button',
|
||||
variant: 'outlined',
|
||||
color: 'secondary',
|
||||
};
|
||||
|
||||
export const SecondaryBorderless = Template.bind({});
|
||||
SecondaryBorderless.args = {
|
||||
children: 'Button',
|
||||
variant: 'borderless',
|
||||
color: 'secondary',
|
||||
};
|
||||
|
||||
export const Danger = Template.bind({});
|
||||
Danger.args = {
|
||||
children: 'Button',
|
||||
color: 'error',
|
||||
};
|
||||
|
||||
export const DangerOutlined = Template.bind({});
|
||||
DangerOutlined.args = {
|
||||
children: 'Button',
|
||||
variant: 'outlined',
|
||||
color: 'error',
|
||||
};
|
||||
|
||||
export const DangerBorderless = Template.bind({});
|
||||
DangerBorderless.args = {
|
||||
children: 'Button',
|
||||
variant: 'borderless',
|
||||
color: 'error',
|
||||
};
|
||||
|
||||
export const Small = Template.bind({});
|
||||
Small.args = {
|
||||
children: 'Button',
|
||||
variant: 'contained',
|
||||
color: 'primary',
|
||||
size: 'small',
|
||||
};
|
||||
|
||||
export const Large = Template.bind({});
|
||||
Large.args = {
|
||||
children: 'Button',
|
||||
variant: 'contained',
|
||||
color: 'primary',
|
||||
size: 'large',
|
||||
};
|
||||
|
||||
export const WithStartIcon = Template.bind({});
|
||||
WithStartIcon.args = {
|
||||
children: 'Button',
|
||||
variant: 'contained',
|
||||
color: 'primary',
|
||||
startIcon: <PlusIcon />,
|
||||
};
|
||||
|
||||
export const WithEndIcon = Template.bind({});
|
||||
WithEndIcon.args = {
|
||||
children: 'Button',
|
||||
variant: 'contained',
|
||||
color: 'primary',
|
||||
endIcon: <PlusCircleIcon />,
|
||||
};
|
||||
@@ -1,86 +0,0 @@
|
||||
import { XIcon } from '@/components/ui/v2/icons/XIcon';
|
||||
import type { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import type { ChipProps } from './Chip';
|
||||
import Chip from './Chip';
|
||||
|
||||
export default {
|
||||
title: 'UI Library / Chip',
|
||||
component: Chip,
|
||||
argTypes: {
|
||||
variant: {
|
||||
options: ['contained', 'outlined'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
color: {
|
||||
options: ['primary', 'secondary', 'error', 'info'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
disabled: {
|
||||
control: { type: 'boolean' },
|
||||
},
|
||||
size: {
|
||||
options: ['small', 'medium'],
|
||||
control: { type: 'radio' },
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof Chip>;
|
||||
|
||||
const Template: ComponentStory<typeof Chip> = function Template(
|
||||
args: ChipProps,
|
||||
) {
|
||||
return <Chip {...args} />;
|
||||
};
|
||||
|
||||
export const Primary = Template.bind({});
|
||||
Primary.args = {
|
||||
label: 'Chip',
|
||||
color: 'primary',
|
||||
};
|
||||
|
||||
export const PrimaryOutlined = Template.bind({});
|
||||
PrimaryOutlined.args = {
|
||||
label: 'Chip',
|
||||
variant: 'outlined',
|
||||
color: 'primary',
|
||||
};
|
||||
|
||||
export const Secondary = Template.bind({});
|
||||
Secondary.args = {
|
||||
label: 'Chip',
|
||||
color: 'secondary',
|
||||
};
|
||||
|
||||
export const SecondaryOutlined = Template.bind({});
|
||||
SecondaryOutlined.args = {
|
||||
label: 'Chip',
|
||||
variant: 'outlined',
|
||||
color: 'secondary',
|
||||
};
|
||||
|
||||
export const Danger = Template.bind({});
|
||||
Danger.args = {
|
||||
label: 'Chip',
|
||||
color: 'error',
|
||||
};
|
||||
|
||||
export const DangerOutlined = Template.bind({});
|
||||
DangerOutlined.args = {
|
||||
label: 'Chip',
|
||||
variant: 'outlined',
|
||||
color: 'error',
|
||||
};
|
||||
|
||||
export const Small = Template.bind({});
|
||||
Small.args = {
|
||||
label: 'Chip',
|
||||
color: 'primary',
|
||||
size: 'small',
|
||||
};
|
||||
|
||||
export const WithDeleteIcon = Template.bind({});
|
||||
WithDeleteIcon.args = {
|
||||
label: 'Chip',
|
||||
color: 'primary',
|
||||
deleteIcon: <XIcon />,
|
||||
onDelete: () => {},
|
||||
};
|
||||
@@ -1,38 +0,0 @@
|
||||
import { Option } from '@/components/ui/v2/Option';
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import type { SelectProps } from './Select';
|
||||
import Select from './Select';
|
||||
|
||||
export default {
|
||||
title: 'UI Library / Select',
|
||||
component: Select,
|
||||
argTypes: {},
|
||||
} as Meta<typeof Select>;
|
||||
|
||||
const Template: StoryFn<SelectProps<any>> = function TemplateFunction(args) {
|
||||
return (
|
||||
<Select className="w-64" {...args}>
|
||||
<Option value="value1">Value 1</Option>
|
||||
<Option value="value2">Value 2</Option>
|
||||
<Option value="value3">Value 3</Option>
|
||||
<Option value="value4">Value 4</Option>
|
||||
</Select>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {
|
||||
defaultValue: 'value1',
|
||||
};
|
||||
|
||||
export const WithLabel = Template.bind({});
|
||||
WithLabel.args = {
|
||||
label: 'Label',
|
||||
};
|
||||
|
||||
export const Disabled = Template.bind({});
|
||||
Disabled.args = {
|
||||
label: 'Label',
|
||||
disabled: true,
|
||||
defaultValue: 'value1',
|
||||
};
|
||||
@@ -1,28 +0,0 @@
|
||||
import type { Meta, StoryFn } from '@storybook/react';
|
||||
import type { SwitchProps } from './Switch';
|
||||
import Switch from './Switch';
|
||||
|
||||
export default {
|
||||
title: 'UI Library / Switch',
|
||||
component: Switch,
|
||||
argTypes: {},
|
||||
} as Meta<typeof Switch>;
|
||||
|
||||
const Template: StoryFn<SwitchProps> = function TemplateFunction(
|
||||
args: SwitchProps,
|
||||
) {
|
||||
return <Switch label="Accept Rules" {...args} />;
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
||||
|
||||
export const Checked = Template.bind({});
|
||||
Checked.args = {
|
||||
checked: true,
|
||||
};
|
||||
|
||||
export const Disabled = Template.bind({});
|
||||
Disabled.args = {
|
||||
disabled: true,
|
||||
};
|
||||
@@ -1,126 +0,0 @@
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import hasuraMetadataQuery from '@/tests/msw/mocks/rest/hasuraMetadataQuery';
|
||||
import tableQuery from '@/tests/msw/mocks/rest/tableQuery';
|
||||
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
|
||||
import type { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type { ColumnAutocompleteProps } from './ColumnAutocomplete';
|
||||
import ColumnAutocomplete from './ColumnAutocomplete';
|
||||
|
||||
export default {
|
||||
title: 'Data Browser / ColumnAutocomplete',
|
||||
component: ColumnAutocomplete,
|
||||
parameters: {
|
||||
docs: {
|
||||
source: {
|
||||
type: 'code',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof ColumnAutocomplete>;
|
||||
|
||||
const defaultParameters = {
|
||||
nextRouter: {
|
||||
path: '/[workspaceSlug]/[appSlug]/database/browser/[dataSourceSlug]/[schemaSlug]/[tableSlug]',
|
||||
asPath: '/workspace/app/database/browser/default/public/users',
|
||||
query: {
|
||||
workspaceSlug: 'workspace',
|
||||
appSlug: 'app',
|
||||
dataSourceSlug: 'default',
|
||||
schemaSlug: 'public',
|
||||
tableSlug: 'books',
|
||||
},
|
||||
},
|
||||
msw: {
|
||||
handlers: [tokenQuery, tableQuery, hasuraMetadataQuery],
|
||||
},
|
||||
};
|
||||
|
||||
const Template: ComponentStory<typeof ColumnAutocomplete> = function Template(
|
||||
args: ColumnAutocompleteProps,
|
||||
) {
|
||||
const [submittedValues, setSubmittedValues] = useState<string>('');
|
||||
|
||||
const form = useForm<{ firstReference: string; secondReference: string }>({
|
||||
defaultValues: {
|
||||
firstReference: null as any,
|
||||
secondReference: null as any,
|
||||
},
|
||||
});
|
||||
|
||||
function handleSubmit(values: {
|
||||
firstReference: string;
|
||||
secondReference: string;
|
||||
}) {
|
||||
setSubmittedValues(JSON.stringify(values, null, 2));
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-flow-row gap-2">
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleSubmit} className="grid grid-flow-row gap-2">
|
||||
<ColumnAutocomplete
|
||||
{...args}
|
||||
onChange={(newValue) =>
|
||||
form.setValue('firstReference', newValue.value, {
|
||||
shouldDirty: true,
|
||||
})
|
||||
}
|
||||
onInitialized={(newValue) => {
|
||||
form.setValue('firstReference', newValue.value, {
|
||||
shouldDirty: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
<ColumnAutocomplete
|
||||
{...args}
|
||||
onChange={(newValue) =>
|
||||
form.setValue('secondReference', newValue.value, {
|
||||
shouldDirty: true,
|
||||
})
|
||||
}
|
||||
onInitialized={(newValue) => {
|
||||
form.setValue('secondReference', newValue.value, {
|
||||
shouldDirty: true,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
<Button type="submit" className="justify-self-start">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
|
||||
<Text component="pre" className="!font-mono !text-gray-700">
|
||||
{submittedValues || 'The form has not been submitted yet.'}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Basic = Template.bind({});
|
||||
Basic.args = {
|
||||
schema: 'public',
|
||||
table: 'books',
|
||||
};
|
||||
Basic.parameters = defaultParameters;
|
||||
|
||||
export const DefaultValue = Template.bind({});
|
||||
DefaultValue.args = {
|
||||
schema: 'public',
|
||||
table: 'books',
|
||||
value: 'author.id',
|
||||
};
|
||||
DefaultValue.parameters = defaultParameters;
|
||||
|
||||
export const DisabledRelationships = Template.bind({});
|
||||
DisabledRelationships.args = {
|
||||
schema: 'public',
|
||||
table: 'books',
|
||||
disableRelationships: true,
|
||||
};
|
||||
DisabledRelationships.parameters = defaultParameters;
|
||||
@@ -127,6 +127,10 @@ describe('RowPermissionsSection', () => {
|
||||
process.env.NEXT_PUBLIC_ENV = 'dev';
|
||||
server.listen();
|
||||
});
|
||||
beforeEach(() => {
|
||||
server.restoreHandlers();
|
||||
server.resetHandlers();
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
server.close();
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
import { Form } from '@/components/form/Form';
|
||||
import { Button } from '@/components/ui/v2/Button';
|
||||
import { Text } from '@/components/ui/v2/Text';
|
||||
import type { RuleGroup } from '@/features/orgs/projects/database/dataGrid/types/dataBrowser';
|
||||
import permissionVariablesQuery from '@/tests/msw/mocks/graphql/permissionVariablesQuery';
|
||||
import hasuraMetadataQuery from '@/tests/msw/mocks/rest/hasuraMetadataQuery';
|
||||
import tableQuery from '@/tests/msw/mocks/rest/tableQuery';
|
||||
import type { ComponentMeta, ComponentStory } from '@storybook/react';
|
||||
import { useState } from 'react';
|
||||
import { FormProvider, useForm } from 'react-hook-form';
|
||||
import type { RuleGroupEditorProps } from './RuleGroupEditor';
|
||||
import RuleGroupEditor from './RuleGroupEditor';
|
||||
|
||||
export default {
|
||||
title: 'Data Browser / RuleGroupEditor',
|
||||
component: RuleGroupEditor,
|
||||
parameters: {
|
||||
docs: {
|
||||
source: {
|
||||
type: 'code',
|
||||
},
|
||||
},
|
||||
},
|
||||
} as ComponentMeta<typeof RuleGroupEditor>;
|
||||
|
||||
const defaultParameters = {
|
||||
nextRouter: {
|
||||
path: '/[workspaceSlug]/[appSlug]/database/browser/[dataSourceSlug]/[schemaSlug]/[tableSlug]',
|
||||
asPath: '/workspace/app/database/browser/default/public/users',
|
||||
query: {
|
||||
workspaceSlug: 'workspace',
|
||||
appSlug: 'app',
|
||||
dataSourceSlug: 'default',
|
||||
schemaSlug: 'public',
|
||||
tableSlug: 'books',
|
||||
},
|
||||
},
|
||||
msw: {
|
||||
handlers: [tableQuery, hasuraMetadataQuery, permissionVariablesQuery],
|
||||
},
|
||||
};
|
||||
|
||||
const Template: ComponentStory<typeof RuleGroupEditor> = function Template(
|
||||
args: RuleGroupEditorProps,
|
||||
) {
|
||||
const [submittedValues, setSubmittedValues] = useState<string>();
|
||||
|
||||
const form = useForm<{ ruleGroupEditor: RuleGroup }>({
|
||||
defaultValues: {
|
||||
ruleGroupEditor: {
|
||||
operator: '_and',
|
||||
rules: [{ column: '', operator: '_eq', value: '' }],
|
||||
groups: [],
|
||||
},
|
||||
},
|
||||
reValidateMode: 'onSubmit',
|
||||
});
|
||||
|
||||
function handleSubmit(values: { ruleGroupEditor: RuleGroup }) {
|
||||
setSubmittedValues(JSON.stringify(values, null, 2));
|
||||
}
|
||||
|
||||
// note: Storybook passes `onRemove` as a prop, but we don't want to use it
|
||||
return (
|
||||
<div className="grid grid-flow-row gap-2">
|
||||
<FormProvider {...form}>
|
||||
<Form onSubmit={handleSubmit} className="grid grid-flow-row gap-2">
|
||||
<RuleGroupEditor
|
||||
{...args}
|
||||
schema="public"
|
||||
table="books"
|
||||
name="ruleGroupEditor"
|
||||
/>
|
||||
|
||||
<Button type="submit" className="justify-self-start">
|
||||
Submit
|
||||
</Button>
|
||||
</Form>
|
||||
</FormProvider>
|
||||
|
||||
<Text component="pre" className="!font-mono !text-gray-700">
|
||||
{submittedValues || 'The form has not been submitted yet.'}
|
||||
</Text>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export const Default = Template.bind({});
|
||||
Default.args = {};
|
||||
Default.parameters = defaultParameters;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import type { ManagePermissionOptions } from './managePermission';
|
||||
import managePermission from './managePermission';
|
||||
@@ -12,9 +12,7 @@ const defaultParameters: ManagePermissionOptions = {
|
||||
};
|
||||
|
||||
const server = setupServer(
|
||||
rest.post('http://localhost:1337/v1/metadata', (_req, res, ctx) =>
|
||||
res(ctx.json({})),
|
||||
),
|
||||
http.post('http://localhost:1337/v1/metadata', () => HttpResponse.json({})),
|
||||
);
|
||||
|
||||
beforeAll(() => server.listen());
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import type { HasuraMetadata } from '@/features/orgs/projects/database/dataGrid/types/dataBrowser';
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import prepareTrackForeignKeyRelationsMetadata from './prepareTrackForeignKeyRelationsMetadata';
|
||||
|
||||
@@ -28,11 +28,8 @@ const testMetadataResponse: { metadata: HasuraMetadata } = {
|
||||
};
|
||||
|
||||
const metadataHandlers = [
|
||||
rest.post(`${APP_URL}/v1/metadata`, (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json<{ metadata: HasuraMetadata }>(testMetadataResponse),
|
||||
),
|
||||
http.post(`${APP_URL}/v1/metadata`, () =>
|
||||
HttpResponse.json(testMetadataResponse),
|
||||
),
|
||||
];
|
||||
|
||||
@@ -131,56 +128,53 @@ test('should only prepare a one-to-one relationship if the table does not have a
|
||||
|
||||
test('should drop existing relationships and prepare a new one-to-many relationship', async () => {
|
||||
server.use(
|
||||
rest.post(`${APP_URL}/v1/metadata`, (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.status(200),
|
||||
ctx.json<{ metadata: HasuraMetadata }>({
|
||||
...testMetadataResponse,
|
||||
metadata: {
|
||||
...testMetadataResponse.metadata,
|
||||
sources: [
|
||||
{
|
||||
...testMetadataResponse.metadata.sources[0],
|
||||
tables: [
|
||||
{
|
||||
...testMetadataResponse.metadata.sources[0].tables[0],
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'author_id',
|
||||
},
|
||||
http.post(`${APP_URL}/v1/metadata`, () =>
|
||||
HttpResponse.json({
|
||||
...testMetadataResponse,
|
||||
metadata: {
|
||||
...testMetadataResponse.metadata,
|
||||
sources: [
|
||||
{
|
||||
...testMetadataResponse.metadata.sources[0],
|
||||
tables: [
|
||||
{
|
||||
...testMetadataResponse.metadata.sources[0].tables[0],
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'author_id',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'authors',
|
||||
schema: 'public',
|
||||
},
|
||||
configuration: {},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'books',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'author_id',
|
||||
table: {
|
||||
name: 'books',
|
||||
schema: 'public',
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'authors',
|
||||
schema: 'public',
|
||||
},
|
||||
configuration: {},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'books',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'author_id',
|
||||
table: {
|
||||
name: 'books',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
object_relationships: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
object_relationships: [],
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { render, screen, TestUserEvent } from '@/tests/testUtils';
|
||||
import { vi } from 'vitest';
|
||||
import DatabasePiTRSettings from './DatabasePiTRSettings';
|
||||
|
||||
import { getOrganizations } from '@/tests/msw/mocks/graphql/getOrganizationQuery';
|
||||
import { getProjectQuery } from '@/tests/msw/mocks/graphql/getProjectQuery';
|
||||
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
|
||||
import { setupServer } from 'msw/node';
|
||||
@@ -75,7 +76,7 @@ vi.mock('@/features/orgs/components/common/TransferProjectDialog', async () => {
|
||||
};
|
||||
});
|
||||
|
||||
const server = setupServer(tokenQuery);
|
||||
const server = setupServer(tokenQuery, getOrganizations);
|
||||
|
||||
describe('DatabasePiTRSettings', () => {
|
||||
beforeAll(() => {
|
||||
|
||||
@@ -52,11 +52,11 @@ function UpgradeNotification({ description }: Props) {
|
||||
<ArrowSquareOutIcon className="ml-1 h-4 w-4" />
|
||||
</Link>
|
||||
<OpenTransferDialogButton onClick={handleTransferDialogOpen} />
|
||||
<TransferProjectDialog
|
||||
open={transferProjectDialogOpen}
|
||||
setOpen={setTransferProjectDialogOpen}
|
||||
/>
|
||||
</Text>
|
||||
<TransferProjectDialog
|
||||
open={transferProjectDialogOpen}
|
||||
setOpen={setTransferProjectDialogOpen}
|
||||
/>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,17 @@ const mockServices = [
|
||||
'job-backup',
|
||||
];
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'getBoundingClientRect', {
|
||||
value: vi.fn(() => ({
|
||||
width: 100,
|
||||
height: 40,
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 40,
|
||||
right: 100,
|
||||
})),
|
||||
});
|
||||
|
||||
vi.mock('@/features/orgs/projects/hooks/useProject', async () => ({
|
||||
useProject: () => ({ project: mockApplication }),
|
||||
}));
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
|
||||
import { render, screen, waitFor } from '@/tests/testUtils';
|
||||
import { graphql } from 'msw';
|
||||
import { HttpResponse, graphql } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { beforeAll, expect, test, vi } from 'vitest';
|
||||
import HasuraCorsDomainSettings from './HasuraCorsDomainSettings';
|
||||
|
||||
const server = setupServer(
|
||||
tokenQuery,
|
||||
graphql.query('GetHasuraSettings', (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
graphql.query('GetHasuraSettings', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
id: 'HasuraSettings',
|
||||
__typename: 'HasuraSettings',
|
||||
@@ -29,8 +29,8 @@ const server = setupServer(
|
||||
resources: [],
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -62,9 +62,9 @@ describe('HasuraCorsDomainSettings', () => {
|
||||
|
||||
test('should enable switch by default when CORS domain is set to one or more domains', async () => {
|
||||
server.use(
|
||||
graphql.query('GetHasuraSettings', (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
graphql.query('GetHasuraSettings', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
id: 'HasuraSettings',
|
||||
__typename: 'HasuraSettings',
|
||||
@@ -84,8 +84,8 @@ describe('HasuraCorsDomainSettings', () => {
|
||||
resources: [],
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
),
|
||||
);
|
||||
|
||||
|
||||
@@ -82,6 +82,7 @@ describe('useProjectLogs - Subscription Creation & Cleanup', () => {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
refetch: vi.fn(),
|
||||
projectNotFound: false,
|
||||
});
|
||||
|
||||
// Mock subscribeToMore to return an unsubscribe function
|
||||
@@ -133,6 +134,7 @@ describe('useProjectLogs - Subscription Creation & Cleanup', () => {
|
||||
loading: true,
|
||||
error: undefined,
|
||||
refetch: vi.fn(),
|
||||
projectNotFound: false,
|
||||
});
|
||||
|
||||
renderHook(() => useProjectLogs(defaultProps));
|
||||
@@ -146,6 +148,7 @@ describe('useProjectLogs - Subscription Creation & Cleanup', () => {
|
||||
loading: false,
|
||||
error: undefined,
|
||||
refetch: vi.fn(),
|
||||
projectNotFound: false,
|
||||
});
|
||||
|
||||
renderHook(() => useProjectLogs(defaultProps));
|
||||
|
||||
@@ -20,6 +20,17 @@ const mockServices = [
|
||||
'job-backup',
|
||||
];
|
||||
|
||||
Object.defineProperty(HTMLElement.prototype, 'getBoundingClientRect', {
|
||||
value: vi.fn(() => ({
|
||||
width: 100,
|
||||
height: 40,
|
||||
top: 0,
|
||||
left: 0,
|
||||
bottom: 40,
|
||||
right: 100,
|
||||
})),
|
||||
});
|
||||
|
||||
vi.mock('@/features/orgs/projects/hooks/useProject', async () => ({
|
||||
useProject: () => ({ project: mockApplication }),
|
||||
}));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { mockApplication, mockOrganization } from '@/tests/mocks';
|
||||
import tokenQuery from '@/tests/msw/mocks/rest/tokenQuery';
|
||||
import { queryClient, render, screen } from '@/tests/testUtils';
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
import { setupServer } from 'msw/node';
|
||||
import { afterAll, beforeAll, vi } from 'vitest';
|
||||
import OverviewDeployments from './OverviewDeployments';
|
||||
@@ -36,8 +36,9 @@ vi.mock('next/router', () => ({
|
||||
|
||||
const server = setupServer(
|
||||
tokenQuery,
|
||||
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
|
||||
res(ctx.status(200)),
|
||||
http.get(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
() => new HttpResponse(null, { status: 200 }),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -49,8 +50,9 @@ beforeAll(() => {
|
||||
|
||||
afterEach(() => {
|
||||
server.resetHandlers(
|
||||
rest.get('https://local.graphql.local.nhost.run/v1', (_req, res, ctx) =>
|
||||
res(ctx.status(200)),
|
||||
http.get(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
() => new HttpResponse(null, { status: 200 }),
|
||||
),
|
||||
);
|
||||
queryClient.clear();
|
||||
@@ -63,37 +65,31 @@ afterAll(() => {
|
||||
|
||||
test('should render an empty state when GitHub is not connected', async () => {
|
||||
server.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
async (req, res, ctx) => {
|
||||
const { operationName } = await req.json();
|
||||
async ({ request }) => {
|
||||
const { operationName } = (await request.json()) as any;
|
||||
if (operationName === 'getProject') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication, githubRepository: null }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication, githubRepository: null }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (operationName === 'getOrganization') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
deployments: [],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
deployments: [],
|
||||
},
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -107,32 +103,28 @@ test('should render an empty state when GitHub is not connected', async () => {
|
||||
});
|
||||
test('should render an empty state when GitHub is connected, but there are no deployments', async () => {
|
||||
server.use(
|
||||
rest.post(
|
||||
http.post(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
async (_req, res, ctx) => {
|
||||
const { operationName } = await _req.json();
|
||||
async ({ request }) => {
|
||||
const { operationName } = (await request.json()) as any;
|
||||
|
||||
if (operationName === 'getProject') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
if (operationName === 'getOrganization') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res(ctx.json({ data: { deployments: [] } }));
|
||||
return HttpResponse.json({ data: { deployments: [] } });
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -155,52 +147,46 @@ test('should render an empty state when GitHub is connected, but there are no de
|
||||
test('should render a list of deployments', async () => {
|
||||
server.use(
|
||||
tokenQuery,
|
||||
rest.post(
|
||||
http.post(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
async (_req, res, ctx) => {
|
||||
const { operationName } = await _req.json();
|
||||
async ({ request }) => {
|
||||
const { operationName } = (await request.json()) as any;
|
||||
|
||||
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
|
||||
return res(ctx.json({ data: { deployments: [] } }));
|
||||
return HttpResponse.json({ data: { deployments: [] } });
|
||||
}
|
||||
|
||||
if (operationName === 'getProject') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
});
|
||||
}
|
||||
if (operationName === 'getOrganization') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
deployments: [
|
||||
{
|
||||
id: '1',
|
||||
commitSHA: 'abc123',
|
||||
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
|
||||
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
commitUserName: 'test.user',
|
||||
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
|
||||
commitMessage: 'Test commit message',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
deployments: [
|
||||
{
|
||||
id: '1',
|
||||
commitSHA: 'abc123',
|
||||
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
|
||||
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
commitUserName: 'test.user',
|
||||
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
|
||||
commitMessage: 'Test commit message',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
@@ -227,69 +213,61 @@ test('should render a list of deployments', async () => {
|
||||
test('should disable redeployments if a deployment is already in progress', async () => {
|
||||
server.use(
|
||||
tokenQuery,
|
||||
rest.post(
|
||||
http.post(
|
||||
'https://local.graphql.local.nhost.run/v1',
|
||||
async (req, res, ctx) => {
|
||||
const { operationName } = await req.json();
|
||||
async ({ request }) => {
|
||||
const { operationName } = (await request.json()) as any;
|
||||
|
||||
if (operationName === 'ScheduledOrPendingDeploymentsSub') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
deployments: [
|
||||
{
|
||||
id: '2',
|
||||
commitSHA: 'abc234',
|
||||
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
|
||||
deploymentEndedAt: null,
|
||||
deploymentStatus: 'PENDING',
|
||||
commitUserName: 'test.user',
|
||||
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
|
||||
commitMessage: 'Test commit message',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
if (operationName === 'getProject') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
if (operationName === 'getOrganization') {
|
||||
return res(
|
||||
ctx.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.json({
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
deployments: [
|
||||
{
|
||||
id: '1',
|
||||
commitSHA: 'abc123',
|
||||
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
|
||||
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
id: '2',
|
||||
commitSHA: 'abc234',
|
||||
deploymentStartedAt: '2021-08-02T00:00:00.000Z',
|
||||
deploymentEndedAt: null,
|
||||
deploymentStatus: 'PENDING',
|
||||
commitUserName: 'test.user',
|
||||
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
|
||||
commitMessage: 'Test commit message',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
if (operationName === 'getProject') {
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication }],
|
||||
},
|
||||
});
|
||||
}
|
||||
if (operationName === 'getOrganization') {
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
organizations: [{ ...mockOrganization }],
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
return HttpResponse.json({
|
||||
data: {
|
||||
deployments: [
|
||||
{
|
||||
id: '1',
|
||||
commitSHA: 'abc123',
|
||||
deploymentStartedAt: '2021-08-01T00:00:00.000Z',
|
||||
deploymentEndedAt: '2021-08-01T00:05:00.000Z',
|
||||
deploymentStatus: 'DEPLOYED',
|
||||
commitUserName: 'test.user',
|
||||
commitUserAvatarUrl: 'http://images.example.com/avatar.png',
|
||||
commitMessage: 'Test commit message',
|
||||
},
|
||||
],
|
||||
},
|
||||
});
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,22 +1,15 @@
|
||||
import { mockOrganization, mockOrganizations } from '@/tests/mocks';
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const getOrganizations = nhostGraphQLLink.query(
|
||||
'getOrganizations',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
organizations: mockOrganizations,
|
||||
}),
|
||||
),
|
||||
export const getOrganizations = nhostGraphQLLink.query('getOrganizations', () =>
|
||||
HttpResponse.json({
|
||||
data: { organizations: mockOrganizations },
|
||||
}),
|
||||
);
|
||||
|
||||
export const getOrganization = nhostGraphQLLink.query(
|
||||
'getOrganization',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
organizations: [{ ...mockOrganization }],
|
||||
}),
|
||||
),
|
||||
export const getOrganization = nhostGraphQLLink.query('getOrganization', () =>
|
||||
HttpResponse.json({
|
||||
data: { organizations: [{ ...mockOrganization }] },
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const getPostgresSettings = nhostGraphQLLink.query(
|
||||
'GetPostgresSettings',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
systemConfig: {
|
||||
postgres: {
|
||||
database: 'gnlivtcgjxctuujxpslj',
|
||||
@@ -29,15 +30,15 @@ export const getPostgresSettings = nhostGraphQLLink.query(
|
||||
__typename: 'ConfigPostgres',
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const getPiTRNotEnabledPostgresSettings = nhostGraphQLLink.query(
|
||||
'GetPostgresSettings',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
systemConfig: {
|
||||
postgres: {
|
||||
database: 'gnlivtcgjxctuujxpslj',
|
||||
@@ -62,8 +63,6 @@ export const getPiTRNotEnabledPostgresSettings = nhostGraphQLLink.query(
|
||||
__typename: 'ConfigPostgres',
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
// {"data":}
|
||||
|
||||
@@ -1,36 +1,35 @@
|
||||
import { mockApplication } from '@/tests/mocks';
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const getProjectQuery = nhostGraphQLLink.query(
|
||||
'getProject',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
apps: [{ ...mockApplication, githubRepository: null }],
|
||||
}),
|
||||
),
|
||||
export const getProjectQuery = nhostGraphQLLink.query('getProject', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
apps: [{ ...mockApplication, githubRepository: null }],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const getProjectStateQuery = (appStates?: any) =>
|
||||
nhostGraphQLLink.query('getProjectState', (_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
nhostGraphQLLink.query('getProjectState', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
apps: [
|
||||
{
|
||||
...mockApplication,
|
||||
appStates: appStates || mockApplication.appStates,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const getNotFoundProjectStateQuery = nhostGraphQLLink.query(
|
||||
'getProjectState',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
apps: [],
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,144 +1,141 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const getProjectsQuery = nhostGraphQLLink.query(
|
||||
'getProjects',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
apps: [
|
||||
{
|
||||
id: 'pitr-usa-id',
|
||||
name: 'pitr-not-enabled-usa',
|
||||
slug: 'pitr-not-enabled-usa',
|
||||
createdAt: '2025-03-10T12:35:23.193578+00:00',
|
||||
subdomain: 'ocrnpctsphttfxkuefyx',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-r-elek-id',
|
||||
email: 'robert@elek.com',
|
||||
displayName: 'Robert',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: 'cd2b77ac-3ef1-4a76-819b-ff1caca09213',
|
||||
appId: 'pitr-usa-id',
|
||||
message:
|
||||
'failed to get dns manager: unknown region: 55985cd4-af14-4d2a-90a5-2a1253ebc1db',
|
||||
stateId: 8,
|
||||
createdAt: '2025-03-10T12:39:23.734345+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
export const getProjectsQuery = nhostGraphQLLink.query('getProjects', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
apps: [
|
||||
{
|
||||
id: 'pitr-usa-id',
|
||||
name: 'pitr-not-enabled-usa',
|
||||
slug: 'pitr-not-enabled-usa',
|
||||
createdAt: '2025-03-10T12:35:23.193578+00:00',
|
||||
subdomain: 'ocrnpctsphttfxkuefyx',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
{
|
||||
id: 'pitr-region-TEST-eu-id',
|
||||
name: 'pitr-region-test-eu',
|
||||
slug: 'pitr-region-test-eu',
|
||||
createdAt: '2025-03-10T12:45:40.813234+00:00',
|
||||
subdomain: 'doszbxwibtopsbfgbjpg',
|
||||
region: {
|
||||
id: 'dd6f8e01-35a9-4ba6-8dc6-ed972f2db93c',
|
||||
name: 'eu-central-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-r-elek-id',
|
||||
email: 'robert@elek.com',
|
||||
displayName: 'Robert',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: 'c7fbf7ad-b60c-432b-86c2-5a9509054c47',
|
||||
appId: 'pitr-region-TEST-eu-id',
|
||||
message: '',
|
||||
stateId: 5,
|
||||
createdAt: '2025-03-12T11:08:59.926611+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-r-elek-id',
|
||||
email: 'robert@elek.com',
|
||||
displayName: 'Robert',
|
||||
__typename: 'users',
|
||||
},
|
||||
{
|
||||
id: 'pitr-test-id',
|
||||
name: 'pitr-test',
|
||||
slug: 'pitr-test',
|
||||
createdAt: '2025-03-04T13:48:59.76498+00:00',
|
||||
subdomain: 'gnlivtcgjxctuujxpslj',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
appStates: [
|
||||
{
|
||||
id: 'cd2b77ac-3ef1-4a76-819b-ff1caca09213',
|
||||
appId: 'pitr-usa-id',
|
||||
message:
|
||||
'failed to get dns manager: unknown region: 55985cd4-af14-4d2a-90a5-2a1253ebc1db',
|
||||
stateId: 8,
|
||||
createdAt: '2025-03-10T12:39:23.734345+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-d-elek-id',
|
||||
email: 'dbarrosop@dravetech.com',
|
||||
displayName: 'David Elek',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: 'fc344bc6-1c59-447a-813f-e0f65754b0e0',
|
||||
appId: 'pitr-test-id',
|
||||
message:
|
||||
'failed to deploy application to kubernetes: failed to deploy application: failed to check rollout status: error running kubectl: exit status 1',
|
||||
stateId: 8,
|
||||
createdAt: '2025-03-11T15:34:41.25304+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
],
|
||||
__typename: 'apps',
|
||||
},
|
||||
{
|
||||
id: 'pitr-region-TEST-eu-id',
|
||||
name: 'pitr-region-test-eu',
|
||||
slug: 'pitr-region-test-eu',
|
||||
createdAt: '2025-03-10T12:45:40.813234+00:00',
|
||||
subdomain: 'doszbxwibtopsbfgbjpg',
|
||||
region: {
|
||||
id: 'dd6f8e01-35a9-4ba6-8dc6-ed972f2db93c',
|
||||
name: 'eu-central-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
{
|
||||
id: 'pitr14-id',
|
||||
name: 'pitr14',
|
||||
slug: 'pitr14',
|
||||
createdAt: '2025-02-25T08:55:22.82937+00:00',
|
||||
subdomain: 'jqumebxpocjytrhevonb',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-d-elek-id',
|
||||
email: 'david@elek.com',
|
||||
displayName: 'David Elek',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: '04bc2db3-a948-48fb-b674-7a8a0133dd2b',
|
||||
appId: 'pitr14-id',
|
||||
message: '',
|
||||
stateId: 5,
|
||||
createdAt: '2025-03-11T20:47:03.102948+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-r-elek-id',
|
||||
email: 'robert@elek.com',
|
||||
displayName: 'Robert',
|
||||
__typename: 'users',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
appStates: [
|
||||
{
|
||||
id: 'c7fbf7ad-b60c-432b-86c2-5a9509054c47',
|
||||
appId: 'pitr-region-TEST-eu-id',
|
||||
message: '',
|
||||
stateId: 5,
|
||||
createdAt: '2025-03-12T11:08:59.926611+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
},
|
||||
{
|
||||
id: 'pitr-test-id',
|
||||
name: 'pitr-test',
|
||||
slug: 'pitr-test',
|
||||
createdAt: '2025-03-04T13:48:59.76498+00:00',
|
||||
subdomain: 'gnlivtcgjxctuujxpslj',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-d-elek-id',
|
||||
email: 'dbarrosop@dravetech.com',
|
||||
displayName: 'David Elek',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: 'fc344bc6-1c59-447a-813f-e0f65754b0e0',
|
||||
appId: 'pitr-test-id',
|
||||
message:
|
||||
'failed to deploy application to kubernetes: failed to deploy application: failed to check rollout status: error running kubectl: exit status 1',
|
||||
stateId: 8,
|
||||
createdAt: '2025-03-11T15:34:41.25304+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
},
|
||||
{
|
||||
id: 'pitr14-id',
|
||||
name: 'pitr14',
|
||||
slug: 'pitr14',
|
||||
createdAt: '2025-02-25T08:55:22.82937+00:00',
|
||||
subdomain: 'jqumebxpocjytrhevonb',
|
||||
region: {
|
||||
id: '1',
|
||||
name: 'us-east-1',
|
||||
__typename: 'regions',
|
||||
},
|
||||
deployments: [],
|
||||
creator: {
|
||||
id: 'creator-d-elek-id',
|
||||
email: 'david@elek.com',
|
||||
displayName: 'David Elek',
|
||||
__typename: 'users',
|
||||
},
|
||||
appStates: [
|
||||
{
|
||||
id: '04bc2db3-a948-48fb-b674-7a8a0133dd2b',
|
||||
appId: 'pitr14-id',
|
||||
message: '',
|
||||
stateId: 5,
|
||||
createdAt: '2025-03-11T20:47:03.102948+00:00',
|
||||
__typename: 'appStateHistory',
|
||||
},
|
||||
],
|
||||
__typename: 'apps',
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const getEmptyProjectsQuery = nhostGraphQLLink.query(
|
||||
'getProjects',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
apps: [],
|
||||
}),
|
||||
),
|
||||
export const getEmptyProjectsQuery = nhostGraphQLLink.query('getProjects', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
apps: [],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,15 +1,16 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const organizationMemberInvites = nhostGraphQLLink.query(
|
||||
'organizationMemberInvites',
|
||||
(_req, res, ctx) => res(ctx.data({ organizationMemberInvites: [] })),
|
||||
() => HttpResponse.json({ data: { organizationMemberInvites: [] } }),
|
||||
);
|
||||
|
||||
export const organizationNewRequests = nhostGraphQLLink.query(
|
||||
'organizationNewRequests',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
organizationNewRequests: [
|
||||
{
|
||||
id: 'org-request-id-1',
|
||||
@@ -17,6 +18,6 @@ export const organizationNewRequests = nhostGraphQLLink.query(
|
||||
__typename: 'organization_new_request',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
const permissionVariablesQuery = nhostGraphQLLink.query(
|
||||
'GetRolesPermissions',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.delay(250),
|
||||
ctx.data({
|
||||
async () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
auth: {
|
||||
user: {
|
||||
@@ -32,8 +32,8 @@ const permissionVariablesQuery = nhostGraphQLLink.query(
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default permissionVariablesQuery;
|
||||
|
||||
@@ -1,50 +1,46 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
/**
|
||||
* Use this handler to simulate a query that returns only the Pro plan.
|
||||
*/
|
||||
export const getProPlanOnlyQuery = nhostGraphQLLink.query(
|
||||
'GetPlans',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
plans: [
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: 'dc5e805e-1bef-4d43-809e-9fdf865e211a',
|
||||
name: 'Pro',
|
||||
price: 25,
|
||||
isFree: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
export const getProPlanOnlyQuery = nhostGraphQLLink.query('GetPlans', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
plans: [
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: 'dc5e805e-1bef-4d43-809e-9fdf865e211a',
|
||||
name: 'Pro',
|
||||
price: 25,
|
||||
isFree: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
* Use this handler to simulate a query that returns all the available plans.
|
||||
*/
|
||||
export const getAllPlansQuery = nhostGraphQLLink.query(
|
||||
'GetPlans',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
plans: [
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: '00000000-0000-0000-0000-000000000000',
|
||||
name: 'Starter',
|
||||
price: 0,
|
||||
isFree: true,
|
||||
},
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: '00000000-0000-0000-0000-000000000001',
|
||||
name: 'Pro',
|
||||
price: 25,
|
||||
isFree: false,
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
export const getAllPlansQuery = nhostGraphQLLink.query('GetPlans', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
plans: [
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: '00000000-0000-0000-0000-000000000000',
|
||||
name: 'Starter',
|
||||
price: 0,
|
||||
isFree: true,
|
||||
},
|
||||
{
|
||||
__typename: 'plans',
|
||||
id: '00000000-0000-0000-0000-000000000001',
|
||||
name: 'Pro',
|
||||
price: 25,
|
||||
isFree: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export const prefetchNewAppQuery = nhostGraphQLLink.query(
|
||||
'PrefetchNewApp',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
regions: [
|
||||
{
|
||||
id: 'dd6f8e01-35a9-4ba6-8dc6-ed972f2db93c',
|
||||
@@ -67,6 +68,6 @@ export const prefetchNewAppQuery = nhostGraphQLLink.query(
|
||||
__typename: 'plans',
|
||||
},
|
||||
],
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
/**
|
||||
* Use this handler to simulate the initial state of the allocated resources.
|
||||
*/
|
||||
export const resourcesUnavailableQuery = nhostGraphQLLink.query(
|
||||
'GetResources',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
__typename: 'ConfigConfig',
|
||||
postgres: {
|
||||
@@ -23,8 +23,8 @@ export const resourcesUnavailableQuery = nhostGraphQLLink.query(
|
||||
resources: null,
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -32,9 +32,9 @@ export const resourcesUnavailableQuery = nhostGraphQLLink.query(
|
||||
*/
|
||||
export const resourcesAvailableQuery = nhostGraphQLLink.query(
|
||||
'GetResources',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
__typename: 'ConfigConfig',
|
||||
postgres: {
|
||||
@@ -86,8 +86,8 @@ export const resourcesAvailableQuery = nhostGraphQLLink.query(
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -95,9 +95,9 @@ export const resourcesAvailableQuery = nhostGraphQLLink.query(
|
||||
*/
|
||||
export const resourcesUpdatedQuery = nhostGraphQLLink.query(
|
||||
'GetResources',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
config: {
|
||||
__typename: 'ConfigConfig',
|
||||
postgres: {
|
||||
@@ -137,6 +137,6 @@ export const resourcesUpdatedQuery = nhostGraphQLLink.query(
|
||||
},
|
||||
},
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
import { HttpResponse } from 'msw';
|
||||
import nhostGraphQLLink from './nhostGraphQLLink';
|
||||
|
||||
export default nhostGraphQLLink.mutation('UpdateConfig', (req, res, ctx) =>
|
||||
res(
|
||||
ctx.data({
|
||||
export default nhostGraphQLLink.mutation('UpdateConfig', () =>
|
||||
HttpResponse.json({
|
||||
data: {
|
||||
updateConfig: {
|
||||
id: 'ConfigConfig',
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -1,419 +1,415 @@
|
||||
import { rest } from 'msw';
|
||||
import { delay, http, HttpResponse } from 'msw';
|
||||
|
||||
const hasuraMetadataQuery = rest.post(
|
||||
const hasuraMetadataQuery = http.post(
|
||||
'https://local.hasura.local.nhost.run/v1/metadata',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.delay(250),
|
||||
ctx.json({
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: { name: 'authors', schema: 'public' },
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'books',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'author_id',
|
||||
table: { name: 'books', schema: 'public' },
|
||||
},
|
||||
async () => {
|
||||
await delay(250);
|
||||
|
||||
return HttpResponse.json({
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: { name: 'authors', schema: 'public' },
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'books',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'author_id',
|
||||
table: { name: 'books', schema: 'public' },
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: { name: 'books', schema: 'public' },
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: { foreign_key_constraint_on: 'author_id' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: { from_env: 'HASURA_GRAPHQL_DATABASE_URL' },
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
],
|
||||
},
|
||||
{
|
||||
table: { name: 'books', schema: 'public' },
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: { foreign_key_constraint_on: 'author_id' },
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: { from_env: 'HASURA_GRAPHQL_DATABASE_URL' },
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
resource_version: 10,
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
resource_version: 10,
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
export const hasuraRelationShipsMetadataQuery = rest.post(
|
||||
export const hasuraRelationShipsMetadataQuery = http.post(
|
||||
'https://local.hasura.local.nhost.run/v1/metadata',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
resource_version: 26,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: {
|
||||
name: 'country',
|
||||
schema: 'public',
|
||||
},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'county',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'countryId',
|
||||
table: {
|
||||
name: 'county',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
resource_version: 26,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: {
|
||||
name: 'country',
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
table: {
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'county',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'country',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'countryId',
|
||||
},
|
||||
},
|
||||
],
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'town',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'countyId',
|
||||
table: {
|
||||
name: 'town',
|
||||
schema: 'public',
|
||||
},
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'countryId',
|
||||
table: {
|
||||
name: 'county',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'town',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'county',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'countyId',
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'county',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'country',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'countryId',
|
||||
},
|
||||
},
|
||||
],
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'town',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'countyId',
|
||||
table: {
|
||||
name: 'town',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'town',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'county',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'countyId',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export const hasuraColumnMetadataQuery = rest.post(
|
||||
export const hasuraColumnMetadataQuery = http.post(
|
||||
'https://local.hasura.local.nhost.run/v1/metadata',
|
||||
(_req, res, ctx) =>
|
||||
res(
|
||||
ctx.json({
|
||||
resource_version: 389,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: {
|
||||
name: 'actor',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'actor_movie',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'actor_id',
|
||||
table: {
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
() =>
|
||||
HttpResponse.json({
|
||||
resource_version: 389,
|
||||
metadata: {
|
||||
version: 3,
|
||||
sources: [
|
||||
{
|
||||
name: 'default',
|
||||
kind: 'postgres',
|
||||
tables: [
|
||||
{
|
||||
table: {
|
||||
name: 'actor',
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
table: {
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'actor',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'actor_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'movie',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'movie_id',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'director',
|
||||
schema: 'public',
|
||||
},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'movies',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'director_id',
|
||||
table: {
|
||||
name: 'movies',
|
||||
schema: 'public',
|
||||
},
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'actor_id',
|
||||
table: {
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
table: {
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'actor',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'actor_id',
|
||||
},
|
||||
},
|
||||
{
|
||||
name: 'movie',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'movie_id',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'director',
|
||||
schema: 'public',
|
||||
},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'movies',
|
||||
schema: 'public',
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'director_id',
|
||||
},
|
||||
},
|
||||
],
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'actor_movie',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'movie_id',
|
||||
table: {
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'director_id',
|
||||
table: {
|
||||
name: 'movies',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'movies',
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'notes',
|
||||
schema: 'public',
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'author',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'director_id',
|
||||
},
|
||||
},
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'user',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'owner',
|
||||
},
|
||||
},
|
||||
],
|
||||
insert_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
check: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
columns: ['id', 'note', 'owner'],
|
||||
},
|
||||
},
|
||||
],
|
||||
select_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
columns: ['id', 'note'],
|
||||
filter: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
],
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'actor_movie',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'movie_id',
|
||||
table: {
|
||||
name: 'actor_movie',
|
||||
schema: 'public',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
update_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
columns: ['note'],
|
||||
filter: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
check: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
delete_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
filter: {
|
||||
id: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'notes',
|
||||
schema: 'public',
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'buckets',
|
||||
schema: 'storage',
|
||||
},
|
||||
configuration: {
|
||||
column_config: {
|
||||
cache_control: {
|
||||
custom_name: 'cacheControl',
|
||||
},
|
||||
created_at: {
|
||||
custom_name: 'createdAt',
|
||||
},
|
||||
download_expiration: {
|
||||
custom_name: 'downloadExpiration',
|
||||
},
|
||||
id: {
|
||||
custom_name: 'id',
|
||||
},
|
||||
max_upload_file_size: {
|
||||
custom_name: 'maxUploadFileSize',
|
||||
},
|
||||
min_upload_file_size: {
|
||||
custom_name: 'minUploadFileSize',
|
||||
},
|
||||
presigned_urls_enabled: {
|
||||
custom_name: 'presignedUrlsEnabled',
|
||||
},
|
||||
updated_at: {
|
||||
custom_name: 'updatedAt',
|
||||
},
|
||||
},
|
||||
custom_column_names: {
|
||||
cache_control: 'cacheControl',
|
||||
created_at: 'createdAt',
|
||||
download_expiration: 'downloadExpiration',
|
||||
id: 'id',
|
||||
max_upload_file_size: 'maxUploadFileSize',
|
||||
min_upload_file_size: 'minUploadFileSize',
|
||||
presigned_urls_enabled: 'presignedUrlsEnabled',
|
||||
updated_at: 'updatedAt',
|
||||
},
|
||||
custom_name: 'buckets',
|
||||
custom_root_fields: {
|
||||
delete: 'deleteBuckets',
|
||||
delete_by_pk: 'deleteBucket',
|
||||
insert: 'insertBuckets',
|
||||
insert_one: 'insertBucket',
|
||||
select: 'buckets',
|
||||
select_aggregate: 'bucketsAggregate',
|
||||
select_by_pk: 'bucket',
|
||||
update: 'updateBuckets',
|
||||
update_by_pk: 'updateBucket',
|
||||
object_relationships: [
|
||||
{
|
||||
name: 'user',
|
||||
using: {
|
||||
foreign_key_constraint_on: 'owner',
|
||||
},
|
||||
},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'files',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'bucket_id',
|
||||
table: {
|
||||
name: 'files',
|
||||
schema: 'storage',
|
||||
},
|
||||
],
|
||||
insert_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
check: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
columns: ['id', 'note', 'owner'],
|
||||
},
|
||||
},
|
||||
],
|
||||
select_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
columns: ['id', 'note'],
|
||||
filter: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
],
|
||||
update_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
columns: ['note'],
|
||||
filter: {
|
||||
owner: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
check: null,
|
||||
},
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
],
|
||||
delete_permissions: [
|
||||
{
|
||||
role: 'user',
|
||||
permission: {
|
||||
filter: {
|
||||
id: {
|
||||
_eq: 'X-Hasura-User-Id',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
{
|
||||
table: {
|
||||
name: 'buckets',
|
||||
schema: 'storage',
|
||||
},
|
||||
configuration: {
|
||||
column_config: {
|
||||
cache_control: {
|
||||
custom_name: 'cacheControl',
|
||||
},
|
||||
created_at: {
|
||||
custom_name: 'createdAt',
|
||||
},
|
||||
download_expiration: {
|
||||
custom_name: 'downloadExpiration',
|
||||
},
|
||||
id: {
|
||||
custom_name: 'id',
|
||||
},
|
||||
max_upload_file_size: {
|
||||
custom_name: 'maxUploadFileSize',
|
||||
},
|
||||
min_upload_file_size: {
|
||||
custom_name: 'minUploadFileSize',
|
||||
},
|
||||
presigned_urls_enabled: {
|
||||
custom_name: 'presignedUrlsEnabled',
|
||||
},
|
||||
updated_at: {
|
||||
custom_name: 'updatedAt',
|
||||
},
|
||||
},
|
||||
custom_column_names: {
|
||||
cache_control: 'cacheControl',
|
||||
created_at: 'createdAt',
|
||||
download_expiration: 'downloadExpiration',
|
||||
id: 'id',
|
||||
max_upload_file_size: 'maxUploadFileSize',
|
||||
min_upload_file_size: 'minUploadFileSize',
|
||||
presigned_urls_enabled: 'presignedUrlsEnabled',
|
||||
updated_at: 'updatedAt',
|
||||
},
|
||||
custom_name: 'buckets',
|
||||
custom_root_fields: {
|
||||
delete: 'deleteBuckets',
|
||||
delete_by_pk: 'deleteBucket',
|
||||
insert: 'insertBuckets',
|
||||
insert_one: 'insertBucket',
|
||||
select: 'buckets',
|
||||
select_aggregate: 'bucketsAggregate',
|
||||
select_by_pk: 'bucket',
|
||||
update: 'updateBuckets',
|
||||
update_by_pk: 'updateBucket',
|
||||
},
|
||||
},
|
||||
array_relationships: [
|
||||
{
|
||||
name: 'files',
|
||||
using: {
|
||||
foreign_key_constraint_on: {
|
||||
column: 'bucket_id',
|
||||
table: {
|
||||
name: 'files',
|
||||
schema: 'storage',
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
configuration: {
|
||||
connection_info: {
|
||||
database_url: {
|
||||
from_env: 'HASURA_GRAPHQL_DATABASE_URL',
|
||||
},
|
||||
isolation_level: 'read-committed',
|
||||
pool_settings: {
|
||||
connection_lifetime: 600,
|
||||
idle_timeout: 180,
|
||||
max_connections: 50,
|
||||
retries: 1,
|
||||
},
|
||||
use_prepared_statements: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
),
|
||||
},
|
||||
],
|
||||
},
|
||||
}),
|
||||
);
|
||||
|
||||
export default hasuraMetadataQuery;
|
||||
|
||||
@@ -1,143 +1,23 @@
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
|
||||
const tableQuery = rest.post(
|
||||
const tableQuery = http.post(
|
||||
'https://local.hasura.local.nhost.run/v2/query',
|
||||
async (req, res, ctx) => {
|
||||
const body = await req.json();
|
||||
if (/table_name = 'authors'/gim.exec(body.args[0].args.sql) !== null) {
|
||||
return res(
|
||||
ctx.delay(250),
|
||||
ctx.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"birth_date","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"timestamp without time zone","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":6,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"timestamp","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{ result_type: 'TuplesOk', result: [['row_to_json']] },
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"authors_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{ result_type: 'TuplesOk', result: [['count'], ['0']] },
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
if (/table_name = 'town'/gim.exec(body.args[0].args.sql) !== null) {
|
||||
return res(
|
||||
ctx.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"text","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"countyId","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['row_to_json']],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"town_countyId_fkey","constraint_type":"f","constraint_definition":"FOREIGN KEY (\\"countyId\\") REFERENCES county(id) ON UPDATE RESTRICT ON DELETE RESTRICT","column_name":"countyId"}',
|
||||
],
|
||||
[
|
||||
'{"constraint_name":"town_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['count'], ['0']],
|
||||
},
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
if (/table_name = 'actor'/gim.exec(body.args[0].args.sql) !== null) {
|
||||
return res(
|
||||
ctx.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"klkudrtrpapfrseiidkp","table_schema":"public","table_name":"actor","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"klkudrtrpapfrseiidkp","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"klkudrtrpapfrseiidkp","table_schema":"public","table_name":"actor","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"klkudrtrpapfrseiidkp","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"text","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
['{"id":"1902e481-b080-4340-abe3-27b0a60973c6","name":"There"}'],
|
||||
['{"id":"a486b088-50e8-41d0-88b0-5bf9a3e7b5e7","name":"hello"}'],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"actor_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['count'], ['2']],
|
||||
},
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
return res(
|
||||
ctx.delay(250),
|
||||
ctx.json([
|
||||
async ({ request }) => {
|
||||
const body = (await request.json()) as any;
|
||||
if (/table_name = 'authors'/gim.exec(body?.args?.[0].args.sql) !== null) {
|
||||
return HttpResponse.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"title","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"release_date","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"timestamp without time zone","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":6,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"timestamp","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"author_id","ordinal_position":4,"column_default":null,"is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"4","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"authors","column_name":"birth_date","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"timestamp without time zone","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":6,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"timestamp","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
@@ -147,16 +27,126 @@ const tableQuery = rest.post(
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"books_author_id_fkey","constraint_type":"f","constraint_definition":"FOREIGN KEY (author_id) REFERENCES authors(id) ON UPDATE RESTRICT ON DELETE RESTRICT","column_name":"author_id"}',
|
||||
],
|
||||
[
|
||||
'{"constraint_name":"books_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
'{"constraint_name":"authors_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{ result_type: 'TuplesOk', result: [['count'], ['0']] },
|
||||
]),
|
||||
);
|
||||
]);
|
||||
}
|
||||
|
||||
if (/table_name = 'town'/gim.exec(body.args[0].args.sql) !== null) {
|
||||
return HttpResponse.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"text","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"local","table_schema":"public","table_name":"town","column_name":"countyId","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"local","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['row_to_json']],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"town_countyId_fkey","constraint_type":"f","constraint_definition":"FOREIGN KEY (\\"countyId\\") REFERENCES county(id) ON UPDATE RESTRICT ON DELETE RESTRICT","column_name":"countyId"}',
|
||||
],
|
||||
[
|
||||
'{"constraint_name":"town_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['count'], ['0']],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
if (/table_name = 'actor'/gim.exec(body.args[0].args.sql) !== null) {
|
||||
return HttpResponse.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"klkudrtrpapfrseiidkp","table_schema":"public","table_name":"actor","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"klkudrtrpapfrseiidkp","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"uuid","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"klkudrtrpapfrseiidkp","table_schema":"public","table_name":"actor","column_name":"name","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"klkudrtrpapfrseiidkp","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","full_data_type":"text","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
['{"id":"1902e481-b080-4340-abe3-27b0a60973c6","name":"There"}'],
|
||||
['{"id":"a486b088-50e8-41d0-88b0-5bf9a3e7b5e7","name":"hello"}'],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"actor_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [['count'], ['2']],
|
||||
},
|
||||
]);
|
||||
}
|
||||
|
||||
return HttpResponse.json([
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"id","ordinal_position":1,"column_default":"gen_random_uuid()","is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"1","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":true,"is_unique":true,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"title","ordinal_position":2,"column_default":null,"is_nullable":"NO","data_type":"text","character_maximum_length":null,"character_octet_length":1073741824,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"text","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"2","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"release_date","ordinal_position":3,"column_default":null,"is_nullable":"NO","data_type":"timestamp without time zone","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":6,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"timestamp","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"3","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
[
|
||||
'{"table_catalog":"pqfgbylcwyuertjcrmgy","table_schema":"public","table_name":"books","column_name":"author_id","ordinal_position":4,"column_default":null,"is_nullable":"NO","data_type":"uuid","character_maximum_length":null,"character_octet_length":null,"numeric_precision":null,"numeric_precision_radix":null,"numeric_scale":null,"datetime_precision":null,"interval_type":null,"interval_precision":null,"character_set_catalog":null,"character_set_schema":null,"character_set_name":null,"collation_catalog":null,"collation_schema":null,"collation_name":null,"domain_catalog":null,"domain_schema":null,"domain_name":null,"udt_catalog":"pqfgbylcwyuertjcrmgy","udt_schema":"pg_catalog","udt_name":"uuid","scope_catalog":null,"scope_schema":null,"scope_name":null,"maximum_cardinality":null,"dtd_identifier":"4","is_self_referencing":"NO","is_identity":"NO","identity_generation":null,"identity_start":null,"identity_increment":null,"identity_maximum":null,"identity_minimum":null,"identity_cycle":"NO","is_generated":"NEVER","generation_expression":null,"is_updatable":"YES","is_primary":false,"is_unique":false,"column_comment":null}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{ result_type: 'TuplesOk', result: [['row_to_json']] },
|
||||
{
|
||||
result_type: 'TuplesOk',
|
||||
result: [
|
||||
['row_to_json'],
|
||||
[
|
||||
'{"constraint_name":"books_author_id_fkey","constraint_type":"f","constraint_definition":"FOREIGN KEY (author_id) REFERENCES authors(id) ON UPDATE RESTRICT ON DELETE RESTRICT","column_name":"author_id"}',
|
||||
],
|
||||
[
|
||||
'{"constraint_name":"books_pkey","constraint_type":"p","constraint_definition":"PRIMARY KEY (id)","column_name":"id"}',
|
||||
],
|
||||
],
|
||||
},
|
||||
{ result_type: 'TuplesOk', result: [['count'], ['0']] },
|
||||
]);
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { mockSession } from '@/tests/mocks';
|
||||
import type { Session } from '@nhost/nhost-js/auth';
|
||||
import { rest } from 'msw';
|
||||
import { http, HttpResponse } from 'msw';
|
||||
|
||||
const tokenQuery = rest.post(
|
||||
const tokenQuery = http.post(
|
||||
'https://local.auth.local.nhost.run/v1/token',
|
||||
(_req, res, ctx) => res(ctx.json<Session>(mockSession)),
|
||||
() => HttpResponse.json<Session>(mockSession),
|
||||
);
|
||||
|
||||
export default tokenQuery;
|
||||
|
||||
@@ -35,6 +35,7 @@ import userEvent, {
|
||||
type Options,
|
||||
type UserEvent,
|
||||
} from '@testing-library/user-event';
|
||||
import { HttpResponse } from 'msw';
|
||||
import { RouterContext } from 'next/dist/shared/lib/router-context.shared-runtime';
|
||||
import type { PropsWithChildren, ReactElement } from 'react';
|
||||
import { Toaster } from 'react-hot-toast';
|
||||
@@ -154,9 +155,9 @@ const graphqlRequestHandlerFactory = (
|
||||
type: 'mutation' | 'query',
|
||||
responsePromise: any,
|
||||
) =>
|
||||
nhostGraphQLLink[type](operationName, async (_req, res, ctx) => {
|
||||
nhostGraphQLLink[type](operationName, async () => {
|
||||
const data = await responsePromise;
|
||||
return res(ctx.data(data));
|
||||
return HttpResponse.json({ data });
|
||||
});
|
||||
/* Helper function to pause responses to be able to test loading states */
|
||||
export const createGraphqlMockResolver = (
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
"test:broken-links": "pnpm exec mintlify broken-links"
|
||||
},
|
||||
"devDependencies": {
|
||||
"mintlify": "^4.2.87",
|
||||
"mintlify": "^4.2.158",
|
||||
"prettier": "^3.5.3",
|
||||
"typedoc": "^0.28.4",
|
||||
"typedoc-plugin-markdown": "^4.6.3"
|
||||
|
||||
@@ -10,10 +10,10 @@ The Nhost CLI provides flexible development workflows that adapt to your needs.
|
||||
## Development Workflows
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Local Development" icon="laptop-code">
|
||||
<Card title="Local Development" icon="laptop-code" href="/platform/cli/local-development">
|
||||
Run the complete Nhost stack locally for offline development, fast iteration, and full control over your environment.
|
||||
</Card>
|
||||
<Card title="Cloud Development" icon="cloud">
|
||||
<Card title="Cloud Development" icon="cloud" href="/platform/cli/cloud-development">
|
||||
Develop against cloud infrastructure while maintaining local tools for simplified remote testing and team collaboration.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
1696
docs/pnpm-lock.yaml
generated
1696
docs/pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -590,11 +590,13 @@ This method may return different T based on the response code:
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
```
|
||||
|
||||
Add a middleware function to the fetch chain
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Parameter | Type |
|
||||
| --------------- | ------------------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) |
|
||||
| Parameter | Type | Description |
|
||||
| --------------- | ------------------------------------------ | ------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) | The middleware function to add |
|
||||
|
||||
##### Returns
|
||||
|
||||
|
||||
@@ -207,6 +207,24 @@ For a more generic request, use the `fetch` method instead.
|
||||
|
||||
Promise with the function response and metadata
|
||||
|
||||
#### pushChainFunction()
|
||||
|
||||
```ts
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
```
|
||||
|
||||
Add a middleware function to the fetch chain
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------------- | ------------------------------------------ | ------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) | The middleware function to add |
|
||||
|
||||
##### Returns
|
||||
|
||||
`void`
|
||||
|
||||
# Functions
|
||||
|
||||
## createAPIClient()
|
||||
|
||||
@@ -289,6 +289,24 @@ URL for the GraphQL endpoint.
|
||||
|
||||
### Methods
|
||||
|
||||
#### pushChainFunction()
|
||||
|
||||
```ts
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
```
|
||||
|
||||
Add a middleware function to the fetch chain
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Parameter | Type | Description |
|
||||
| --------------- | ------------------------------------------ | ------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) | The middleware function to add |
|
||||
|
||||
##### Returns
|
||||
|
||||
`void`
|
||||
|
||||
#### request()
|
||||
|
||||
##### Call Signature
|
||||
|
||||
@@ -399,11 +399,13 @@ This method may return different T based on the response code:
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
```
|
||||
|
||||
Add a middleware function to the fetch chain
|
||||
|
||||
##### Parameters
|
||||
|
||||
| Parameter | Type |
|
||||
| --------------- | ------------------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) |
|
||||
| Parameter | Type | Description |
|
||||
| --------------- | ------------------------------------------ | ------------------------------ |
|
||||
| `chainFunction` | [`ChainFunction`](./fetch#chainfunction) | The middleware function to add |
|
||||
|
||||
##### Returns
|
||||
|
||||
|
||||
10
go.mod
10
go.mod
@@ -37,9 +37,6 @@ require (
|
||||
github.com/pquerna/otp v1.5.0
|
||||
github.com/rs/cors/wrapper/gin v0.0.0-20240830163046-1084d89a1692
|
||||
github.com/sirupsen/logrus v1.9.3
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/spf13/viper v1.21.0
|
||||
github.com/stretchr/testify v1.11.1
|
||||
github.com/twilio/twilio-go v1.28.3
|
||||
github.com/urfave/cli-docs/v3 v3.0.0-alpha6
|
||||
@@ -100,7 +97,6 @@ require (
|
||||
github.com/cyphar/filepath-securejoin v0.4.1 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/emirpasic/gods v1.18.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/gin-contrib/sse v1.1.0 // indirect
|
||||
github.com/go-git/gcfg v1.5.1-0.20230307220236-3a3c6141e376 // indirect
|
||||
@@ -125,7 +121,6 @@ require (
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/invopop/jsonschema v0.13.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
@@ -165,15 +160,11 @@ require (
|
||||
github.com/rivo/uniseg v0.4.7 // indirect
|
||||
github.com/rs/cors v1.11.0 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.11.0 // indirect
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 // indirect
|
||||
github.com/skeema/knownhosts v1.3.1 // indirect
|
||||
github.com/sosodev/duration v1.3.1 // indirect
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect
|
||||
github.com/speakeasy-api/jsonpath v0.6.2 // indirect
|
||||
github.com/spf13/afero v1.15.0 // indirect
|
||||
github.com/spf13/cast v1.10.0 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
github.com/tidwall/gjson v1.18.0 // indirect
|
||||
github.com/tidwall/match v1.1.1 // indirect
|
||||
github.com/tidwall/pretty v1.2.1 // indirect
|
||||
@@ -189,7 +180,6 @@ require (
|
||||
github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect
|
||||
github.com/yosida95/uritemplate/v3 v3.0.2 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.61.0 // indirect
|
||||
go.yaml.in/yaml/v3 v3.0.4 // indirect
|
||||
golang.org/x/arch v0.20.0 // indirect
|
||||
golang.org/x/image v0.18.0 // indirect
|
||||
golang.org/x/net v0.44.0 // indirect
|
||||
|
||||
22
go.sum
22
go.sum
@@ -116,7 +116,6 @@ github.com/containerd/errdefs v1.0.0 h1:tg5yIfIlQIrxYtu9ajqY42W3lpS19XqdxRQeEwYG
|
||||
github.com/containerd/errdefs v1.0.0/go.mod h1:+YBYIdtsnF4Iw6nWZhJcqGSg/dwvV7tyJ/kCkyJ2k+M=
|
||||
github.com/containerd/errdefs/pkg v0.3.0 h1:9IKJ06FvyNlexW690DXuQNx2KA2cUJXx151Xdx3ZPPE=
|
||||
github.com/containerd/errdefs/pkg v0.3.0/go.mod h1:NJw6s9HwNuRhnjJhM7pylWwMyAkmCQvQ4GpJHEqRLVk=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7 h1:zbFlGlXEAKlwXpmvle3d8Oe3YnkKIK4xSRTd3sHPnBo=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.7/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
@@ -157,8 +156,6 @@ github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSw
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.8 h1:FfZ3gj38NjllZIeJAmMhr+qKL8Wu+nOoI3GqacKw1NM=
|
||||
@@ -263,8 +260,6 @@ github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/invopop/jsonschema v0.13.0 h1:KvpoAJWEjR3uD9Kbm2HWJmqsEaHt8lBUpd0qHcIi21E=
|
||||
github.com/invopop/jsonschema v0.13.0/go.mod h1:ffZ5Km5SWWRAIN6wbDXItl95euhFz2uON45H2qjYt+0=
|
||||
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
|
||||
@@ -403,8 +398,6 @@ github.com/rs/cors/wrapper/gin v0.0.0-20240830163046-1084d89a1692 h1:lwzJgPw5Y6p
|
||||
github.com/rs/cors/wrapper/gin v0.0.0-20240830163046-1084d89a1692/go.mod h1:742Ialb8SOs5yB2PqRDzFcyND3280PoaS5/wcKQUQKE=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc=
|
||||
github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3 h1:n661drycOFuPLCN3Uc8sB6B/s6Z4t2xvBgU1htSHuq8=
|
||||
github.com/sergi/go-diff v1.3.2-0.20230802210424-5b0b94c5c0d3/go.mod h1:A0bzQcvG0E7Rwjx0REVgAGH58e96+X0MeOfepqsbeW4=
|
||||
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||
@@ -414,22 +407,11 @@ github.com/skeema/knownhosts v1.3.1 h1:X2osQ+RAjK76shCbvhHHHVl3ZlgDm8apHEHFqRjnB
|
||||
github.com/skeema/knownhosts v1.3.1/go.mod h1:r7KTdC8l4uxWRyK2TpQZ/1o5HaSzh06ePQNxPwTcfiY=
|
||||
github.com/sosodev/duration v1.3.1 h1:qtHBDMQ6lvMQsL15g4aopM4HEfOaYuhWBw3NPTtlqq4=
|
||||
github.com/sosodev/duration v1.3.1/go.mod h1:RQIBBX0+fMLc/D9+Jb/fwvVmo0eZvDDEERAikUR6SDg=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw=
|
||||
github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U=
|
||||
github.com/speakeasy-api/jsonpath v0.6.2 h1:Mys71yd6u8kuowNCR0gCVPlVAHCmKtoGXYoAtcEbqXQ=
|
||||
github.com/speakeasy-api/jsonpath v0.6.2/go.mod h1:ymb2iSkyOycmzKwbEAYPJV/yi2rSmvBCLZJcyD+VVWw=
|
||||
github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I=
|
||||
github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk=
|
||||
github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU=
|
||||
github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY=
|
||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
@@ -444,8 +426,6 @@ github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO
|
||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U=
|
||||
github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
|
||||
github.com/tidwall/gjson v1.18.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||
@@ -502,8 +482,6 @@ go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mx
|
||||
go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0=
|
||||
go.uber.org/mock v0.5.0 h1:KAMbZvZPyBPWgD14IrIQ38QCyjwpvVVV6K/bHl1IwQU=
|
||||
go.uber.org/mock v0.5.0/go.mod h1:ge71pBPLYDk7QIi1LupWxdAykm7KIEFchiOqd6z7qMM=
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/arch v0.20.0 h1:dx1zTU0MAE98U+TQ8BLl7XsJbgze2WnNKF/8tGp/Q6c=
|
||||
golang.org/x/arch v0.20.0/go.mod h1:bdwinDaKcfZUGpH09BB7ZmOfhalA8lQdzl62l8gGWsk=
|
||||
golang.org/x/crypto v0.0.0-20181025213731-e84da0312774/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
|
||||
|
||||
@@ -104,9 +104,11 @@ let
|
||||
dir=$(realpath --relative-to="$PWD" "$absdir")
|
||||
echo " ➜ Copying node_modules for $dir"
|
||||
cp -r ${node_modules}/$dir/node_modules $dir/node_modules
|
||||
done
|
||||
|
||||
pnpm audit-ci
|
||||
echo " ➜ Running pnpm audit-ci for $dir"
|
||||
pnpm audit-ci --directory $dir
|
||||
|
||||
done
|
||||
|
||||
${preCheck}
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@
|
||||
"turbo": "2.3.3",
|
||||
"typescript": "5.8.3",
|
||||
"vite": "^5.4.20",
|
||||
"vite-plugin-dts": "^3.9.1",
|
||||
"vite-tsconfig-paths": "^4.3.2",
|
||||
"vitest": "^0.32.4"
|
||||
},
|
||||
|
||||
@@ -103,7 +103,7 @@
|
||||
"devDependencies": {
|
||||
"@graphql-typed-document-node/core": "^3.2.0",
|
||||
"@jest/globals": "^29.7.0",
|
||||
"@rollup/plugin-node-resolve": "^16.0.1",
|
||||
"@rollup/plugin-node-resolve": "^16.0.2",
|
||||
"@types/jest": "^29.5.14",
|
||||
"@types/node": "^22.15.17",
|
||||
"@types/rollup-plugin-peer-deps-external": "^2.2.5",
|
||||
@@ -118,5 +118,10 @@
|
||||
"sideEffects": false,
|
||||
"dependencies": {
|
||||
"tslib": "^2.8.1"
|
||||
},
|
||||
"pnpm": {
|
||||
"overrides": {
|
||||
"rollup@<2.79.2": ">=2.79.2"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
254
packages/nhost-js/pnpm-lock.yaml
generated
254
packages/nhost-js/pnpm-lock.yaml
generated
@@ -4,6 +4,9 @@ settings:
|
||||
autoInstallPeers: true
|
||||
excludeLinksFromLockfile: false
|
||||
|
||||
overrides:
|
||||
rollup@<2.79.2: '>=2.79.2'
|
||||
|
||||
importers:
|
||||
|
||||
.:
|
||||
@@ -19,8 +22,8 @@ importers:
|
||||
specifier: ^29.7.0
|
||||
version: 29.7.0
|
||||
'@rollup/plugin-node-resolve':
|
||||
specifier: ^16.0.1
|
||||
version: 16.0.1(rollup@0.63.5)
|
||||
specifier: ^16.0.2
|
||||
version: 16.0.2(rollup@4.52.4)
|
||||
'@types/jest':
|
||||
specifier: ^29.5.14
|
||||
version: 29.5.14
|
||||
@@ -44,7 +47,7 @@ importers:
|
||||
version: 3.6.2
|
||||
rollup-plugin-peer-deps-external:
|
||||
specifier: ^2.2.4
|
||||
version: 2.2.4(rollup@0.63.5)
|
||||
version: 2.2.4(rollup@4.52.4)
|
||||
terser:
|
||||
specifier: ^5.39.0
|
||||
version: 5.39.0
|
||||
@@ -318,24 +321,134 @@ packages:
|
||||
'@jridgewell/trace-mapping@0.3.30':
|
||||
resolution: {integrity: sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==}
|
||||
|
||||
'@rollup/plugin-node-resolve@16.0.1':
|
||||
resolution: {integrity: sha512-tk5YCxJWIG81umIvNkSod2qK5KyQW19qcBF/B78n1bjtOON6gzKoVeSzAE8yHCZEDmqkHKkxplExA8KzdJLJpA==}
|
||||
'@rollup/plugin-node-resolve@16.0.2':
|
||||
resolution: {integrity: sha512-tCtHJ2BlhSoK4cCs25NMXfV7EALKr0jyasmqVCq3y9cBrKdmJhtsy1iTz36Xhk/O+pDJbzawxF4K6ZblqCnITQ==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^2.78.0||^3.0.0||^4.0.0
|
||||
rollup: '>=2.79.2'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/pluginutils@5.2.0':
|
||||
resolution: {integrity: sha512-qWJ2ZTbmumwiLFomfzTyt5Kng4hwPi9rwCYN4SHb6eaRU1KNO4ccxINHr/VhH4GgPlt1XfSTLX2LBTme8ne4Zw==}
|
||||
'@rollup/pluginutils@5.3.0':
|
||||
resolution: {integrity: sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==}
|
||||
engines: {node: '>=14.0.0'}
|
||||
peerDependencies:
|
||||
rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0
|
||||
rollup: '>=2.79.2'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.52.4':
|
||||
resolution: {integrity: sha512-BTm2qKNnWIQ5auf4deoetINJm2JzvihvGb9R6K/ETwKLql/Bb3Eg2H1FBp1gUb4YGbydMA3jcmQTR73q7J+GAA==}
|
||||
cpu: [arm]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-android-arm64@4.52.4':
|
||||
resolution: {integrity: sha512-P9LDQiC5vpgGFgz7GSM6dKPCiqR3XYN1WwJKA4/BUVDjHpYsf3iBEmVz62uyq20NGYbiGPR5cNHI7T1HqxNs2w==}
|
||||
cpu: [arm64]
|
||||
os: [android]
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.52.4':
|
||||
resolution: {integrity: sha512-QRWSW+bVccAvZF6cbNZBJwAehmvG9NwfWHwMy4GbWi/BQIA/laTIktebT2ipVjNncqE6GLPxOok5hsECgAxGZg==}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.52.4':
|
||||
resolution: {integrity: sha512-hZgP05pResAkRJxL1b+7yxCnXPGsXU0fG9Yfd6dUaoGk+FhdPKCJ5L1Sumyxn8kvw8Qi5PvQ8ulenUbRjzeCTw==}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.52.4':
|
||||
resolution: {integrity: sha512-xmc30VshuBNUd58Xk4TKAEcRZHaXlV+tCxIXELiE9sQuK3kG8ZFgSPi57UBJt8/ogfhAF5Oz4ZSUBN77weM+mQ==}
|
||||
cpu: [arm64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.52.4':
|
||||
resolution: {integrity: sha512-WdSLpZFjOEqNZGmHflxyifolwAiZmDQzuOzIq9L27ButpCVpD7KzTRtEG1I0wMPFyiyUdOO+4t8GvrnBLQSwpw==}
|
||||
cpu: [x64]
|
||||
os: [freebsd]
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.52.4':
|
||||
resolution: {integrity: sha512-xRiOu9Of1FZ4SxVbB0iEDXc4ddIcjCv2aj03dmW8UrZIW7aIQ9jVJdLBIhxBI+MaTnGAKyvMwPwQnoOEvP7FgQ==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.52.4':
|
||||
resolution: {integrity: sha512-FbhM2p9TJAmEIEhIgzR4soUcsW49e9veAQCziwbR+XWB2zqJ12b4i/+hel9yLiD8pLncDH4fKIPIbt5238341Q==}
|
||||
cpu: [arm]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-4n4gVwhPHR9q/g8lKCyz0yuaD0MvDf7dV4f9tHt0C73Mp8h38UCtSCSE6R9iBlTbXlmA8CjpsZoujhszefqueg==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.52.4':
|
||||
resolution: {integrity: sha512-u0n17nGA0nvi/11gcZKsjkLj1QIpAuPFQbR48Subo7SmZJnGxDpspyw2kbpuoQnyK+9pwf3pAoEXerJs/8Mi9g==}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-0G2c2lpYtbTuXo8KEJkDkClE/+/2AFPdPAbmaHoE870foRFs4pBrDehilMcrSScrN/fB/1HTaWO4bqw+ewBzMQ==}
|
||||
cpu: [loong64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-teSACug1GyZHmPDv14VNbvZFX779UqWTsd7KtTM9JIZRDI5NUwYSIS30kzI8m06gOPB//jtpqlhmraQ68b5X2g==}
|
||||
cpu: [ppc64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-/MOEW3aHjjs1p4Pw1Xk4+3egRevx8Ji9N6HUIA1Ifh8Q+cg9dremvFCUbOX2Zebz80BwJIgCBUemjqhU5XI5Eg==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.52.4':
|
||||
resolution: {integrity: sha512-1HHmsRyh845QDpEWzOFtMCph5Ts+9+yllCrREuBR/vg2RogAQGGBRC8lDPrPOMnrdOJ+mt1WLMOC2Kao/UwcvA==}
|
||||
cpu: [riscv64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-seoeZp4L/6D1MUyjWkOMRU6/iLmCU2EjbMTyAG4oIOs1/I82Y5lTeaxW0KBfkUdHAWN7j25bpkt0rjnOgAcQcA==}
|
||||
cpu: [s390x]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-Wi6AXf0k0L7E2gteNsNHUs7UMwCIhsCTs6+tqQ5GPwVRWMaflqGec4Sd8n6+FNFDw9vGcReqk2KzBDhCa1DLYg==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.52.4':
|
||||
resolution: {integrity: sha512-dtBZYjDmCQ9hW+WgEkaffvRRCKm767wWhxsFW3Lw86VXz/uJRuD438/XvbZT//B96Vs8oTA8Q4A0AfHbrxP9zw==}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.52.4':
|
||||
resolution: {integrity: sha512-1ox+GqgRWqaB1RnyZXL8PD6E5f7YyRUJYnCqKpNzxzP0TkaUh112NDrR9Tt+C8rJ4x5G9Mk8PQR3o7Ku2RKqKA==}
|
||||
cpu: [arm64]
|
||||
os: [openharmony]
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.52.4':
|
||||
resolution: {integrity: sha512-8GKr640PdFNXwzIE0IrkMWUNUomILLkfeHjXBi/nUvFlpZP+FA8BKGKpacjW6OUUHaNI6sUURxR2U2g78FOHWQ==}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.52.4':
|
||||
resolution: {integrity: sha512-AIy/jdJ7WtJ/F6EcfOb2GjR9UweO0n43jNObQMb6oGxkYTfLcnN7vYYpG+CN3lLxrQkzWnMOoNSHTW54pgbVxw==}
|
||||
cpu: [ia32]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.52.4':
|
||||
resolution: {integrity: sha512-UF9KfsH9yEam0UjTwAgdK0anlQ7c8/pWPU2yVjyWcF1I1thABt6WXE47cI71pGiZ8wGvxohBoLnxM04L/wj8mQ==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.52.4':
|
||||
resolution: {integrity: sha512-bf9PtUa0u8IXDVxzRToFQKsNCRz9qLYfR/MpECxl4mRoWYjAeFjgxj1XdZr2M/GNVpT05p+LgQOHopYDlUu6/w==}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@sinclair/typebox@0.27.8':
|
||||
resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==}
|
||||
|
||||
@@ -357,9 +470,6 @@ packages:
|
||||
'@types/babel__traverse@7.28.0':
|
||||
resolution: {integrity: sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q==}
|
||||
|
||||
'@types/estree@0.0.39':
|
||||
resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==}
|
||||
|
||||
'@types/estree@1.0.8':
|
||||
resolution: {integrity: sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==}
|
||||
|
||||
@@ -1096,10 +1206,11 @@ packages:
|
||||
rollup-plugin-peer-deps-external@2.2.4:
|
||||
resolution: {integrity: sha512-AWdukIM1+k5JDdAqV/Cxd+nejvno2FVLVeZ74NKggm3Q5s9cbbcOgUPGdbxPi4BXu7xGaZ8HG12F+thImYu/0g==}
|
||||
peerDependencies:
|
||||
rollup: '*'
|
||||
rollup: '>=2.79.2'
|
||||
|
||||
rollup@0.63.5:
|
||||
resolution: {integrity: sha512-dFf8LpUNzIj3oE0vCvobX6rqOzHzLBoblyFp+3znPbjiSmSvOoK2kMKx+Fv9jYduG1rvcCfCveSgEaQHjWRF6g==}
|
||||
rollup@4.52.4:
|
||||
resolution: {integrity: sha512-CLEVl+MnPAiKh5pl4dEWSyMTpuflgNQiLGhMv8ezD5W/qP8AKvmYpCOKRRNOh7oRKnauBZ4SyeYkMS+1VSyKwQ==}
|
||||
engines: {node: '>=18.0.0', npm: '>=8.0.0'}
|
||||
hasBin: true
|
||||
|
||||
semver@6.3.1:
|
||||
@@ -1689,23 +1800,89 @@ snapshots:
|
||||
'@jridgewell/resolve-uri': 3.1.2
|
||||
'@jridgewell/sourcemap-codec': 1.5.5
|
||||
|
||||
'@rollup/plugin-node-resolve@16.0.1(rollup@0.63.5)':
|
||||
'@rollup/plugin-node-resolve@16.0.2(rollup@4.52.4)':
|
||||
dependencies:
|
||||
'@rollup/pluginutils': 5.2.0(rollup@0.63.5)
|
||||
'@rollup/pluginutils': 5.3.0(rollup@4.52.4)
|
||||
'@types/resolve': 1.20.2
|
||||
deepmerge: 4.3.1
|
||||
is-module: 1.0.0
|
||||
resolve: 1.22.10
|
||||
optionalDependencies:
|
||||
rollup: 0.63.5
|
||||
rollup: 4.52.4
|
||||
|
||||
'@rollup/pluginutils@5.2.0(rollup@0.63.5)':
|
||||
'@rollup/pluginutils@5.3.0(rollup@4.52.4)':
|
||||
dependencies:
|
||||
'@types/estree': 1.0.8
|
||||
estree-walker: 2.0.2
|
||||
picomatch: 4.0.3
|
||||
optionalDependencies:
|
||||
rollup: 0.63.5
|
||||
rollup: 4.52.4
|
||||
|
||||
'@rollup/rollup-android-arm-eabi@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-android-arm64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-arm64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-darwin-x64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-arm64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-freebsd-x64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-gnueabihf@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm-musleabihf@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-arm64-musl@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-loong64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-ppc64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-riscv64-musl@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-s390x-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-linux-x64-musl@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-openharmony-arm64@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-arm64-msvc@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-ia32-msvc@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-gnu@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@rollup/rollup-win32-x64-msvc@4.52.4':
|
||||
optional: true
|
||||
|
||||
'@sinclair/typebox@0.27.8': {}
|
||||
|
||||
@@ -1738,8 +1915,6 @@ snapshots:
|
||||
dependencies:
|
||||
'@babel/types': 7.28.2
|
||||
|
||||
'@types/estree@0.0.39': {}
|
||||
|
||||
'@types/estree@1.0.8': {}
|
||||
|
||||
'@types/graceful-fs@4.1.9':
|
||||
@@ -1769,7 +1944,7 @@ snapshots:
|
||||
|
||||
'@types/rollup-plugin-peer-deps-external@2.2.5':
|
||||
dependencies:
|
||||
rollup: 0.63.5
|
||||
rollup: 4.52.4
|
||||
|
||||
'@types/stack-utils@2.0.3': {}
|
||||
|
||||
@@ -2614,14 +2789,37 @@ snapshots:
|
||||
path-parse: 1.0.7
|
||||
supports-preserve-symlinks-flag: 1.0.0
|
||||
|
||||
rollup-plugin-peer-deps-external@2.2.4(rollup@0.63.5):
|
||||
rollup-plugin-peer-deps-external@2.2.4(rollup@4.52.4):
|
||||
dependencies:
|
||||
rollup: 0.63.5
|
||||
rollup: 4.52.4
|
||||
|
||||
rollup@0.63.5:
|
||||
rollup@4.52.4:
|
||||
dependencies:
|
||||
'@types/estree': 0.0.39
|
||||
'@types/node': 22.15.17
|
||||
'@types/estree': 1.0.8
|
||||
optionalDependencies:
|
||||
'@rollup/rollup-android-arm-eabi': 4.52.4
|
||||
'@rollup/rollup-android-arm64': 4.52.4
|
||||
'@rollup/rollup-darwin-arm64': 4.52.4
|
||||
'@rollup/rollup-darwin-x64': 4.52.4
|
||||
'@rollup/rollup-freebsd-arm64': 4.52.4
|
||||
'@rollup/rollup-freebsd-x64': 4.52.4
|
||||
'@rollup/rollup-linux-arm-gnueabihf': 4.52.4
|
||||
'@rollup/rollup-linux-arm-musleabihf': 4.52.4
|
||||
'@rollup/rollup-linux-arm64-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-arm64-musl': 4.52.4
|
||||
'@rollup/rollup-linux-loong64-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-ppc64-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-riscv64-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-riscv64-musl': 4.52.4
|
||||
'@rollup/rollup-linux-s390x-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-x64-gnu': 4.52.4
|
||||
'@rollup/rollup-linux-x64-musl': 4.52.4
|
||||
'@rollup/rollup-openharmony-arm64': 4.52.4
|
||||
'@rollup/rollup-win32-arm64-msvc': 4.52.4
|
||||
'@rollup/rollup-win32-ia32-msvc': 4.52.4
|
||||
'@rollup/rollup-win32-x64-gnu': 4.52.4
|
||||
'@rollup/rollup-win32-x64-msvc': 4.52.4
|
||||
fsevents: 2.3.3
|
||||
|
||||
semver@6.3.1: {}
|
||||
|
||||
|
||||
@@ -1609,6 +1609,10 @@ export interface VerifyTicketParams {
|
||||
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
/**
|
||||
Summary: Get public keys for JWT verification in JWK Set format
|
||||
|
||||
@@ -18,6 +18,11 @@ import {
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
|
||||
/**
|
||||
* Execute a request to a serverless function
|
||||
* The response body will be automatically parsed based on the content type into the following types:
|
||||
@@ -27,7 +32,8 @@ export interface Client {
|
||||
*
|
||||
* @param path - The path to the serverless function
|
||||
* @param options - Additional fetch options to apply to the request
|
||||
* @returns Promise with the function response and metadata. */
|
||||
* @returns Promise with the function response and metadata.
|
||||
*/
|
||||
fetch<T = unknown>(
|
||||
path: string,
|
||||
options?: RequestInit,
|
||||
@@ -69,7 +75,12 @@ export const createAPIClient = (
|
||||
baseURL: string,
|
||||
chainFunctions: ChainFunction[] = [],
|
||||
): Client => {
|
||||
const enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
let enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
|
||||
const pushChainFunction = (chainFunction: ChainFunction) => {
|
||||
chainFunctions.push(chainFunction);
|
||||
enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
};
|
||||
|
||||
/**
|
||||
* Executes a request to a serverless function and processes the response
|
||||
@@ -148,5 +159,6 @@ export const createAPIClient = (
|
||||
baseURL,
|
||||
fetch,
|
||||
post,
|
||||
pushChainFunction,
|
||||
} as Client;
|
||||
};
|
||||
|
||||
@@ -91,6 +91,11 @@ export interface Client {
|
||||
* URL for the GraphQL endpoint.
|
||||
*/
|
||||
url: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,7 +113,12 @@ export const createAPIClient = (
|
||||
url: string,
|
||||
chainFunctions: ChainFunction[] = [],
|
||||
): Client => {
|
||||
const enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
let enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
|
||||
const pushChainFunction = (chainFunction: ChainFunction) => {
|
||||
chainFunctions.push(chainFunction);
|
||||
enhancedFetch = createEnhancedFetch(chainFunctions);
|
||||
};
|
||||
|
||||
const executeOperation = async <
|
||||
TResponseData = unknown,
|
||||
@@ -183,5 +193,6 @@ export const createAPIClient = (
|
||||
return {
|
||||
request,
|
||||
url,
|
||||
pushChainFunction,
|
||||
} as Client;
|
||||
};
|
||||
|
||||
@@ -461,6 +461,10 @@ export interface GetFileMetadataHeadersParams {
|
||||
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
/**
|
||||
Summary: Upload files
|
||||
|
||||
600
pnpm-lock.yaml
generated
600
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
@@ -67,14 +67,13 @@ func logFlags(ctx context.Context, logger *slog.Logger, cmd *cli.Command) {
|
||||
flags := make([]any, 0, len(cmd.Root().Flags)+len(cmd.Flags))
|
||||
for _, flag := range cmd.Root().Flags {
|
||||
name := flag.Names()[0]
|
||||
value := cmd.Generic(name)
|
||||
value := cmd.Value(name)
|
||||
|
||||
var logValue any = value
|
||||
if isSecret(name) {
|
||||
logValue = "********"
|
||||
value = "********"
|
||||
}
|
||||
|
||||
flags = append(flags, slog.Any(name, logValue))
|
||||
flags = append(flags, slog.Any(name, value))
|
||||
|
||||
processed[name] = struct{}{}
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/pflag"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func addBoolFlag(
|
||||
flags *pflag.FlagSet,
|
||||
name string,
|
||||
defaultValue bool, //nolint:unparam
|
||||
help string,
|
||||
) {
|
||||
flags.Bool(name, defaultValue, help)
|
||||
|
||||
if err := viper.BindPFlag(name, flags.Lookup(name)); err != nil {
|
||||
cobra.CheckErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func addStringFlag(flags *pflag.FlagSet, name string, defaultValue string, help string) {
|
||||
flags.String(name, defaultValue, help)
|
||||
|
||||
if err := viper.BindPFlag(name, flags.Lookup(name)); err != nil {
|
||||
cobra.CheckErr(err)
|
||||
}
|
||||
}
|
||||
|
||||
func addStringArrayFlag(flags *pflag.FlagSet, name string, defaultValue []string, help string) {
|
||||
flags.StringArray(name, defaultValue, help)
|
||||
|
||||
if err := viper.BindPFlag(name, flags.Lookup(name)); err != nil {
|
||||
cobra.CheckErr(err)
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,103 @@
|
||||
package cmd
|
||||
|
||||
import "github.com/sirupsen/logrus"
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
func getLogger() *logrus.Logger {
|
||||
logger := logrus.New()
|
||||
logger.SetFormatter(&logrus.TextFormatter{ //nolint:exhaustruct
|
||||
FullTimestamp: true,
|
||||
})
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/lmittmann/tint"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
return logger
|
||||
func getLogger(debug bool, formatTEXT bool) *slog.Logger {
|
||||
var (
|
||||
logLevel slog.Level
|
||||
addSource bool
|
||||
)
|
||||
|
||||
if debug {
|
||||
logLevel = slog.LevelDebug
|
||||
addSource = true
|
||||
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
logLevel = slog.LevelInfo
|
||||
addSource = false
|
||||
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
}
|
||||
|
||||
var handler slog.Handler
|
||||
if formatTEXT {
|
||||
handler = tint.NewHandler(os.Stdout, &tint.Options{
|
||||
AddSource: addSource,
|
||||
Level: logLevel,
|
||||
TimeFormat: time.StampMilli,
|
||||
NoColor: false,
|
||||
ReplaceAttr: nil,
|
||||
})
|
||||
} else {
|
||||
handler = slog.NewJSONHandler(os.Stdout, &slog.HandlerOptions{
|
||||
AddSource: addSource,
|
||||
Level: logLevel,
|
||||
ReplaceAttr: nil,
|
||||
})
|
||||
}
|
||||
|
||||
return slog.New(handler)
|
||||
}
|
||||
|
||||
func isSecret(name string) bool {
|
||||
return strings.Contains(name, "pass") ||
|
||||
strings.Contains(name, "token") ||
|
||||
strings.Contains(name, "secret") ||
|
||||
strings.Contains(name, "key") ||
|
||||
strings.Contains(name, "license") ||
|
||||
strings.Contains(name, "postgres") ||
|
||||
strings.Contains(name, "client-id") ||
|
||||
strings.Contains(name, "client-secret")
|
||||
}
|
||||
|
||||
func logFlags(ctx context.Context, logger *slog.Logger, cmd *cli.Command) {
|
||||
processed := make(map[string]struct{})
|
||||
|
||||
flags := make([]any, 0, len(cmd.Root().Flags)+len(cmd.Flags))
|
||||
for _, flag := range cmd.Root().Flags {
|
||||
name := flag.Names()[0]
|
||||
value := cmd.Value(name)
|
||||
|
||||
if isSecret(name) {
|
||||
value = "********"
|
||||
}
|
||||
|
||||
flags = append(flags, slog.Any(name, value))
|
||||
|
||||
processed[name] = struct{}{}
|
||||
}
|
||||
|
||||
for _, flag := range cmd.Flags {
|
||||
name := flag.Names()[0]
|
||||
if _, ok := processed[name]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
value := cmd.Generic(name)
|
||||
|
||||
var logValue any = value
|
||||
if isSecret(name) {
|
||||
logValue = "********"
|
||||
}
|
||||
|
||||
flags = append(flags, slog.Any(name, logValue))
|
||||
}
|
||||
|
||||
logger.LogAttrs(
|
||||
ctx,
|
||||
slog.LevelInfo,
|
||||
"starting program",
|
||||
slog.Group("flags", flags...),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,61 +0,0 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
name = "storage"
|
||||
debugFlag = "debug"
|
||||
configFlag = "config"
|
||||
)
|
||||
|
||||
var (
|
||||
cfgFile *string
|
||||
rootCmd = &cobra.Command{ //nolint:exhaustruct
|
||||
Use: name,
|
||||
Aliases: []string{},
|
||||
SuggestFor: []string{},
|
||||
Short: "Storage utilizes hasura and s3 to build a cloud storage",
|
||||
Version: controller.Version(),
|
||||
}
|
||||
)
|
||||
|
||||
// Execute executes the root command.
|
||||
func Execute() error {
|
||||
return rootCmd.Execute() //nolint: wrapcheck
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
cfgFile = rootCmd.PersistentFlags().StringP(configFlag, "c", "", "use this configuration file")
|
||||
addBoolFlag(rootCmd.PersistentFlags(), debugFlag, false, "enable debug messages")
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
viper.AutomaticEnv()
|
||||
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
|
||||
|
||||
if *cfgFile != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(*cfgFile)
|
||||
} else {
|
||||
// Find home directory.
|
||||
viper.SetConfigName(name)
|
||||
viper.AddConfigPath("$HOME")
|
||||
viper.AddConfigPath(".")
|
||||
}
|
||||
|
||||
if err := viper.ReadInConfig(); err != nil {
|
||||
fmt.Fprintf(os.Stderr, "problem reading %s: %s\n", viper.ConfigFileUsed(), err)
|
||||
} else {
|
||||
fmt.Fprintln(os.Stderr, "using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
||||
@@ -3,8 +3,8 @@ package cmd
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
@@ -24,33 +24,33 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/migrations"
|
||||
"github.com/nhost/nhost/services/storage/storage"
|
||||
ginmiddleware "github.com/oapi-codegen/gin-middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
publicURLFlag = "public-url"
|
||||
apiRootPrefixFlag = "api-root-prefix"
|
||||
bindFlag = "bind"
|
||||
hasuraEndpointFlag = "hasura-endpoint"
|
||||
hasuraMetadataFlag = "hasura-metadata"
|
||||
hasuraAdminSecretFlag = "hasura-graphql-admin-secret" //nolint: gosec
|
||||
s3EndpointFlag = "s3-endpoint"
|
||||
s3AccessKeyFlag = "s3-access-key"
|
||||
s3SecretKeyFlag = "s3-secret-key" //nolint: gosec
|
||||
s3RegionFlag = "s3-region"
|
||||
s3BucketFlag = "s3-bucket"
|
||||
s3RootFolderFlag = "s3-root-folder"
|
||||
s3DisableHTTPS = "s3-disable-http"
|
||||
postgresMigrationsFlag = "postgres-migrations"
|
||||
postgresMigrationsSourceFlag = "postgres-migrations-source"
|
||||
fastlyServiceFlag = "fastly-service"
|
||||
fastlyKeyFlag = "fastly-key"
|
||||
corsAllowOriginsFlag = "cors-allow-origins"
|
||||
corsAllowCredentialsFlag = "cors-allow-credentials" //nolint: gosec
|
||||
clamavServerFlag = "clamav-server"
|
||||
hasuraDBNameFlag = "hasura-db-name"
|
||||
flagDebug = "debug"
|
||||
flagLogFormatTEXT = "log-format-text"
|
||||
flagPublicURL = "public-url"
|
||||
flagAPIRootPrefix = "api-root-prefix"
|
||||
flagBind = "bind"
|
||||
flagHasuraEndpoint = "hasura-endpoint"
|
||||
flagHasuraMetadata = "hasura-metadata"
|
||||
flagHasuraAdminSecret = "hasura-graphql-admin-secret" //nolint: gosec
|
||||
flagS3Endpoint = "s3-endpoint"
|
||||
flagS3AccessKey = "s3-access-key"
|
||||
flagS3SecretKey = "s3-secret-key" //nolint: gosec
|
||||
flagS3Region = "s3-region"
|
||||
flagS3Bucket = "s3-bucket"
|
||||
flagS3RootFolder = "s3-root-folder"
|
||||
flagS3DisableHTTPS = "s3-disable-https"
|
||||
flagPostgresMigrations = "postgres-migrations"
|
||||
flagPostgresMigrationsSource = "postgres-migrations-source"
|
||||
flagFastlyService = "fastly-service"
|
||||
flagFastlyKey = "fastly-key"
|
||||
flagCorsAllowOrigins = "cors-allow-origins"
|
||||
flagCorsAllowCredentials = "cors-allow-credentials" //nolint: gosec
|
||||
flagClamavServer = "clamav-server"
|
||||
flagHasuraDBName = "hasura-db-name"
|
||||
)
|
||||
|
||||
func getCorsMiddleware(
|
||||
@@ -81,10 +81,13 @@ func getGin( //nolint:funlen
|
||||
metadataStorage controller.MetadataStorage,
|
||||
contentStorage controller.ContentStorage,
|
||||
imageTransformer *image.Transformer,
|
||||
logger *logrus.Logger,
|
||||
logger *slog.Logger,
|
||||
debug bool,
|
||||
corsAllowOrigins []string,
|
||||
corsAllowCredentials bool,
|
||||
fastlyService string,
|
||||
fastlyKey string,
|
||||
clamavServer string,
|
||||
) (*http.Server, error) {
|
||||
router := gin.New()
|
||||
|
||||
@@ -113,18 +116,17 @@ func getGin( //nolint:funlen
|
||||
gin.Recovery(),
|
||||
}
|
||||
|
||||
fastlyService := viper.GetString(fastlyServiceFlag)
|
||||
if fastlyService != "" {
|
||||
logger.Info("enabling fastly middleware")
|
||||
logger.InfoContext(context.Background(), "enabling fastly middleware")
|
||||
handlers = append(
|
||||
handlers,
|
||||
fastly.New(fastlyService, viper.GetString(fastlyKeyFlag), logger),
|
||||
fastly.New(fastlyService, fastlyKey, logger),
|
||||
)
|
||||
}
|
||||
|
||||
router.Use(handlers...)
|
||||
|
||||
av, err := getAv(viper.GetString(clamavServerFlag))
|
||||
av, err := getAv(clamavServer)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("problem trying to get av: %w", err)
|
||||
}
|
||||
@@ -177,15 +179,19 @@ func getContentStorage(
|
||||
ctx context.Context,
|
||||
s3Endpoint, region, s3AccessKey, s3SecretKey, bucket, rootFolder string,
|
||||
disableHTTPS bool,
|
||||
logger *logrus.Logger,
|
||||
logger *slog.Logger,
|
||||
) *storage.S3 {
|
||||
var (
|
||||
cfg aws.Config
|
||||
err error
|
||||
)
|
||||
|
||||
if region == "" {
|
||||
region = "no-region"
|
||||
}
|
||||
|
||||
if s3AccessKey != "" && s3SecretKey != "" {
|
||||
logger.Info("Using static aws credentials")
|
||||
logger.InfoContext(ctx, "Using static aws credentials")
|
||||
|
||||
cfg, err = config.LoadDefaultConfig(
|
||||
ctx,
|
||||
@@ -195,7 +201,7 @@ func getContentStorage(
|
||||
),
|
||||
)
|
||||
} else {
|
||||
logger.Info("Using default configuration for aws credentials")
|
||||
logger.InfoContext(ctx, "Using default configuration for aws credentials")
|
||||
|
||||
cfg, err = config.LoadDefaultConfig(ctx, config.WithRegion(region))
|
||||
}
|
||||
@@ -217,211 +223,273 @@ func getContentStorage(
|
||||
return st
|
||||
}
|
||||
|
||||
func applymigrations(
|
||||
func applyMigrations(
|
||||
ctx context.Context,
|
||||
postgresMigrations bool,
|
||||
postgresSource string,
|
||||
hasuraMetadata bool,
|
||||
hasuraEndpoint string,
|
||||
hasuraSecret string,
|
||||
hasuraDBName string,
|
||||
logger *logrus.Logger,
|
||||
) {
|
||||
logger *slog.Logger,
|
||||
) error {
|
||||
if postgresMigrations {
|
||||
if postgresSource == "" {
|
||||
logger.Error("you need to specify " + postgresMigrationsSourceFlag)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
logger.Info("applying postgres migrations")
|
||||
logger.InfoContext(ctx, "applying postgres migrations")
|
||||
|
||||
if err := migrations.ApplyPostgresMigration(postgresSource); err != nil {
|
||||
logger.Errorf("problem applying postgres migrations: %s", err.Error())
|
||||
os.Exit(1)
|
||||
return fmt.Errorf("problem applying postgres migrations: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
if hasuraMetadata {
|
||||
logger.Info("applying hasura metadata")
|
||||
logger.InfoContext(ctx, "applying hasura metadata")
|
||||
|
||||
if err := migrations.ApplyHasuraMetadata(hasuraEndpoint, hasuraSecret, hasuraDBName); err != nil {
|
||||
logger.Errorf("problem applying hasura metadata: %s", err.Error())
|
||||
os.Exit(1)
|
||||
if err := migrations.ApplyHasuraMetadata(
|
||||
ctx, hasuraEndpoint, hasuraSecret, hasuraDBName,
|
||||
); err != nil {
|
||||
return fmt.Errorf("problem applying hasura metadata: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() { //nolint:funlen
|
||||
rootCmd.AddCommand(serveCmd)
|
||||
|
||||
{
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
publicURLFlag,
|
||||
"http://localhost:8000",
|
||||
"public URL of the service",
|
||||
)
|
||||
addStringFlag(serveCmd.Flags(), apiRootPrefixFlag, "/v1", "API root prefix")
|
||||
addStringFlag(serveCmd.Flags(), bindFlag, ":8000", "bind the service to this address")
|
||||
}
|
||||
|
||||
{
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
hasuraEndpointFlag,
|
||||
"",
|
||||
"Use this endpoint when connecting using graphql as metadata storage",
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
addStringFlag(serveCmd.Flags(), s3EndpointFlag, "", "S3 Endpoint")
|
||||
addStringFlag(serveCmd.Flags(), s3AccessKeyFlag, "", "S3 Access key")
|
||||
addStringFlag(serveCmd.Flags(), s3SecretKeyFlag, "", "S3 Secret key")
|
||||
addStringFlag(serveCmd.Flags(), s3RegionFlag, "no-region", "S3 region")
|
||||
addStringFlag(serveCmd.Flags(), s3BucketFlag, "", "S3 bucket")
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
s3RootFolderFlag,
|
||||
"",
|
||||
"All buckets will be created inside this root",
|
||||
)
|
||||
}
|
||||
|
||||
{
|
||||
addBoolFlag(serveCmd.Flags(), postgresMigrationsFlag, false, "Apply Postgres migrations")
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
postgresMigrationsSourceFlag,
|
||||
"",
|
||||
"postgres connection, i.e. postgres://user@pass:localhost:5432/mydb",
|
||||
)
|
||||
addStringFlag(serveCmd.Flags(), hasuraDBNameFlag, "default", "Hasura database name")
|
||||
}
|
||||
|
||||
{
|
||||
addBoolFlag(serveCmd.Flags(), hasuraMetadataFlag, false, "Apply Hasura's metadata")
|
||||
addStringFlag(serveCmd.Flags(), hasuraAdminSecretFlag, "", "")
|
||||
}
|
||||
|
||||
{
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
fastlyServiceFlag,
|
||||
"",
|
||||
"Enable Fastly middleware and enable automated purges",
|
||||
)
|
||||
addStringFlag(serveCmd.Flags(), fastlyKeyFlag, "", "Fastly CDN Key to authenticate purges")
|
||||
}
|
||||
|
||||
{
|
||||
addStringArrayFlag(
|
||||
serveCmd.Flags(),
|
||||
corsAllowOriginsFlag,
|
||||
[]string{"*"},
|
||||
"CORS allow origins",
|
||||
)
|
||||
addBoolFlag(serveCmd.Flags(), corsAllowCredentialsFlag, false, "CORS allow credentials")
|
||||
addStringFlag(
|
||||
serveCmd.Flags(),
|
||||
clamavServerFlag,
|
||||
"",
|
||||
"If set, use ClamAV to scan files. Example: tcp://clamavd:3310",
|
||||
)
|
||||
func CommandServe() *cli.Command { //nolint:funlen
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "serve",
|
||||
Usage: "Start storage server",
|
||||
Flags: []cli.Flag{
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagDebug,
|
||||
Usage: "enable debug messages",
|
||||
Category: "general",
|
||||
Sources: cli.EnvVars("DEBUG"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint: exhaustruct
|
||||
Name: flagLogFormatTEXT,
|
||||
Usage: "format logs in plain text",
|
||||
Category: "general",
|
||||
Value: false,
|
||||
Sources: cli.EnvVars("LOG_FORMAT_TEXT"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagPublicURL,
|
||||
Usage: "public URL of the service",
|
||||
Value: "http://localhost:8000",
|
||||
Category: "server",
|
||||
Sources: cli.EnvVars("PUBLIC_URL"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagAPIRootPrefix,
|
||||
Usage: "API root prefix",
|
||||
Value: "/v1",
|
||||
Category: "server",
|
||||
Sources: cli.EnvVars("API_ROOT_PREFIX"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagBind,
|
||||
Usage: "bind the service to this address",
|
||||
Value: ":8000",
|
||||
Category: "server",
|
||||
Sources: cli.EnvVars("BIND"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagHasuraEndpoint,
|
||||
Usage: "Use this endpoint when connecting using graphql as metadata storage",
|
||||
Category: "hasura",
|
||||
Sources: cli.EnvVars("HASURA_ENDPOINT"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagHasuraMetadata,
|
||||
Usage: "Apply Hasura's metadata",
|
||||
Category: "hasura",
|
||||
Sources: cli.EnvVars("HASURA_METADATA"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagHasuraAdminSecret,
|
||||
Usage: "Hasura admin secret",
|
||||
Category: "hasura",
|
||||
Sources: cli.EnvVars(
|
||||
"HASURA_GRAPHQL_ADMIN_SECRET",
|
||||
"HASURA_GRAPHQL_ADMIN_SECRET",
|
||||
),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagHasuraDBName,
|
||||
Usage: "Hasura database name",
|
||||
Value: "default",
|
||||
Category: "hasura",
|
||||
Sources: cli.EnvVars("HASURA_DB_NAME"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3Endpoint,
|
||||
Usage: "S3 Endpoint",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_ENDPOINT"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3AccessKey,
|
||||
Usage: "S3 Access key",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_ACCESS_KEY"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3SecretKey,
|
||||
Usage: "S3 Secret key",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_SECRET_KEY"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3Region,
|
||||
Usage: "S3 region",
|
||||
Value: "no-region",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_REGION"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3Bucket,
|
||||
Usage: "S3 bucket",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_BUCKET"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagS3RootFolder,
|
||||
Usage: "All buckets will be created inside this root",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_ROOT_FOLDER"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagS3DisableHTTPS,
|
||||
Usage: "Disable HTTPS for S3",
|
||||
Category: "s3",
|
||||
Sources: cli.EnvVars("S3_DISABLE_HTTPS"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagPostgresMigrations,
|
||||
Usage: "Apply Postgres migrations",
|
||||
Category: "postgres",
|
||||
Sources: cli.EnvVars("POSTGRES_MIGRATIONS"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagPostgresMigrationsSource,
|
||||
Usage: "postgres connection, i.e. postgres://user@pass:localhost:5432/mydb",
|
||||
Category: "postgres",
|
||||
Required: true,
|
||||
Sources: cli.EnvVars("POSTGRES_MIGRATIONS_SOURCE"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagFastlyService,
|
||||
Usage: "Enable Fastly middleware and enable automated purges",
|
||||
Category: "cdn",
|
||||
Sources: cli.EnvVars("FASTLY_SERVICE"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagFastlyKey,
|
||||
Usage: "Fastly CDN Key to authenticate purges",
|
||||
Category: "cdn",
|
||||
Sources: cli.EnvVars("FASTLY_KEY"),
|
||||
},
|
||||
&cli.StringSliceFlag{ //nolint:exhaustruct
|
||||
Name: flagCorsAllowOrigins,
|
||||
Usage: "CORS allow origins",
|
||||
Value: []string{"*"},
|
||||
Category: "cors",
|
||||
Sources: cli.EnvVars("CORS_ALLOW_ORIGINS"),
|
||||
},
|
||||
&cli.BoolFlag{ //nolint:exhaustruct
|
||||
Name: flagCorsAllowCredentials,
|
||||
Usage: "CORS allow credentials",
|
||||
Category: "cors",
|
||||
Sources: cli.EnvVars("CORS_ALLOW_CREDENTIALS"),
|
||||
},
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagClamavServer,
|
||||
Usage: "If set, use ClamAV to scan files. Example: tcp://clamavd:3310",
|
||||
Category: "antivirus",
|
||||
Sources: cli.EnvVars("CLAMAV_SERVER"),
|
||||
},
|
||||
},
|
||||
Action: serve,
|
||||
}
|
||||
}
|
||||
|
||||
var serveCmd = &cobra.Command{ //nolint:exhaustruct
|
||||
Use: "serve",
|
||||
Short: "Starts storage server",
|
||||
Run: func(cmd *cobra.Command, _ []string) {
|
||||
logger := getLogger()
|
||||
func serve(ctx context.Context, cmd *cli.Command) error { //nolint:funlen
|
||||
logger := getLogger(cmd.Bool(flagDebug), cmd.Bool(flagLogFormatTEXT))
|
||||
logger.InfoContext(ctx, cmd.Root().Name+" v"+cmd.Root().Version)
|
||||
logFlags(ctx, logger, cmd)
|
||||
|
||||
logger.Info("storage version ", controller.Version())
|
||||
imageTransformer := image.NewTransformer()
|
||||
defer imageTransformer.Shutdown()
|
||||
|
||||
ctx, cancel := context.WithCancel(cmd.Context())
|
||||
servCtx, cancel := context.WithCancel(ctx)
|
||||
defer cancel()
|
||||
|
||||
contentStorage := getContentStorage(
|
||||
servCtx,
|
||||
cmd.String(flagS3Endpoint),
|
||||
cmd.String(flagS3Region),
|
||||
cmd.String(flagS3AccessKey),
|
||||
cmd.String(flagS3SecretKey),
|
||||
cmd.String(flagS3Bucket),
|
||||
cmd.String(flagS3RootFolder),
|
||||
cmd.Bool(flagS3DisableHTTPS),
|
||||
logger,
|
||||
)
|
||||
|
||||
if err := applyMigrations(
|
||||
ctx,
|
||||
cmd.Bool(flagPostgresMigrations),
|
||||
cmd.String(flagPostgresMigrationsSource),
|
||||
cmd.Bool(flagHasuraMetadata),
|
||||
cmd.String(flagHasuraEndpoint),
|
||||
cmd.String(flagHasuraAdminSecret),
|
||||
cmd.String(flagHasuraDBName),
|
||||
logger,
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
metadataStorage := getMetadataStorage(
|
||||
cmd.String(flagHasuraEndpoint) + "/graphql",
|
||||
)
|
||||
|
||||
server, err := getGin( //nolint: contextcheck
|
||||
cmd.String(flagBind),
|
||||
cmd.String(flagPublicURL),
|
||||
cmd.String(flagAPIRootPrefix),
|
||||
cmd.String(flagHasuraAdminSecret),
|
||||
metadataStorage,
|
||||
contentStorage,
|
||||
imageTransformer,
|
||||
logger,
|
||||
cmd.Bool(flagDebug),
|
||||
cmd.StringSlice(flagCorsAllowOrigins),
|
||||
cmd.Bool(flagCorsAllowCredentials),
|
||||
cmd.String(flagFastlyService),
|
||||
cmd.String(flagFastlyKey),
|
||||
cmd.String(flagClamavServer),
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go func() {
|
||||
defer cancel()
|
||||
|
||||
if viper.GetBool(debugFlag) {
|
||||
logger.SetLevel(logrus.DebugLevel)
|
||||
gin.SetMode(gin.DebugMode)
|
||||
} else {
|
||||
logger.SetLevel(logrus.InfoLevel)
|
||||
gin.SetMode(gin.ReleaseMode)
|
||||
logger.InfoContext(servCtx, "starting server")
|
||||
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
logger.ErrorContext(servCtx, "server failed", slog.String("error", err.Error()))
|
||||
}
|
||||
}()
|
||||
|
||||
imageTransformer := image.NewTransformer()
|
||||
defer imageTransformer.Shutdown()
|
||||
<-servCtx.Done()
|
||||
|
||||
logger.WithFields(
|
||||
logrus.Fields{
|
||||
debugFlag: viper.GetBool(debugFlag),
|
||||
bindFlag: viper.GetString(bindFlag),
|
||||
hasuraEndpointFlag: viper.GetString(hasuraEndpointFlag),
|
||||
postgresMigrationsFlag: viper.GetBool(postgresMigrationsFlag),
|
||||
hasuraMetadataFlag: viper.GetBool(hasuraMetadataFlag),
|
||||
s3EndpointFlag: viper.GetString(s3EndpointFlag),
|
||||
s3RegionFlag: viper.GetString(s3RegionFlag),
|
||||
s3BucketFlag: viper.GetString(s3BucketFlag),
|
||||
s3RootFolderFlag: viper.GetString(s3RootFolderFlag),
|
||||
clamavServerFlag: viper.GetString(clamavServerFlag),
|
||||
hasuraDBNameFlag: viper.GetString(hasuraDBNameFlag),
|
||||
},
|
||||
).Debug("parameters")
|
||||
logger.InfoContext(ctx, "shutting down server")
|
||||
|
||||
contentStorage := getContentStorage(
|
||||
ctx,
|
||||
viper.GetString(s3EndpointFlag),
|
||||
viper.GetString(s3RegionFlag),
|
||||
viper.GetString(s3AccessKeyFlag),
|
||||
viper.GetString(s3SecretKeyFlag),
|
||||
viper.GetString(s3BucketFlag),
|
||||
viper.GetString(s3RootFolderFlag),
|
||||
viper.GetBool(s3DisableHTTPS),
|
||||
logger,
|
||||
)
|
||||
if err := server.Shutdown(ctx); err != nil {
|
||||
logger.ErrorContext(ctx, "problem shutting down server", slog.String("error", err.Error()))
|
||||
}
|
||||
|
||||
applymigrations(
|
||||
viper.GetBool(postgresMigrationsFlag),
|
||||
viper.GetString(postgresMigrationsSourceFlag),
|
||||
viper.GetBool(hasuraMetadataFlag),
|
||||
viper.GetString(hasuraEndpointFlag),
|
||||
viper.GetString(hasuraAdminSecretFlag),
|
||||
viper.GetString(hasuraDBNameFlag),
|
||||
logger,
|
||||
)
|
||||
|
||||
metadataStorage := getMetadataStorage(
|
||||
viper.GetString(hasuraEndpointFlag) + "/graphql",
|
||||
)
|
||||
server, err := getGin(
|
||||
viper.GetString(bindFlag),
|
||||
viper.GetString(publicURLFlag),
|
||||
viper.GetString(apiRootPrefixFlag),
|
||||
viper.GetString(hasuraAdminSecretFlag),
|
||||
metadataStorage,
|
||||
contentStorage,
|
||||
imageTransformer,
|
||||
logger,
|
||||
viper.GetBool(debugFlag),
|
||||
viper.GetStringSlice(corsAllowOriginsFlag),
|
||||
viper.GetBool(corsAllowCredentialsFlag),
|
||||
)
|
||||
cobra.CheckErr(err)
|
||||
|
||||
go func() {
|
||||
defer cancel()
|
||||
logger.Info("starting server")
|
||||
if err := server.ListenAndServe(); err != nil {
|
||||
logger.Error("server failed", logrus.Fields{
|
||||
"error": err,
|
||||
})
|
||||
}
|
||||
}()
|
||||
|
||||
<-ctx.Done()
|
||||
|
||||
logger.Info("shutting down server")
|
||||
err = server.Shutdown(ctx)
|
||||
cobra.CheckErr(err)
|
||||
},
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4,12 +4,12 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/image"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type FileSummary struct {
|
||||
@@ -91,7 +91,7 @@ type Controller struct {
|
||||
contentStorage ContentStorage
|
||||
imageTransformer *image.Transformer
|
||||
av Antivirus
|
||||
logger *logrus.Logger
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func New(
|
||||
@@ -102,7 +102,7 @@ func New(
|
||||
contentStorage ContentStorage,
|
||||
imageTransformer *image.Transformer,
|
||||
av Antivirus,
|
||||
logger *logrus.Logger,
|
||||
logger *slog.Logger,
|
||||
) *Controller {
|
||||
return &Controller{
|
||||
publicURL,
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
@@ -32,7 +33,10 @@ func (ctrl *Controller) DeleteBrokenMetadata( //nolint:ireturn
|
||||
|
||||
files, apiErr := ctrl.deleteBrokenMetadata(ctx)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to delete broken metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to delete broken metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -43,8 +44,9 @@ func TestDeleteBrokenMetadata(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
c := gomock.NewController(t)
|
||||
defer c.Finish()
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
@@ -17,12 +18,18 @@ func (ctrl *Controller) DeleteFile( //nolint:ireturn
|
||||
|
||||
apiErr := ctrl.metadataStorage.DeleteFileByID(ctx, request.Id, sessionHeaders)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem deleting file metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "problem deleting file metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
if apiErr := ctrl.contentStorage.DeleteFile(ctx, request.Id); apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem deleting file content")
|
||||
logger.ErrorContext(
|
||||
ctx, "problem deleting file content", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -23,8 +24,7 @@ func TestDeleteFile(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}))
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
@@ -30,7 +31,10 @@ func (ctrl *Controller) DeleteOrphanedFiles( //nolint:ireturn
|
||||
|
||||
files, apiErr := ctrl.deleteOrphans(ctx)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to delete orphaned files")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to delete orphaned files", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -29,8 +30,9 @@ func TestDeleteOrphans(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
c := gomock.NewController(t)
|
||||
defer c.Finish()
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"slices"
|
||||
@@ -14,7 +15,6 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/image"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func deptr[T any](v *T) T { //nolint:ireturn
|
||||
@@ -254,8 +254,9 @@ func (ctrl *Controller) processFileToDownload(
|
||||
}
|
||||
|
||||
func (ctrl *Controller) getFileResponse( //nolint: ireturn,dupl
|
||||
ctx context.Context,
|
||||
file *processedFile,
|
||||
logger logrus.FieldLogger,
|
||||
logger *slog.Logger,
|
||||
) api.GetFileResponseObject {
|
||||
switch file.statusCode {
|
||||
case http.StatusOK:
|
||||
@@ -311,8 +312,9 @@ func (ctrl *Controller) getFileResponse( //nolint: ireturn,dupl
|
||||
},
|
||||
}
|
||||
default:
|
||||
logger.WithField("statusCode", file.statusCode).
|
||||
Error("unexpected status code from download")
|
||||
logger.ErrorContext(
|
||||
ctx, "unexpected status code from download", slog.Int("statusCode", file.statusCode),
|
||||
)
|
||||
|
||||
return ErrUnexpectedStatusCode
|
||||
}
|
||||
@@ -330,7 +332,10 @@ func (ctrl *Controller) GetFile( //nolint:ireturn
|
||||
ctx, request.Id, true, sessionHeaders,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to get file metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to get file metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -350,9 +355,12 @@ func (ctrl *Controller) GetFile( //nolint:ireturn
|
||||
acceptHeader,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to process file for download")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to process file for download", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
return ctrl.getFileResponse(processedFile, logger), nil
|
||||
return ctrl.getFileResponse(ctx, processedFile, logger), nil
|
||||
}
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
@@ -8,7 +10,6 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/nhost/nhost/services/storage/image"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -194,8 +195,7 @@ func TestGetFileInfo(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}))
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
@@ -24,13 +25,18 @@ func (ctrl *Controller) GetFilePresignedURL( //nolint:ireturn
|
||||
ctx context.Context, request api.GetFilePresignedURLRequestObject,
|
||||
) (api.GetFilePresignedURLResponseObject, error) {
|
||||
logger := middleware.LoggerFromContext(ctx)
|
||||
logger = logger.With("file_id", request.Id)
|
||||
|
||||
sessionHeaders := middleware.SessionHeadersFromContext(ctx)
|
||||
|
||||
fileMetadata, bucketMetadata, apiErr := ctrl.getFileMetadata(
|
||||
ctx, request.Id, true, sessionHeaders,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("error getting file metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "error getting file metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -38,7 +44,8 @@ func (ctrl *Controller) GetFilePresignedURL( //nolint:ireturn
|
||||
err := errors.New( //nolint: err113
|
||||
"presigned URLs are not enabled on the bucket where this file is located in",
|
||||
)
|
||||
logger.WithError(err).Error("presigned URLs not enabled for bucket")
|
||||
|
||||
logger.ErrorContext(ctx, "presigned URLs not enabled for bucket")
|
||||
|
||||
return ForbiddenError(err, err.Error()), nil
|
||||
}
|
||||
@@ -49,7 +56,9 @@ func (ctrl *Controller) GetFilePresignedURL( //nolint:ireturn
|
||||
time.Duration(bucketMetadata.DownloadExpiration)*time.Second,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("error creating presigned URL for file")
|
||||
logger.ErrorContext(
|
||||
ctx, "error creating presigned URL for file", slog.String("error", apiErr.Error()))
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -2,13 +2,14 @@ package controller_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -32,8 +33,7 @@ func TestGetFilePresignedURL(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}))
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -2,7 +2,9 @@ package controller_test
|
||||
|
||||
import (
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -10,7 +12,6 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -200,8 +201,7 @@ func TestGetFile(t *testing.T) { //nolint:maintidx
|
||||
},
|
||||
}
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}))
|
||||
|
||||
for _, tc := range cases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -12,7 +13,6 @@ import (
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -81,8 +81,9 @@ func getAmazonSignature(request api.GetFileWithPresignedURLRequestObject) string
|
||||
}
|
||||
|
||||
func (ctrl *Controller) getFileWithPresignedURLResponseObject( //nolint: ireturn,dupl
|
||||
ctx context.Context,
|
||||
file *processedFile,
|
||||
logger logrus.FieldLogger,
|
||||
logger *slog.Logger,
|
||||
) api.GetFileWithPresignedURLResponseObject {
|
||||
switch file.statusCode {
|
||||
case http.StatusOK:
|
||||
@@ -138,8 +139,9 @@ func (ctrl *Controller) getFileWithPresignedURLResponseObject( //nolint: ireturn
|
||||
},
|
||||
}
|
||||
default:
|
||||
logger.WithField("statusCode", file.statusCode).
|
||||
Error("unexpected status code from download")
|
||||
logger.ErrorContext(
|
||||
ctx, "unexpected status code from download", slog.Int("statusCode", file.statusCode),
|
||||
)
|
||||
|
||||
return ErrUnexpectedStatusCode
|
||||
}
|
||||
@@ -159,7 +161,10 @@ func (ctrl *Controller) GetFileWithPresignedURL( //nolint: ireturn
|
||||
http.Header{"x-hasura-admin-secret": []string{ctrl.hasuraAdminSecret}},
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to get file metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to get file metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -172,7 +177,10 @@ func (ctrl *Controller) GetFileWithPresignedURL( //nolint: ireturn
|
||||
|
||||
expires, apiErr := expiresIn(request.Params.XAmzExpires, request.Params.XAmzDate)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to parse expiration time")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to parse expiration time", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -193,9 +201,12 @@ func (ctrl *Controller) GetFileWithPresignedURL( //nolint: ireturn
|
||||
acceptHeader,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to process file for download")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to process file for download", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return nil, apiErr
|
||||
}
|
||||
|
||||
return ctrl.getFileWithPresignedURLResponseObject(processedFile, logger), nil
|
||||
return ctrl.getFileWithPresignedURLResponseObject(ctx, processedFile, logger), nil
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"path"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
@@ -63,7 +64,10 @@ func (ctrl *Controller) ListBrokenMetadata( //nolint:ireturn
|
||||
|
||||
files, apiErr := ctrl.listBrokenMetadata(ctx)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to list broken metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to list broken metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -42,8 +43,9 @@ func TestListBrokenMetadata(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
c := gomock.NewController(t)
|
||||
defer c.Finish()
|
||||
|
||||
@@ -3,6 +3,7 @@ package controller
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
@@ -55,7 +56,10 @@ func (ctrl *Controller) ListFilesNotUploaded( //nolint:ireturn
|
||||
|
||||
files, apiErr := ctrl.listNotUploaded(ctx)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to list not uploaded files")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to list not uploaded files", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -36,8 +37,9 @@ func TestListNotUploaded(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
c := gomock.NewController(t)
|
||||
defer c.Finish()
|
||||
|
||||
@@ -2,6 +2,7 @@ package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"path"
|
||||
|
||||
@@ -50,7 +51,10 @@ func (ctrl *Controller) ListOrphanedFiles( //nolint:ireturn
|
||||
|
||||
files, apiErr := ctrl.listOrphans(ctx)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("failed to delete orphaned files")
|
||||
logger.ErrorContext(
|
||||
ctx, "failed to list orphaned files", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package controller_test
|
||||
|
||||
import (
|
||||
"log/slog"
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -29,8 +30,9 @@ func TestListOrphans(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
c := gomock.NewController(t)
|
||||
defer c.Finish()
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/middleware"
|
||||
@@ -71,7 +72,7 @@ func (ctrl *Controller) ReplaceFile( //nolint:funlen,ireturn
|
||||
|
||||
file, apiErr := replaceFileParseRequest(request)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem parsing request")
|
||||
logger.ErrorContext(ctx, "problem parsing request", slog.String("error", apiErr.Error()))
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -79,22 +80,34 @@ func (ctrl *Controller) ReplaceFile( //nolint:funlen,ireturn
|
||||
ctx, request.Id, false, sessionHeaders,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem getting file metadata")
|
||||
logger.ErrorContext(
|
||||
ctx, "problem getting file metadata", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
if apiErr = checkFileSize(
|
||||
file.header, bucketMetadata.MinUploadFile, bucketMetadata.MaxUploadFile,
|
||||
); apiErr != nil {
|
||||
apiErr := fmt.Errorf("problem checking file size %s: %w", file.Name, apiErr)
|
||||
logger.WithError(apiErr).Errorf("problem checking file size %s", file.Name)
|
||||
wrappedErr := fmt.Errorf("problem checking file size %s: %w", file.Name, apiErr)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem checking file size",
|
||||
slog.String("error", wrappedErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return InternalServerError(apiErr), nil
|
||||
return InternalServerError(wrappedErr), nil
|
||||
}
|
||||
|
||||
fileContent, contentType, apiErr := ctrl.getMultipartFile(file)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Errorf("problem getting multipart file %s", file.Name)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem getting multipart file",
|
||||
slog.String("error", apiErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
defer fileContent.Close()
|
||||
@@ -102,14 +115,24 @@ func (ctrl *Controller) ReplaceFile( //nolint:funlen,ireturn
|
||||
if apiErr := ctrl.scanAndReportVirus(
|
||||
ctx, fileContent, file.ID, file.Name, sessionHeaders,
|
||||
); apiErr != nil {
|
||||
logger.WithError(apiErr).Errorf("problem scanning file %s for viruses", file.Name)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem scanning file for viruses",
|
||||
slog.String("error", apiErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
if apiErr := ctrl.metadataStorage.SetIsUploaded(
|
||||
ctx, file.ID, false, sessionHeaders,
|
||||
); apiErr != nil {
|
||||
logger.WithError(apiErr).Errorf("problem flagging file as pending upload %s", file.Name)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem flagging file as pending upload",
|
||||
slog.String("error", apiErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
@@ -117,7 +140,11 @@ func (ctrl *Controller) ReplaceFile( //nolint:funlen,ireturn
|
||||
if apiErr != nil {
|
||||
// let's revert the change to isUploaded
|
||||
_ = ctrl.metadataStorage.SetIsUploaded(ctx, file.ID, true, sessionHeaders)
|
||||
logger.WithError(apiErr).Errorf("problem uploading file %s to storage", file.Name)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem uploading file to storage",
|
||||
slog.String("error", apiErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
@@ -129,7 +156,12 @@ func (ctrl *Controller) ReplaceFile( //nolint:funlen,ireturn
|
||||
sessionHeaders,
|
||||
)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Errorf("problem populating file metadata for file %s", file.Name)
|
||||
logger.ErrorContext(
|
||||
ctx, "problem populating file metadata for file",
|
||||
slog.String("error", apiErr.Error()),
|
||||
slog.String("fileName", file.Name),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,9 @@ package controller_test
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"log/slog"
|
||||
"mime/multipart"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -13,7 +15,6 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -67,8 +68,9 @@ func TestReplaceFile(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
file := fakeFile{
|
||||
contents: "some content",
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"mime/multipart"
|
||||
"net/http"
|
||||
|
||||
@@ -253,19 +254,25 @@ func (ctrl *Controller) UploadFiles( //nolint:ireturn
|
||||
|
||||
form, err := request.Body.ReadForm(maxFormMemory)
|
||||
if err != nil {
|
||||
logger.WithError(err).Error("problem reading multipart form")
|
||||
logger.ErrorContext(
|
||||
ctx, "problem reading multipart form", slog.String("error", err.Error()),
|
||||
)
|
||||
|
||||
return InternalServerError(err), nil
|
||||
}
|
||||
|
||||
uploadFilesRequest, apiErr := parseUploadRequest(form)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem parsing upload request")
|
||||
logger.ErrorContext(
|
||||
ctx, "problem parsing upload request", slog.String("error", apiErr.Error()),
|
||||
)
|
||||
|
||||
return apiErr, nil
|
||||
}
|
||||
|
||||
fm, apiErr := ctrl.upload(ctx, uploadFilesRequest, sessionHeaders)
|
||||
if apiErr != nil {
|
||||
logger.WithError(apiErr).Error("problem uploading files")
|
||||
logger.ErrorContext(ctx, "problem uploading files", slog.String("error", apiErr.Error()))
|
||||
|
||||
return api.UploadFilesdefaultJSONResponse{
|
||||
Body: api.ErrorResponseWithProcessedFiles{
|
||||
|
||||
@@ -5,8 +5,10 @@ import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"mime/multipart"
|
||||
"net/textproto"
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
@@ -16,7 +18,6 @@ import (
|
||||
"github.com/nhost/nhost/services/storage/api"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/controller/mock"
|
||||
"github.com/sirupsen/logrus"
|
||||
gomock "go.uber.org/mock/gomock"
|
||||
)
|
||||
|
||||
@@ -115,8 +116,9 @@ func TestUploadFile(t *testing.T) {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
logger := logrus.New()
|
||||
logger.SetLevel(logrus.ErrorLevel)
|
||||
logger := slog.New(
|
||||
slog.NewTextHandler(os.Stdout, &slog.HandlerOptions{Level: slog.LevelError}),
|
||||
)
|
||||
|
||||
files := []fakeFile{
|
||||
{
|
||||
|
||||
@@ -1,16 +1,77 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/nhost/nhost/services/storage/cmd"
|
||||
docs "github.com/urfave/cli-docs/v3"
|
||||
"github.com/urfave/cli/v3"
|
||||
)
|
||||
|
||||
const (
|
||||
flagOutput = "output"
|
||||
)
|
||||
|
||||
var Version string
|
||||
|
||||
func markdownDocs() *cli.Command {
|
||||
return &cli.Command{ //nolint:exhaustruct
|
||||
Name: "docs",
|
||||
Usage: "Generate markdown documentation for the CLI",
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{ //nolint:exhaustruct
|
||||
Name: flagOutput,
|
||||
Usage: "Output file (default: stdout)",
|
||||
Value: "",
|
||||
},
|
||||
},
|
||||
Action: func(_ context.Context, cmd *cli.Command) error {
|
||||
md, err := docs.ToMarkdown(cmd.Root())
|
||||
if err != nil {
|
||||
return cli.Exit("failed to generate markdown documentation: "+err.Error(), 1)
|
||||
}
|
||||
|
||||
out := os.Stdout
|
||||
if output := cmd.String(flagOutput); output != "" {
|
||||
out, err = os.OpenFile(
|
||||
output,
|
||||
os.O_CREATE|os.O_WRONLY|os.O_TRUNC,
|
||||
0o644, //nolint:mnd
|
||||
)
|
||||
if err != nil {
|
||||
return cli.Exit("failed to open output file: "+err.Error(), 1)
|
||||
}
|
||||
}
|
||||
defer out.Close()
|
||||
|
||||
if _, err := out.WriteString(md); err != nil {
|
||||
return cli.Exit("failed to write markdown documentation: "+err.Error(), 1)
|
||||
}
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
//go:generate oapi-codegen -config api/server.cfg.yaml controller/openapi.yaml
|
||||
//go:generate oapi-codegen -config api/types.cfg.yaml controller/openapi.yaml
|
||||
//go:generate gqlgenc
|
||||
func main() {
|
||||
if err := cmd.Execute(); err != nil {
|
||||
os.Exit(1)
|
||||
serveCmd := cmd.CommandServe()
|
||||
app := &cli.Command{ //nolint:exhaustruct
|
||||
Name: "storage",
|
||||
Version: Version,
|
||||
Usage: "Nhost Storage API server",
|
||||
Flags: serveCmd.Flags,
|
||||
Commands: []*cli.Command{
|
||||
markdownDocs(),
|
||||
},
|
||||
Action: serveCmd.Action,
|
||||
}
|
||||
|
||||
if err := app.Run(context.Background(), os.Args); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,10 @@ curl -D - -X POST --location "https://api.fastly.com/tokens" \
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -66,7 +66,7 @@ func (fst *fastly) purge(ctx context.Context, key string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func New(serviceID string, apiKey string, logger *logrus.Logger) gin.HandlerFunc {
|
||||
func New(serviceID string, apiKey string, logger *slog.Logger) gin.HandlerFunc {
|
||||
fst := &fastly{serviceID, apiKey}
|
||||
|
||||
return func(ctx *gin.Context) {
|
||||
@@ -87,10 +87,16 @@ func New(serviceID string, apiKey string, logger *logrus.Logger) gin.HandlerFunc
|
||||
}
|
||||
|
||||
if id := ctx.GetString(fileChangedContextKey); id != "" {
|
||||
logger.WithField("key", id).Debug("purging file from cdn")
|
||||
logger.InfoContext(
|
||||
ctx.Request.Context(), "purging file from cdn", slog.String("key", id),
|
||||
)
|
||||
|
||||
if err := fst.purge(ctx, id); err != nil {
|
||||
logger.WithField("key", id).WithError(err).Error("failed to purge file from cdn")
|
||||
logger.ErrorContext(
|
||||
ctx.Request.Context(),
|
||||
"failed to purge file from cdn",
|
||||
slog.String("key", id), slog.String("error", err.Error()),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,35 +2,35 @@ package middleware
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
type loggerCtxKey struct{}
|
||||
|
||||
// Stores the logger in the context.
|
||||
func LoggerToContext(ctx context.Context, logger logrus.FieldLogger) context.Context {
|
||||
func LoggerToContext(ctx context.Context, logger *slog.Logger) context.Context {
|
||||
return context.WithValue(ctx, loggerCtxKey{}, logger)
|
||||
}
|
||||
|
||||
// Retrieves the logger from the context. It creates a new one if it can't be found.
|
||||
func LoggerFromContext(ctx context.Context) logrus.FieldLogger { //nolint:contextcheck,ireturn
|
||||
func LoggerFromContext(ctx context.Context) *slog.Logger { //nolint:contextcheck
|
||||
ginCtx, ok := ctx.(*gin.Context)
|
||||
if ok {
|
||||
ctx = ginCtx.Request.Context()
|
||||
}
|
||||
|
||||
logger, ok := ctx.Value(loggerCtxKey{}).(logrus.FieldLogger)
|
||||
logger, ok := ctx.Value(loggerCtxKey{}).(*slog.Logger)
|
||||
if !ok {
|
||||
return logrus.New()
|
||||
return slog.Default()
|
||||
}
|
||||
|
||||
return logger
|
||||
}
|
||||
|
||||
func Logger(logger logrus.FieldLogger) gin.HandlerFunc {
|
||||
func Logger(logger *slog.Logger) gin.HandlerFunc {
|
||||
return func(ctx *gin.Context) {
|
||||
startTime := time.Now()
|
||||
|
||||
@@ -39,14 +39,20 @@ func Logger(logger logrus.FieldLogger) gin.HandlerFunc {
|
||||
clientIP := ctx.ClientIP()
|
||||
reqMethod := ctx.Request.Method
|
||||
reqURL := ctx.Request.RequestURI
|
||||
logger := logger.WithFields(logrus.Fields{
|
||||
"trace_id": trace.TraceID,
|
||||
"span_id": trace.SpanID,
|
||||
"parent_span_id": trace.ParentSpanID,
|
||||
"client_ip": clientIP,
|
||||
"request_method": reqMethod,
|
||||
"request_url": reqURL,
|
||||
})
|
||||
logger := logger.With(
|
||||
slog.Group(
|
||||
"trace",
|
||||
slog.String("trace_id", trace.TraceID),
|
||||
slog.String("span_id", trace.SpanID),
|
||||
slog.String("parent_span_id", trace.ParentSpanID),
|
||||
),
|
||||
slog.Group(
|
||||
"request",
|
||||
slog.String("client_ip", clientIP),
|
||||
slog.String("method", reqMethod),
|
||||
slog.String("url", reqURL),
|
||||
),
|
||||
)
|
||||
ctx.Request = ctx.Request.WithContext(
|
||||
LoggerToContext(ctx.Request.Context(), logger),
|
||||
)
|
||||
@@ -55,18 +61,19 @@ func Logger(logger logrus.FieldLogger) gin.HandlerFunc {
|
||||
latencyTime := time.Since(startTime)
|
||||
statusCode := ctx.Writer.Status()
|
||||
|
||||
logger = logger.WithFields(logrus.Fields{
|
||||
"status_code": statusCode,
|
||||
"latency_time": latencyTime,
|
||||
"errors": ctx.Errors.Errors(),
|
||||
})
|
||||
logger = logger.With(slog.Group(
|
||||
"response",
|
||||
slog.Int("status_code", statusCode),
|
||||
slog.Duration("latency_time", latencyTime),
|
||||
slog.Any("errors", ctx.Errors.Errors()),
|
||||
))
|
||||
|
||||
TraceToHTTPHeaders(trace, ctx.Writer.Header())
|
||||
|
||||
if len(ctx.Errors.Errors()) > 0 {
|
||||
logger.Error("call completed with errors")
|
||||
logger.ErrorContext(ctx, "call completed with errors")
|
||||
} else {
|
||||
logger.Info("call completed")
|
||||
logger.InfoContext(ctx, "call completed")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ type hasuraErrResponse struct {
|
||||
Code string `json:"code"`
|
||||
}
|
||||
|
||||
func postMetadata(baseURL, hasuraSecret string, data interface{}) error {
|
||||
func postMetadata(ctx context.Context, baseURL, hasuraSecret string, data any) error {
|
||||
client := &http.Client{ //nolint: exhaustruct
|
||||
Timeout: time.Second * timeout,
|
||||
}
|
||||
@@ -31,7 +31,7 @@ func postMetadata(baseURL, hasuraSecret string, data interface{}) error {
|
||||
}
|
||||
|
||||
req, err := http.NewRequestWithContext(
|
||||
context.Background(),
|
||||
ctx,
|
||||
http.MethodPost,
|
||||
baseURL+"/metadata",
|
||||
bytes.NewBuffer(b),
|
||||
@@ -154,7 +154,9 @@ type DropRelationshipArgs struct {
|
||||
Relationship string `json:"relationship"`
|
||||
}
|
||||
|
||||
func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolint: funlen
|
||||
func ApplyHasuraMetadata( //nolint: funlen
|
||||
ctx context.Context, url, hasuraSecret, hasuraDBName string,
|
||||
) error {
|
||||
bucketsTable := TrackTable{
|
||||
Type: "pg_track_table",
|
||||
Args: PgTrackTableArgs{
|
||||
@@ -190,7 +192,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, bucketsTable); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, bucketsTable); err != nil {
|
||||
return fmt.Errorf("problem adding metadata for the buckets table: %w", err)
|
||||
}
|
||||
|
||||
@@ -232,7 +234,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, filesTable); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, filesTable); err != nil {
|
||||
return fmt.Errorf("problem adding metadata for the files table: %w", err)
|
||||
}
|
||||
|
||||
@@ -270,7 +272,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, virusTable); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, virusTable); err != nil {
|
||||
return fmt.Errorf("problem adding metadata for the virus table: %w", err)
|
||||
}
|
||||
|
||||
@@ -289,7 +291,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, objRelationshipBuckets); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, objRelationshipBuckets); err != nil {
|
||||
return fmt.Errorf("problem creaiing object relationship for buckets: %w", err)
|
||||
}
|
||||
|
||||
@@ -314,7 +316,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, arrRelationship); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, arrRelationship); err != nil {
|
||||
return fmt.Errorf("problem creating array relationships: %w", err)
|
||||
}
|
||||
|
||||
@@ -333,7 +335,7 @@ func ApplyHasuraMetadata(url, hasuraSecret, hasuraDBName string) error { //nolin
|
||||
},
|
||||
}
|
||||
|
||||
if err := postMetadata(url, hasuraSecret, objRelationshipVirusFile); err != nil {
|
||||
if err := postMetadata(ctx, url, hasuraSecret, objRelationshipVirusFile); err != nil {
|
||||
return fmt.Errorf("problem creaiing object relationship for buckets: %w", err)
|
||||
}
|
||||
|
||||
|
||||
@@ -1,14 +0,0 @@
|
||||
---
|
||||
debug: true
|
||||
hasura-endpoint: http://localhost:8080/v1
|
||||
hasura-metadata: true
|
||||
hasura-graphql-admin-secret: nhost-admin-secret
|
||||
s3-endpoint: "http://localhost:9000"
|
||||
s3-access-key: "5a7bdb5f42c41e0622bf61d6e08d5537"
|
||||
s3-secret-key: "9e1c40c65a615a5b52f52aeeaf549944ec53acb1dff4a0bf01fb58e969f915c8"
|
||||
s3-disable-http: true
|
||||
s3-region: "us-east-1"
|
||||
s3-bucket: "default"
|
||||
s3-root-folder: "f215cf48-7458-4596-9aa5-2159fc6a3caf"
|
||||
postgres-migrations: true
|
||||
postgres-migrations-source: postgres://postgres:hejsan@localhost:5432/postgres?sslmode=disable
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"github.com/aws/aws-sdk-go-v2/aws"
|
||||
"github.com/aws/aws-sdk-go-v2/service/s3"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func deptr[T any](p *T) T { //nolint:ireturn
|
||||
@@ -63,7 +63,7 @@ type S3 struct {
|
||||
bucket *string
|
||||
rootFolder string
|
||||
url string
|
||||
logger *logrus.Logger
|
||||
logger *slog.Logger
|
||||
}
|
||||
|
||||
func NewS3(
|
||||
@@ -71,7 +71,7 @@ func NewS3(
|
||||
bucket string,
|
||||
rootFolder string,
|
||||
url string,
|
||||
logger *logrus.Logger,
|
||||
logger *slog.Logger,
|
||||
) *S3 {
|
||||
return &S3{
|
||||
client: client,
|
||||
|
||||
@@ -6,6 +6,7 @@ package storage_test
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net/http"
|
||||
"os"
|
||||
"slices"
|
||||
@@ -21,11 +22,10 @@ import (
|
||||
"github.com/google/go-cmp/cmp/cmpopts"
|
||||
"github.com/nhost/nhost/services/storage/controller"
|
||||
"github.com/nhost/nhost/services/storage/storage"
|
||||
"github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
func getS3() *storage.S3 {
|
||||
logger := logrus.New()
|
||||
logger := slog.New(slog.NewTextHandler(os.Stdout, nil))
|
||||
ctx := context.Background()
|
||||
config, err := config.LoadDefaultConfig(ctx,
|
||||
config.WithRegion("eu-central-1"),
|
||||
@@ -38,7 +38,7 @@ func getS3() *storage.S3 {
|
||||
),
|
||||
)
|
||||
if err != nil {
|
||||
logger.Error(err)
|
||||
logger.ErrorContext(ctx, "config load failed", slog.String("error", err.Error()))
|
||||
}
|
||||
url := "http://localhost:9000"
|
||||
client := s3.NewFromConfig(config,
|
||||
|
||||
@@ -91,6 +91,10 @@ export interface SignInProviderParams {
|
||||
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
/**
|
||||
Summary: Sign in with an OAuth2 provider
|
||||
|
||||
@@ -610,6 +610,10 @@ export interface VerifyTicketParams {
|
||||
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
/**
|
||||
Summary: Refresh access token
|
||||
|
||||
@@ -138,6 +138,10 @@ export interface SimpleObject {
|
||||
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;};
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
{{- define "client_interface" }}
|
||||
export interface Client {
|
||||
baseURL: string;
|
||||
|
||||
/** Add a middleware function to the fetch chain
|
||||
* @param chainFunction - The middleware function to add
|
||||
*/
|
||||
pushChainFunction(chainFunction: ChainFunction): void;
|
||||
{{- range .Methods }}
|
||||
{{- $method := . }}
|
||||
|
||||
14
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
14
vendor/github.com/fsnotify/fsnotify/.cirrus.yml
generated
vendored
@@ -1,14 +0,0 @@
|
||||
freebsd_task:
|
||||
name: 'FreeBSD'
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-2
|
||||
install_script:
|
||||
- pkg update -f
|
||||
- pkg install -y go
|
||||
test_script:
|
||||
# run tests as user "cirrus" instead of root
|
||||
- pw useradd cirrus -m
|
||||
- chown -R cirrus:cirrus .
|
||||
- FSNOTIFY_BUFFER=4096 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
|
||||
- sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race ./...
|
||||
- FSNOTIFY_DEBUG=1 sudo --preserve-env=FSNOTIFY_BUFFER -u cirrus go test -parallel 1 -race -v ./...
|
||||
10
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
10
vendor/github.com/fsnotify/fsnotify/.gitignore
generated
vendored
@@ -1,10 +0,0 @@
|
||||
# go test -c output
|
||||
*.test
|
||||
*.test.exe
|
||||
|
||||
# Output of go build ./cmd/fsnotify
|
||||
/fsnotify
|
||||
/fsnotify.exe
|
||||
|
||||
/test/kqueue
|
||||
/test/a.out
|
||||
2
vendor/github.com/fsnotify/fsnotify/.mailmap
generated
vendored
2
vendor/github.com/fsnotify/fsnotify/.mailmap
generated
vendored
@@ -1,2 +0,0 @@
|
||||
Chris Howey <howeyc@gmail.com> <chris@howey.me>
|
||||
Nathan Youngman <git@nathany.com> <4566+nathany@users.noreply.github.com>
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user