Merge branch 'next' into develop

This commit is contained in:
Zeke Zhang 2024-08-18 08:41:51 +08:00
commit e617e10758
47 changed files with 1056 additions and 642 deletions

View File

@ -7,6 +7,40 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
## [v1.2.35-alpha](https://github.com/nocobase/nocobase/compare/v1.2.34-alpha...v1.2.35-alpha) - 2024-08-16
### Merged
- fix: the display of data source status [`#5069`](https://github.com/nocobase/nocobase/pull/5069)
- chore: upgrade mysql2 version [`#5070`](https://github.com/nocobase/nocobase/pull/5070)
- fix: filter form action bar stye improve [`#5054`](https://github.com/nocobase/nocobase/pull/5054)
- fix: quote table name in mysql query interface [`#5065`](https://github.com/nocobase/nocobase/pull/5065)
- fix: collection with non ID as the primary key will encounter an error when using gantt [`#5061`](https://github.com/nocobase/nocobase/pull/5061)
- fix: increase the upload file size limit of field-markdown-vditor [`#5063`](https://github.com/nocobase/nocobase/pull/5063)
- fix(data-vi): dependency typo [`#5060`](https://github.com/nocobase/nocobase/pull/5060)
- chore(deps): bump @babel/plugin-transform-modules-amd from 7.22.5 to 7.24.7 [`#5052`](https://github.com/nocobase/nocobase/pull/5052)
- chore(deps): bump xpipe from 1.0.5 to 1.0.7 [`#5050`](https://github.com/nocobase/nocobase/pull/5050)
- chore(deps): bump tsup from 7.2.0 to 8.2.4 [`#5046`](https://github.com/nocobase/nocobase/pull/5046)
- fix(inherit): correct title for inherited sub-collection association block [`#5048`](https://github.com/nocobase/nocobase/pull/5048)
- fix: load parent field in inherited collection [`#5044`](https://github.com/nocobase/nocobase/pull/5044)
- fix: disable edit and delete button for all records and own record in data scope configuration [`#5041`](https://github.com/nocobase/nocobase/pull/5041)
- fix(Collapse): fix issue with data scope settings being ineffective [`#4914`](https://github.com/nocobase/nocobase/pull/4914)
- fix(Table): should not error when open a popup by clicking a multi-level field [`#5038`](https://github.com/nocobase/nocobase/pull/5038)
- fix(linkageRules): fix an exception when the condition contains a association field [`#5037`](https://github.com/nocobase/nocobase/pull/5037)
- fix(client): missing sort parameter [`#5034`](https://github.com/nocobase/nocobase/pull/5034)
- fix(database): skip table doesn't exist [`#5023`](https://github.com/nocobase/nocobase/pull/5023)
- fix(variable): the chinaRegions field should not be a submenu [`#5030`](https://github.com/nocobase/nocobase/pull/5030)
- style: quick add button for association field in the form, compact theme style without adaptation [`#5024`](https://github.com/nocobase/nocobase/pull/5024)
- fix: correct foreign key value errors [`#5027`](https://github.com/nocobase/nocobase/pull/5027)
- fix: source field type filtering association fields in sql collection & view collection [`#5014`](https://github.com/nocobase/nocobase/pull/5014)
- fix: allowMultiple should not appear on read-only association fields [`#5017`](https://github.com/nocobase/nocobase/pull/5017)
### Commits
- chore(versions): 😊 publish v1.2.35-alpha [`39bc571`](https://github.com/nocobase/nocobase/commit/39bc5717881454cb1bf210673418e1be49f45614)
- chore: update changelog [`d37c71a`](https://github.com/nocobase/nocobase/commit/d37c71aaed459a1364a2b04bd478f529472a5ae0)
- Update LICENSE.txt [`28c2fff`](https://github.com/nocobase/nocobase/commit/28c2fff0e48ed135322839ae9f27d1740a351902)
## [v1.2.34-alpha](https://github.com/nocobase/nocobase/compare/v1.2.33-alpha...v1.2.34-alpha) - 2024-08-08
### Merged

View File

@ -8,6 +8,7 @@
*/
export * from './useApp';
export * from './useAppSpin';
export * from './usePlugin';
export * from './useRouter';
export * from './useAppSpin';
export * from './useRouterBasename';

View File

@ -0,0 +1,19 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { useHref } from 'react-router-dom';
/**
* see: https://stackoverflow.com/questions/50449423/accessing-basename-of-browserouter
* @returns {string} basename
*/
export const useRouterBasename = () => {
const basenameOfCurrentRouter = useHref('/');
return basenameOfCurrentRouter;
};

View File

@ -20,7 +20,7 @@ import omit from 'lodash/omit';
import qs from 'qs';
import { ChangeEvent, useCallback, useContext, useEffect, useMemo } from 'react';
import { useTranslation } from 'react-i18next';
import { NavigateFunction, useHref } from 'react-router-dom';
import { NavigateFunction } from 'react-router-dom';
import { useReactToPrint } from 'react-to-print';
import {
AssociationFilter,
@ -28,6 +28,7 @@ import {
useCollectionRecord,
useDataSourceHeaders,
useFormActiveFields,
useRouterBasename,
useTableBlockContext,
} from '../..';
import { useAPIClient, useRequest } from '../../api-client';
@ -1594,9 +1595,7 @@ export function useLinkActionProps(componentProps?: any) {
const searchParams = componentPropsValue?.['params'] || [];
const openInNewWindow = fieldSchema?.['x-component-props']?.['openInNewWindow'];
const { parseURLAndParams } = useParseURLAndParams();
// see: https://stackoverflow.com/questions/50449423/accessing-basename-of-browserouter
const basenameOfCurrentRouter = useHref('/');
const basenameOfCurrentRouter = useRouterBasename();
return {
type: 'default',

View File

@ -52,6 +52,7 @@ import {
UUIDFieldInterface,
NanoidFieldInterface,
UnixTimestampFieldInterface,
DateFieldInterface,
} from './interfaces';
import {
GeneralCollectionTemplate,
@ -173,6 +174,7 @@ export class CollectionPlugin extends Plugin {
UUIDFieldInterface,
NanoidFieldInterface,
UnixTimestampFieldInterface,
DateFieldInterface,
]);
}

View File

@ -7,8 +7,8 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Switch } from 'antd';
import React from 'react';
import { Switch, Radio, Input } from 'antd';
import React, { useEffect, useState } from 'react';
export const TargetKey = () => {
return <div>Target key</div>;
@ -50,3 +50,37 @@ export const ForeignKey2 = () => {
</div>
);
};
// 自定义 Radio 组件
export const CustomRadio = (props) => {
const { options, onChange } = props;
const [value, setValue] = useState(props.value);
useEffect(() => {
setValue(['server', 'client'].includes(props.value) ? props.value : 'custom');
}, [props.value]);
const handleRadioChange = (e) => {
setValue(e.target.value);
if (e.target.value !== 'custom') {
onChange?.(e.target.value);
}
};
return (
<Radio.Group onChange={handleRadioChange} value={value}>
{options.map((option) => (
<Radio key={option.value} value={option.value}>
{option.label}
{option.value === 'custom' && value === 'custom' ? (
<Input
style={{ width: 200, marginLeft: 10 }}
onChange={(e) => {
onChange?.(e.target.value);
}}
value={['server', 'client', 'custom'].includes(props.value) ? null : props.value}
/>
) : null}
</Radio>
))}
</Radio.Group>
);
};

View File

@ -0,0 +1,60 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { CollectionFieldInterface } from '../../data-source/collection-field-interface/CollectionFieldInterface';
import { dateTimeProps, defaultProps, operators } from './properties';
export class DateFieldInterface extends CollectionFieldInterface {
name = 'date';
type = 'object';
group = 'datetime';
order = 1;
title = '{{t("Date")}}';
sortable = true;
default = {
type: 'dateOnly',
uiSchema: {
type: 'string',
'x-component': 'DatePicker',
'x-component-props': {
dateOnly: true,
},
},
};
availableTypes = ['date', 'dateOnly', 'string'];
hasDefaultValue = true;
properties = {
...defaultProps,
'uiSchema.x-component-props.dateFormat': {
type: 'string',
title: '{{t("Date format")}}',
'x-component': 'Radio.Group',
'x-decorator': 'FormItem',
default: 'YYYY-MM-DD',
enum: [
{
label: '{{t("Year/Month/Day")}}',
value: 'YYYY/MM/DD',
},
{
label: '{{t("Year-Month-Day")}}',
value: 'YYYY-MM-DD',
},
{
label: '{{t("Day/Month/Year")}}',
value: 'DD/MM/YYYY',
},
],
},
};
filterable = {
operators: operators.datetime,
};
titleUsable = true;
}

View File

@ -19,6 +19,9 @@ export class DatetimeFieldInterface extends CollectionFieldInterface {
sortable = true;
default = {
type: 'date',
defaultToCurrentTime: false,
onUpdateToCurrentTime: false,
timezone: 'server',
uiSchema: {
type: 'string',
'x-component': 'DatePicker',

View File

@ -46,3 +46,4 @@ export * from './sort';
export * from './uuid';
export * from './nanoid';
export * from './unixTimestamp';
export * from './date';

View File

@ -10,6 +10,7 @@
import { Field } from '@formily/core';
import { ISchema } from '@formily/react';
import { uid } from '@formily/shared';
import { CustomRadio } from '../components';
export * as operators from './operators';
export const type: ISchema = {
@ -225,6 +226,29 @@ export const reverseFieldProperties: Record<string, ISchema> = {
};
export const dateTimeProps: { [key: string]: ISchema } = {
timezone: {
type: 'string',
title: '{{t("Timezone")}}',
'x-component': CustomRadio,
'x-decorator': 'FormItem',
default: 'server',
'x-component-props': {
options: [
{
label: '{{t("None")}}',
value: 'server',
},
{
label: '{{t("Client\'s time zone")}}',
value: 'client',
},
{
label: '{{t("Custom")}}',
value: 'custom',
},
],
},
},
'uiSchema.x-component-props.dateFormat': {
type: 'string',
title: '{{t("Date format")}}',
@ -276,6 +300,18 @@ export const dateTimeProps: { [key: string]: ISchema } = {
},
],
},
defaultToCurrentTime: {
type: 'boolean',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-content': '{{t("Default value to current time")}}',
},
onUpdateToCurrentTime: {
type: 'boolean',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-content': '{{t("Automatically update timestamp on update")}}',
},
};
export const dataSource: ISchema = {

View File

@ -8,8 +8,8 @@
*/
import { CollectionFieldInterface } from '../../data-source/collection-field-interface/CollectionFieldInterface';
import { dateTimeProps, defaultProps, operators } from './properties';
import { defaultProps, operators } from './properties';
import { CustomRadio } from './components';
export class UnixTimestampFieldInterface extends CollectionFieldInterface {
name = 'unixTimestamp';
type = 'object';
@ -18,21 +18,47 @@ export class UnixTimestampFieldInterface extends CollectionFieldInterface {
title = '{{t("Unix Timestamp")}}';
sortable = true;
default = {
type: 'bigInt',
type: 'unixTimestamp',
accuracy: 'second',
timezone: 'server',
defaultToCurrentTime: false,
onUpdateToCurrentTime: false,
uiSchema: {
type: 'number',
'x-component': 'UnixTimestamp',
'x-component-props': {
accuracy: 'second',
showTime: true,
},
},
};
availableTypes = ['integer', 'bigInt'];
hasDefaultValue = true;
availableTypes = ['integer', 'bigInt', 'unixTimestamp'];
hasDefaultValue = false;
properties = {
...defaultProps,
'uiSchema.x-component-props.accuracy': {
timezone: {
type: 'string',
title: '{{t("Timezone")}}',
'x-component': CustomRadio,
'x-decorator': 'FormItem',
default: 'server',
'x-component-props': {
options: [
{
label: '{{t("None")}}',
value: 'server',
},
{
label: '{{t("Client\'s time zone")}}',
value: 'client',
},
{
label: 'custom',
value: 'custom',
},
],
},
},
accuracy: {
type: 'string',
title: '{{t("Accuracy")}}',
'x-component': 'Radio.Group',
@ -43,6 +69,20 @@ export class UnixTimestampFieldInterface extends CollectionFieldInterface {
{ value: 'second', label: '{{t("Second")}}' },
],
},
defaultToCurrentTime: {
type: 'boolean',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-content': '{{t("Default value to current time")}}',
default: true,
},
onUpdateToCurrentTime: {
type: 'boolean',
'x-decorator': 'FormItem',
'x-component': 'Checkbox',
'x-content': '{{t("Automatically update timestamp on update")}}',
default: true,
},
};
filterable = {
operators: operators.number,

View File

@ -283,7 +283,7 @@
"Checkbox group": "复选框",
"China region": "中国行政区",
"Date & Time": "日期 & 时间",
"Datetime": "日期",
"Datetime": "日期时间",
"Relation": "关系类型",
"Link to": "关联",
"Link to description": "用于快速创建表关系,可兼容大多数普通场景。适合非开发人员使用。作为字段存在时,它是一个下拉选择用于选择目标数据表的数据。创建后,将同时在目标数据表中生成当前数据表的关联字段。",
@ -967,5 +967,8 @@
"Clear default value": "清除默认值",
"Open in new window": "新窗口打开",
"Sorry, the page you visited does not exist.": "抱歉,你访问的页面不存在。",
"Set Template Engine": "设置模板引擎"
"Template engine": "模板引擎",
"Default value to current time":"设置字段默认值为当前时间",
"Automatically update timestamp on update":"当记录更新时自动设置字段值为当前时间",
"Client's time zone":"客户端时区"
}

View File

@ -78,13 +78,11 @@ export const useTableBlockProps = () => {
),
onChange: useCallback(
({ current, pageSize }, filters, sorter) => {
const sort = !ctx.dragSort
? sorter.order
const sort = sorter.order
? sorter.order === `ascend`
? [sorter.field]
: [`-${sorter.field}`]
: globalSort || ctx.dragSortBy
: ctx.dragSortBy;
: globalSort || ctx.dragSortBy;
const currentPageSize = pageSize || fieldSchema.parent?.['x-decorator-props']?.['params']?.pageSize;
const args = { ...params?.[0], page: current || 1, pageSize: currentPageSize };
if (sort) {
@ -92,7 +90,7 @@ export const useTableBlockProps = () => {
}
ctx.service.run(args);
},
[globalSort, params],
[globalSort, params, ctx.dragSort],
),
onClickRow: useCallback(
(record, setSelectedRow, selectedRow) => {

View File

@ -30,14 +30,14 @@ export const markdownBlockSettings = new SchemaSettings({
};
},
},
{
name: 'setBlockTemplate',
Component: SchemaSettingsRenderEngine,
},
{
name: 'setTheBlockHeight',
Component: SchemaSettingsBlockHeightItem,
},
{
name: 'setBlockTemplate',
Component: SchemaSettingsRenderEngine,
},
{
name: 'divider',
type: 'divider',

View File

@ -154,6 +154,7 @@ export const SubTable: any = observer(
onClick() {
selectedRows.map((v) => field.value.push(v));
field.onInput(field.value);
field.initialValue = field.value;
setSelectedRows([]);
setVisible(false);
},

View File

@ -78,18 +78,21 @@ export const mapDatePicker = function () {
return (props: any) => {
const format = getDefaultFormat(props) as any;
const onChange = props.onChange;
return {
...props,
format: format,
value: str2moment(props.value, props),
onChange: (value: Dayjs | null) => {
onChange: (value: Dayjs | null, dateString) => {
if (onChange) {
if (!props.showTime && value) {
value = value.startOf('day');
}
if (props.dateOnly) {
onChange(dateString);
} else {
onChange(moment2str(value, props));
}
}
},
};
};

View File

@ -17,12 +17,13 @@ import classNames from 'classnames';
import React, { memo, useCallback, useContext, useEffect, useMemo, useState } from 'react';
import { ErrorBoundary } from 'react-error-boundary';
import { useTranslation } from 'react-i18next';
import { Outlet, useOutletContext, useParams, useSearchParams } from 'react-router-dom';
import { NavigateFunction, Outlet, useOutletContext, useParams, useSearchParams } from 'react-router-dom';
import { FormDialog } from '..';
import { useStyles as useAClStyles } from '../../../acl/style';
import { useRequest } from '../../../api-client';
import { useNavigateNoUpdate } from '../../../application/CustomRouterContextProvider';
import { useAppSpin } from '../../../application/hooks/useAppSpin';
import { useRouterBasename } from '../../../application/hooks/useRouterBasename';
import { useDocumentTitle } from '../../../document-title';
import { useGlobalTheme } from '../../../global-theme';
import { Icon } from '../../../icon';
@ -47,6 +48,7 @@ export const Page = (props) => {
const { theme } = useGlobalTheme();
const { getAriaLabel } = useGetAriaLabelOfSchemaInitializer();
const { tabUid, name: pageUid } = useParams();
const basenameOfCurrentRouter = useRouterBasename();
// react18 tab 动画会卡顿,所以第一个 tab 时,动画禁用,后面的 tab 才启用
const [hasMounted, setHasMounted] = useState(false);
@ -112,7 +114,7 @@ export const Page = (props) => {
}}
onChange={(activeKey) => {
setLoading(true);
navigate(`/admin/${pageUid}/tabs/${activeKey}`, { replace: true });
navigateToTab({ activeKey, navigate, basename: basenameOfCurrentRouter });
setTimeout(() => {
setLoading(false);
}, 50);
@ -319,3 +321,41 @@ const PageContent = memo(
},
);
PageContent.displayName = 'PageContent';
export function navigateToTab({
activeKey,
navigate,
basename,
pathname = window.location.pathname,
}: {
activeKey: string;
navigate: NavigateFunction;
/** the router basename */
basename: string;
pathname?: string;
}) {
pathname = pathname.replace(basename, '');
if (pathname.endsWith('/')) {
pathname = pathname.slice(0, -1);
}
if (!pathname.startsWith('/')) {
pathname = `/${pathname}`;
}
if (isTabPage(pathname)) {
navigate(`${pathname.replace(/\/tabs\/[^/]+$/, `/tabs/${activeKey}`)}`, { replace: true });
} else {
navigate(`${pathname}/tabs/${activeKey}`, { replace: true });
}
}
export function isTabPage(pathname: string) {
if (pathname.endsWith('/')) {
pathname = pathname.slice(0, -1);
}
const list = pathname.split('/');
return list[list.length - 2] === 'tabs';
}

View File

@ -84,7 +84,8 @@ const PopupParamsProvider: FC<Omit<PopupProps, 'hidden'>> = (props) => {
return <PopupParamsProviderContext.Provider value={value}>{props.children}</PopupParamsProviderContext.Provider>;
};
const PopupTabsPropsProvider: FC<{ params: PopupParams }> = ({ children, params }) => {
const PopupTabsPropsProvider: FC = ({ children }) => {
const { params } = useCurrentPopupContext();
const { changeTab } = usePagePopup();
const onChange = useCallback(
(key: string) => {
@ -99,7 +100,7 @@ const PopupTabsPropsProvider: FC<{ params: PopupParams }> = ({ children, params
}
return (
<TabsContextProvider activeKey={params.tab} onChange={onChange}>
<TabsContextProvider activeKey={params?.tab} onChange={onChange}>
{children}
</TabsContextProvider>
);
@ -166,7 +167,7 @@ const PagePopupsItemProvider: FC<{
>
{/* Pass the service of the block where the button is located down, to refresh the block's data when the popup is closed */}
<BlockRequestContext.Provider value={storedContext.service}>
<PopupTabsPropsProvider params={params}>
<PopupTabsPropsProvider>
<div style={{ display: 'none' }}>{children}</div>
</PopupTabsPropsProvider>
</BlockRequestContext.Provider>

View File

@ -7,11 +7,11 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { render, screen, waitFor, renderAppOptions, userEvent } from '@nocobase/test/client';
import { DocumentTitleProvider, Form, FormItem, Grid, IconPicker, Input } from '@nocobase/client';
import { render, renderAppOptions, screen, userEvent, waitFor } from '@nocobase/test/client';
import React from 'react';
import App1 from '../demos/demo1';
import { Page } from '../Page';
import { DocumentTitleProvider, Form, FormItem, Grid, IconPicker, Input } from '@nocobase/client';
import { isTabPage, navigateToTab, Page } from '../Page';
describe('Page', () => {
it('should render correctly', async () => {
@ -159,3 +159,196 @@ describe('Page', () => {
});
});
});
describe('utils', () => {
it('isTabPage', () => {
expect(isTabPage('/admin')).toBe(false);
expect(isTabPage('/admin/test/tabs/tabId')).toBe(true);
expect(isTabPage('/admin/test/tabs/tabId/')).toBe(true);
});
it('navigateToTab with basename "/"', () => {
const navigate1 = vi.fn();
const navigate2 = vi.fn();
const navigate3 = vi.fn();
const navigate4 = vi.fn();
const navigate5 = vi.fn();
const navigate6 = vi.fn();
const navigate7 = vi.fn();
const navigate8 = vi.fn();
navigateToTab({ activeKey: 'tabId', navigate: navigate1, pathname: '/admin/test', basename: '/' });
expect(navigate1).toBeCalledWith('/admin/test/tabs/tabId', { replace: true });
navigateToTab({ activeKey: 'tabId', navigate: navigate2, pathname: '/admin/test/', basename: '/' });
expect(navigate2).toBeCalledWith('/admin/test/tabs/tabId', { replace: true });
navigateToTab({ activeKey: 'tabId', navigate: navigate3, pathname: '/admin/test/tabs/oldTabId', basename: '/' });
expect(navigate3).toBeCalledWith('/admin/test/tabs/tabId', { replace: true });
navigateToTab({ activeKey: 'tabId', navigate: navigate4, pathname: '/admin/test/tabs/oldTabId/', basename: '/' });
expect(navigate4).toBeCalledWith('/admin/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate5,
pathname: '/admin/test/tabs/tab1/pages/pageId/tabs/tab2',
basename: '/',
});
expect(navigate5).toBeCalledWith('/admin/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate6,
pathname: '/admin/test/tabs/tab1/pages/pageId/tabs/tab2/',
basename: '/',
});
expect(navigate6).toBeCalledWith('/admin/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate7,
pathname: '/admin/test/tabs/tab1/pages/pageId',
basename: '/',
});
expect(navigate7).toBeCalledWith('/admin/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate8,
pathname: '/admin/test/tabs/tab1/pages/pageId/',
basename: '/',
});
expect(navigate8).toBeCalledWith('/admin/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
});
it('navigateToTab with basename "/apps/appId"', () => {
const navigate1 = vi.fn();
const navigate2 = vi.fn();
const navigate3 = vi.fn();
const navigate4 = vi.fn();
const navigate5 = vi.fn();
const navigate6 = vi.fn();
const navigate7 = vi.fn();
const navigate8 = vi.fn();
navigateToTab({ activeKey: 'tabId', navigate: navigate1, pathname: '/apps/appId/test', basename: '/apps/appId' });
expect(navigate1).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({ activeKey: 'tabId', navigate: navigate2, pathname: '/apps/appId/test/', basename: '/apps/appId' });
expect(navigate2).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate3,
pathname: '/apps/appId/test/tabs/oldTabId',
basename: '/apps/appId',
});
expect(navigate3).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate4,
pathname: '/apps/appId/test/tabs/oldTabId/',
basename: '/apps/appId',
});
expect(navigate4).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate5,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/tabs/tab2',
basename: '/apps/appId',
});
expect(navigate5).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate6,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/tabs/tab2/',
basename: '/apps/appId',
});
expect(navigate6).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate7,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId',
basename: '/apps/appId',
});
expect(navigate7).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate8,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/',
basename: '/apps/appId',
});
expect(navigate8).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
});
it('navigateToTab with basename "/apps/appId/"', () => {
const navigate1 = vi.fn();
const navigate2 = vi.fn();
const navigate3 = vi.fn();
const navigate4 = vi.fn();
const navigate5 = vi.fn();
const navigate6 = vi.fn();
const navigate7 = vi.fn();
const navigate8 = vi.fn();
navigateToTab({ activeKey: 'tabId', navigate: navigate1, pathname: '/apps/appId/test', basename: '/apps/appId/' });
expect(navigate1).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({ activeKey: 'tabId', navigate: navigate2, pathname: '/apps/appId/test/', basename: '/apps/appId/' });
expect(navigate2).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate3,
pathname: '/apps/appId/test/tabs/oldTabId',
basename: '/apps/appId/',
});
expect(navigate3).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate4,
pathname: '/apps/appId/test/tabs/oldTabId/',
basename: '/apps/appId/',
});
expect(navigate4).toBeCalledWith('/test/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate5,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/tabs/tab2',
basename: '/apps/appId/',
});
expect(navigate5).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate6,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/tabs/tab2/',
basename: '/apps/appId/',
});
expect(navigate6).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate7,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId',
basename: '/apps/appId/',
});
expect(navigate7).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
navigateToTab({
activeKey: 'tabId',
navigate: navigate8,
pathname: '/apps/appId/test/tabs/tab1/pages/pageId/',
basename: '/apps/appId/',
});
expect(navigate8).toBeCalledWith('/test/tabs/tab1/pages/pageId/tabs/tabId', { replace: true });
});
});

View File

@ -8,57 +8,32 @@
*/
import { connect, mapReadPretty } from '@formily/react';
import React, { useMemo } from 'react';
import React from 'react';
import { DatePicker } from '../date-picker';
import dayjs from 'dayjs';
const toValue = (value: any, accuracy) => {
if (value) {
return timestampToDate(value, accuracy);
}
return null;
};
function timestampToDate(timestamp, accuracy = 'millisecond') {
if (accuracy === 'second') {
timestamp *= 1000; // 如果精确度是秒级则将时间戳乘以1000转换为毫秒级
}
return dayjs(timestamp);
}
function getTimestamp(date, accuracy = 'millisecond') {
if (accuracy === 'second') {
return dayjs(date).unix();
} else {
return dayjs(date).valueOf(); // 默认返回毫秒级时间戳
}
}
interface UnixTimestampProps {
value?: number;
accuracy?: 'millisecond' | 'second';
value?: any;
onChange?: (value: number) => void;
}
export const UnixTimestamp = connect(
(props: UnixTimestampProps) => {
const { value, onChange, accuracy = 'second' } = props;
const v = useMemo(() => toValue(value, accuracy), [value, accuracy]);
const { value, onChange } = props;
return (
<DatePicker
{...props}
value={v}
value={value}
onChange={(v: any) => {
if (onChange) {
onChange(getTimestamp(v, accuracy));
onChange(v);
}
}}
/>
);
},
mapReadPretty((props) => {
const { value, accuracy = 'second' } = props;
const v = useMemo(() => toValue(value, accuracy), [value, accuracy]);
return <DatePicker.ReadPretty {...props} value={v} />;
const { value } = props;
return <DatePicker.ReadPretty {...props} value={value} />;
}),
);

View File

@ -13,11 +13,9 @@ import { UnixTimestamp } from '@nocobase/client';
describe('UnixTimestamp', () => {
it('renders without errors', async () => {
const { container } = await renderAppOptions({
Component: UnixTimestamp,
props: {
accuracy: 'millisecond',
},
value: 0,
Component: UnixTimestamp as any,
props: {},
value: null,
});
expect(container).toMatchInlineSnapshot(`
<div>
@ -69,78 +67,10 @@ describe('UnixTimestamp', () => {
`);
});
it('millisecond', async () => {
await renderAppOptions({
Component: UnixTimestamp,
value: 1712819630000,
props: {
accuracy: 'millisecond',
},
});
await waitFor(() => {
expect(screen.getByRole('textbox')).toHaveValue('2024-04-11');
});
});
it('second', async () => {
await renderAppOptions({
Component: UnixTimestamp,
value: 1712819630,
props: {
accuracy: 'second',
},
});
await waitFor(() => {
expect(screen.getByRole('textbox')).toHaveValue('2024-04-11');
});
});
it('string', async () => {
await renderAppOptions({
Component: UnixTimestamp,
value: '2024-04-11',
props: {
accuracy: 'millisecond',
},
});
await waitFor(() => {
expect(screen.getByRole('textbox')).toHaveValue('2024-04-11');
});
});
it('change', async () => {
const onChange = vitest.fn();
await renderAppOptions({
Component: UnixTimestamp,
value: '2024-04-11',
onChange,
props: {
accuracy: 'millisecond',
},
});
await userEvent.click(screen.getByRole('textbox'));
await waitFor(() => {
expect(screen.queryByRole('table')).toBeInTheDocument();
});
await userEvent.click(document.querySelector('td[title="2024-04-12"]'));
await waitFor(() => {
expect(screen.getByRole('textbox')).toHaveValue('2024-04-12');
});
expect(onChange).toBeCalledWith(1712880000000);
});
it('read pretty', async () => {
const { container } = await renderReadPrettyApp({
Component: UnixTimestamp,
Component: UnixTimestamp as any,
value: '2024-04-11',
props: {
accuracy: 'millisecond',
},
});
expect(screen.getByText('2024-04-11')).toBeInTheDocument();

View File

@ -34,7 +34,7 @@ export function SchemaSettingsRenderEngine() {
return (
<SchemaSettingsSelectItem
key="render-template"
title={t('Set Template Engine')}
title={t('Template engine')}
options={options}
value={field.decoratorProps.engine || 'string'}
onChange={(engine) => {

View File

@ -0,0 +1,42 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Database, mockDatabase } from '@nocobase/database';
describe('date only', () => {
let db: Database;
beforeEach(async () => {
db = mockDatabase({
timezone: '+08:00',
});
await db.clean({ drop: true });
});
afterEach(async () => {
await db.close();
});
it('should set date field with dateOnly', async () => {
db.collection({
name: 'tests',
fields: [{ name: 'date1', type: 'dateOnly' }],
});
await db.sync();
const item = await db.getRepository('tests').create({
values: {
date1: '2023-03-24',
},
});
expect(item.get('date1')).toBe('2023-03-24');
});
});

View File

@ -11,6 +11,69 @@ import { mockDatabase } from '../';
import { Database } from '../../database';
import { Repository } from '../../repository';
describe('timezone', () => {
let db: Database;
beforeEach(async () => {
db = mockDatabase({
timezone: '+08:00',
});
await db.clean({ drop: true });
});
afterEach(async () => {
await db.close();
});
describe('timezone', () => {
test('custom', async () => {
db.collection({
name: 'tests',
timestamps: false,
fields: [{ name: 'date1', type: 'date', timezone: '+06:00' }],
});
await db.sync();
const repository = db.getRepository('tests');
const instance = await repository.create({ values: { date1: '2023-03-24 00:00:00' } });
const date1 = instance.get('date1');
expect(date1.toISOString()).toEqual('2023-03-23T18:00:00.000Z');
});
test('client', async () => {
db.collection({
name: 'tests',
timestamps: false,
fields: [{ name: 'date1', type: 'date', timezone: 'client' }],
});
await db.sync();
const repository = db.getRepository('tests');
const instance = await repository.create({
values: { date1: '2023-03-24 01:00:00' },
context: {
timezone: '+01:00',
},
});
const date1 = instance.get('date1');
expect(date1.toISOString()).toEqual('2023-03-24T00:00:00.000Z');
});
test('server', async () => {
db.collection({
name: 'tests',
fields: [{ name: 'date1', type: 'date', timezone: 'server' }],
});
await db.sync();
const repository = db.getRepository('tests');
const instance = await repository.create({ values: { date1: '2023-03-24 08:00:00' } });
const date1 = instance.get('date1');
expect(date1.toISOString()).toEqual('2023-03-24T00:00:00.000Z');
});
});
});
describe('date-field', () => {
let db: Database;
let repository: Repository;
@ -30,6 +93,71 @@ describe('date-field', () => {
await db.close();
});
it('should set default to current time', async () => {
const c1 = db.collection({
name: 'test11',
fields: [
{
name: 'date1',
type: 'date',
defaultToCurrentTime: true,
},
],
});
await db.sync();
const instance = await c1.repository.create({});
const date1 = instance.get('date1');
expect(date1).toBeDefined();
});
it('should set to current time when update', async () => {
const c1 = db.collection({
name: 'test11',
fields: [
{
name: 'date1',
type: 'date',
onUpdateToCurrentTime: true,
},
{
name: 'title',
type: 'string',
},
],
});
await db.sync();
const instance = await c1.repository.create({
values: {
title: 'test',
},
});
const date1Val = instance.get('date1');
expect(date1Val).toBeDefined();
console.log('update');
await c1.repository.update({
values: {
title: 'test2',
},
filter: {
id: instance.get('id'),
},
});
await instance.reload();
const date1Val2 = instance.get('date1');
expect(date1Val2).toBeDefined();
expect(date1Val2.getTime()).toBeGreaterThan(date1Val.getTime());
});
test('create', async () => {
const createExpectToBe = async (key, actual, expected) => {
const instance = await repository.create({
values: {
@ -39,7 +167,6 @@ describe('date-field', () => {
return expect(instance.get(key).toISOString()).toEqual(expected);
};
test('create', async () => {
// sqlite 时区不能自定义,只有 +00:00postgres 和 mysql 可以自定义 DB_TIMEZONE
await createExpectToBe('date1', '2023-03-24', '2023-03-24T00:00:00.000Z');
await createExpectToBe('date1', '2023-03-24T16:00:00.000Z', '2023-03-24T16:00:00.000Z');

View File

@ -0,0 +1,86 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { Database, mockDatabase } from '@nocobase/database';
import moment from 'moment';
describe('unix timestamp field', () => {
let db: Database;
beforeEach(async () => {
db = mockDatabase();
await db.clean({ drop: true });
});
afterEach(async () => {
await db.close();
});
it('should set default to current time', async () => {
const c1 = db.collection({
name: 'test11',
fields: [
{
name: 'date1',
type: 'unixTimestamp',
defaultToCurrentTime: true,
},
],
});
await db.sync();
const instance = await c1.repository.create({});
const date1 = instance.get('date1');
expect(date1).toBeDefined();
console.log(instance.toJSON());
});
it('should set date value', async () => {
const c1 = db.collection({
name: 'test12',
fields: [
{
name: 'date1',
type: 'unixTimestamp',
},
],
});
await db.sync();
await c1.repository.create({
values: {
date1: '2021-01-01T00:00:00Z',
},
});
const item = await c1.repository.findOne();
const val = item.get('date1');
const date = moment(val).utc().format('YYYY-MM-DD HH:mm:ss');
expect(date).toBe('2021-01-01 00:00:00');
});
describe('timezone', () => {
test('custom', async () => {
db.collection({
name: 'tests',
timestamps: false,
fields: [{ name: 'date1', type: 'unixTimestamp', timezone: '+06:00' }],
});
await db.sync();
const repository = db.getRepository('tests');
const instance = await repository.create({ values: { date1: '2023-03-24 00:00:00' } });
const date1 = instance.get('date1');
expect(date1.toISOString()).toEqual('2023-03-23T18:00:00.000Z');
});
});
});

View File

@ -34,7 +34,6 @@ import {
import { SequelizeStorage, Umzug } from 'umzug';
import { Collection, CollectionOptions, RepositoryType } from './collection';
import { CollectionFactory } from './collection-factory';
import { CollectionGroupManager } from './collection-group-manager';
import { ImporterReader, ImportFileExtension } from './collection-importer';
import DatabaseUtils from './database-utils';
import ReferencesMap from './features/references-map';
@ -42,7 +41,6 @@ import { referentialIntegrityCheck } from './features/referential-integrity-chec
import { ArrayFieldRepository } from './field-repository/array-field-repository';
import * as FieldTypes from './fields';
import { Field, FieldContext, RelationField } from './fields';
import { checkDatabaseVersion } from './helpers';
import { InheritedCollection } from './inherited-collection';
import InheritanceMap from './inherited-map';
import { InterfaceManager } from './interface-manager';
@ -221,6 +219,9 @@ export class Database extends EventEmitter implements AsyncEmitter {
}
}
// @ts-ignore
opts.rawTimezone = opts.timezone;
if (options.dialect === 'sqlite') {
delete opts.timezone;
} else if (!opts.timezone) {
@ -851,7 +852,8 @@ export class Database extends EventEmitter implements AsyncEmitter {
* @internal
*/
async checkVersion() {
return await checkDatabaseVersion(this);
return true;
// return await checkDatabaseVersion(this);
}
/**

View File

@ -10,8 +10,14 @@
import { DataTypes } from 'sequelize';
import { BaseColumnFieldOptions, Field } from './field';
const datetimeRegex = /^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/;
function isValidDatetime(str) {
return datetimeRegex.test(str);
}
export class DateField extends Field {
get dataType() {
get dataType(): any {
return DataTypes.DATE(3);
}
@ -33,6 +39,59 @@ export class DateField extends Field {
return props.gmt;
}
init() {
const { name, defaultToCurrentTime, onUpdateToCurrentTime, timezone } = this.options;
this.resolveTimeZone = (context) => {
// @ts-ignore
const serverTimeZone = this.database.options.rawTimezone;
if (timezone === 'server') {
return serverTimeZone;
}
if (timezone === 'client') {
return context?.timezone || serverTimeZone;
}
if (timezone) {
return timezone;
}
return serverTimeZone;
};
this.beforeSave = async (instance, options) => {
const value = instance.get(name);
if (!value && instance.isNewRecord && defaultToCurrentTime) {
instance.set(name, new Date());
return;
}
if (onUpdateToCurrentTime) {
instance.set(name, new Date());
return;
}
};
}
setter(value, options) {
if (value === null) {
return value;
}
if (value instanceof Date) {
return value;
}
if (typeof value === 'string' && isValidDatetime(value)) {
const dateTimezone = this.resolveTimeZone(options?.context);
const dateString = `${value} ${dateTimezone}`;
return new Date(dateString);
}
return value;
}
bind() {
super.bind();
@ -51,6 +110,13 @@ export class DateField extends Field {
// @ts-ignore
model.refreshAttributes();
}
this.on('beforeSave', this.beforeSave);
}
unbind() {
super.unbind();
this.off('beforeSave', this.beforeSave);
}
}

View File

@ -0,0 +1,21 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { BaseColumnFieldOptions, Field } from './field';
import { DataTypes } from 'sequelize';
export class DateOnlyField extends Field {
get dataType(): any {
return DataTypes.DATEONLY;
}
}
export interface DateOnlyFieldOptions extends BaseColumnFieldOptions {
type: 'dateOnly';
}

View File

@ -56,7 +56,7 @@ export abstract class Field {
return this.options.type;
}
abstract get dataType();
abstract get dataType(): any;
isRelationField() {
return false;
@ -171,11 +171,13 @@ export abstract class Field {
Object.assign(opts, { type: this.database.sequelize.normalizeDataType(this.dataType) });
}
Object.assign(opts, this.additionalSequelizeOptions());
return opts;
}
isSqlite() {
return this.database.sequelize.getDialect() === 'sqlite';
additionalSequelizeOptions() {
return {};
}
typeToString() {

View File

@ -36,6 +36,8 @@ import { UUIDFieldOptions } from './uuid-field';
import { VirtualFieldOptions } from './virtual-field';
import { NanoidFieldOptions } from './nanoid-field';
import { EncryptionField } from './encryption-field';
import { UnixTimestampFieldOptions } from './unix-timestamp-field';
import { DateOnlyFieldOptions } from './date-only-field';
export * from './array-field';
export * from './belongs-to-field';
@ -43,6 +45,7 @@ export * from './belongs-to-many-field';
export * from './boolean-field';
export * from './context-field';
export * from './date-field';
export * from './date-only-field';
export * from './field';
export * from './has-many-field';
export * from './has-one-field';
@ -61,6 +64,7 @@ export * from './uuid-field';
export * from './virtual-field';
export * from './nanoid-field';
export * from './encryption-field';
export * from './unix-timestamp-field';
export type FieldOptions =
| BaseFieldOptions
@ -81,6 +85,8 @@ export type FieldOptions =
| SetFieldOptions
| TimeFieldOptions
| DateFieldOptions
| DateOnlyFieldOptions
| UnixTimestampFieldOptions
| UidFieldOptions
| UUIDFieldOptions
| NanoidFieldOptions

View File

@ -0,0 +1,60 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import { DataTypes } from 'sequelize';
import { DateField } from './date-field';
import { BaseColumnFieldOptions } from './field';
export class UnixTimestampField extends DateField {
get dataType() {
return DataTypes.BIGINT;
}
additionalSequelizeOptions(): {} {
const { name } = this.options;
let { accuracy } = this.options;
if (this.options?.uiSchema['x-component-props']?.accuracy) {
accuracy = this.options?.uiSchema['x-component-props']?.accuracy;
}
if (!accuracy) {
accuracy = 'second';
}
let rationalNumber = 1000;
if (accuracy === 'millisecond') {
rationalNumber = 1;
}
return {
get() {
const value = this.getDataValue(name);
if (value === null || value === undefined) {
return value;
}
return new Date(value * rationalNumber);
},
set(value) {
if (value === null || value === undefined) {
this.setDataValue(name, value);
} else {
// date to unix timestamp
this.setDataValue(name, Math.floor(new Date(value).getTime() / rationalNumber));
}
},
};
}
}
export interface UnixTimestampFieldOptions extends BaseColumnFieldOptions {
type: 'unix-timestamp';
}

View File

@ -7,7 +7,7 @@
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import lodash, { isPlainObject } from 'lodash';
import lodash from 'lodash';
import { Model as SequelizeModel, ModelStatic } from 'sequelize';
import { Collection } from './collection';
import { Database } from './database';
@ -30,7 +30,8 @@ interface JSONTransformerOptions {
export class Model<TModelAttributes extends {} = any, TCreationAttributes extends {} = TModelAttributes>
extends SequelizeModel<TModelAttributes, TCreationAttributes>
implements IModel {
implements IModel
{
public static database: Database;
public static collection: Collection;
@ -49,6 +50,21 @@ export class Model<TModelAttributes extends {} = any, TCreationAttributes extend
return await runner.runSync(options);
}
static callSetters(values, options) {
// map values
const result = {};
for (const key of Object.keys(values)) {
const field = this.collection.getField(key);
if (field && field.setter) {
result[key] = field.setter.call(field, values[key], options, values, key);
} else {
result[key] = values[key];
}
}
return result;
}
// TODO
public toChangedWithAssociations() {
// @ts-ignore

View File

@ -573,7 +573,7 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
underscored: this.collection.options.underscored,
});
const values = guard.sanitize(options.values || {});
const values = (this.model as typeof Model).callSetters(guard.sanitize(options.values || {}), options);
const instance = await this.model.create<any>(values, {
...options,
@ -645,7 +645,7 @@ export class Repository<TModelAttributes extends {} = any, TCreationAttributes e
const guard = UpdateGuard.fromOptions(this.model, { ...options, underscored: this.collection.options.underscored });
const values = guard.sanitize(options.values);
const values = (this.model as typeof Model).callSetters(guard.sanitize(options.values || {}), options);
// NOTE:
// 1. better to be moved to separated API like bulkUpdate/updateMany

View File

@ -18,8 +18,8 @@ const postgres = {
name: 'string',
smallint: ['integer', 'sort'],
integer: ['integer', 'sort'],
bigint: ['bigInt', 'sort'],
integer: ['integer', 'unixTimestamp', 'sort'],
bigint: ['bigInt', 'unixTimestamp', 'sort'],
decimal: 'decimal',
numeric: 'float',
real: 'float',
@ -61,11 +61,11 @@ const mysql = {
text: 'text',
mediumtext: 'text',
longtext: 'text',
int: ['integer', 'sort'],
'int unsigned': ['integer', 'sort'],
integer: ['integer', 'sort'],
bigint: ['bigInt', 'sort'],
'bigint unsigned': ['bigInt', 'sort'],
int: ['integer', 'unixTimestamp', 'sort'],
'int unsigned': ['integer', 'unixTimestamp', 'sort'],
integer: ['integer', 'unixTimestamp', 'sort'],
bigint: ['bigInt', 'unixTimestamp', 'sort'],
'bigint unsigned': ['bigInt', 'unixTimestamp', 'sort'],
float: 'float',
double: 'float',
boolean: 'boolean',

View File

@ -216,23 +216,20 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
* @internal
*/
public perfHistograms = new Map<string, RecordableHistogram>();
protected plugins = new Map<string, Plugin>();
protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance();
protected _started: Date | null = null;
private _authenticated = false;
private _maintaining = false;
private _maintainingCommandStatus: MaintainingCommandStatus;
private _maintainingStatusBeforeCommand: MaintainingCommandStatus | null;
private _actionCommand: Command;
/**
* @internal
*/
public pubSubManager: PubSubManager;
public syncMessageManager: SyncMessageManager;
public requestLogger: Logger;
protected plugins = new Map<string, Plugin>();
protected _appSupervisor: AppSupervisor = AppSupervisor.getInstance();
private _authenticated = false;
private _maintaining = false;
private _maintainingCommandStatus: MaintainingCommandStatus;
private _maintainingStatusBeforeCommand: MaintainingCommandStatus | null;
private _actionCommand: Command;
private sqlLogger: Logger;
protected _logger: SystemLogger;
constructor(public options: ApplicationOptions) {
super();
@ -245,6 +242,8 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
}
}
protected _started: Date | null = null;
/**
* @experimental
*/
@ -252,6 +251,8 @@ export class Application<StateT = DefaultState, ContextT = DefaultContext> exten
return this._started;
}
protected _logger: SystemLogger;
get logger() {
return this._logger;
}

View File

@ -23,7 +23,10 @@ export const BreadcumbTitle = () => {
const dm = useDataSourceManager();
const { displayName } = dm.getDataSource(name) || {};
const { dataSource } = useContext(DataSourceContext);
const dataSourceValue = useMemo(() => dataSource || dm.getDataSource(name), [dataSource, name]);
const dataSourceValue = useMemo(
() => (dataSource && dataSource?.name === name ? dataSource : dm.getDataSource(name)),
[dataSource, name],
);
const items = useMemo(() => {
const status = dataSourceValue?.status;
const option = statusEnum.find((v) => v.value === status);

View File

@ -134,7 +134,7 @@ export const ConfigurationTable = () => {
method: 'post',
});
field.data.loading = false;
setDataSource(data?.data);
setDataSource({ ...data?.data, name });
if (data?.data?.status === 'reloading') {
message.warning(t('Data source synchronization in progress'));
} else if (data?.data?.status === 'loaded') {

View File

@ -28,8 +28,8 @@
"@nocobase/actions": "1.x",
"@nocobase/cache": "1.x",
"@nocobase/client": "1.x",
"@nocobase/plugin-data-source-main": "1.x",
"@nocobase/database": "1.x",
"@nocobase/plugin-data-source-main": "1.x",
"@nocobase/server": "1.x",
"@nocobase/test": "1.x",
"@nocobase/utils": "1.x"

View File

@ -0,0 +1,29 @@
/**
* This file is part of the NocoBase (R) project.
* Copyright (c) 2020-2024 NocoBase Co., Ltd.
* Authors: NocoBase Team.
*
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
* For more information, please refer to: https://www.nocobase.com/agreement.
*/
import React from 'react';
import { Statistic as AntdStatistic } from 'antd';
export const Statistic: React.FC<any> = (props: any) => {
const { link, ...options } = props;
return (
<div
onClick={() => {
if (link) {
window.open(link, '__blank');
}
}}
style={{
cursor: link ? 'pointer' : 'auto',
}}
>
<AntdStatistic {...options} />
</div>
);
};

View File

@ -8,16 +8,16 @@
*/
import { AntdChart } from './antd';
import { Statistic as AntdStatistic } from 'antd';
import { lang } from '../../locale';
import { ChartType, RenderProps } from '../chart';
import { Statistic as C } from './components/Statistic';
export class Statistic extends AntdChart {
constructor() {
super({
name: 'statistic',
title: 'Statistic',
Component: AntdStatistic,
Component: C,
config: [
{
property: 'field',
@ -33,6 +33,14 @@ export class Statistic extends AntdChart {
'x-component': 'Input',
},
},
{
link: {
title: lang('Link'),
type: 'string',
'x-decorator': 'FormItem',
'x-component': 'Input',
},
},
],
});
}

View File

@ -130,7 +130,7 @@ export const KanbanBlockInitializer = ({
return (
<DataBlockInitializer
{...itemConfig}
componentType={`Calendar`}
componentType={`Kanban`}
icon={<FormOutlined />}
onCreateBlockSchema={async (options) => {
if (createBlockSchema) {

View File

@ -15,7 +15,7 @@
"antd": "5.x",
"antd-style": "3.x",
"async-mutex": "^0.3.2",
"mysql2": "^2.3.3",
"mysql2": "^3.11.0",
"pg": "^8.7.3",
"react": "18.x",
"react-i18next": "^11.15.1",

View File

@ -43,9 +43,9 @@ function DynamicExpression({ value, onChange }) {
}
export default class extends Instruction {
title = `{{t("Dynamic Calculation", { ns: "${NAMESPACE}" })}}`;
title = `{{t("Dynamic expression calculation", { ns: "${NAMESPACE}" })}}`;
type = 'dynamic-calculation';
group = 'extended';
group = 'calculation';
description = `{{t("Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression. The expression is dynamic one from an expression collections.", { ns: "${NAMESPACE}" })}}`;
fieldset = {
expression: {

View File

@ -1,6 +1,6 @@
{
"Expression": "表达式",
"Dynamic Calculation": "动态表达式计算",
"Dynamic expression calculation": "动态表达式计算",
"Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression. The expression is dynamic one from an expression collections.": "基于计算引擎计算表达式并获取值作为结果。可以在表达式中使用上游节点的变量。表达式是从表达式表中动态获取的。",
"Select dynamic expression": "选择动态表达式",
"Select the dynamic expression queried from the upstream node. You need to query it from an expression collection.": "从上游节点中选择查询出来的动态表达式。你需要从动态表达式类型的数据表中查询。",

View File

@ -38,6 +38,7 @@ export function AddButton(props: AddButtonProps) {
const groups = useMemo(() => {
return [
{ key: 'control', label: `{{t("Control", { ns: "${NAMESPACE}" })}}` },
{ key: 'calculation', label: `{{t("Calculation", { ns: "${NAMESPACE}" })}}` },
{ key: 'collection', label: `{{t("Collection operations", { ns: "${NAMESPACE}" })}}` },
{ key: 'manual', label: `{{t("Manual", { ns: "${NAMESPACE}" })}}` },
{ key: 'extended', label: `{{t("Extended types", { ns: "${NAMESPACE}" })}}` },

View File

@ -20,7 +20,7 @@ import { Instruction } from '.';
export default class extends Instruction {
title = `{{t("Calculation", { ns: "${NAMESPACE}" })}}`;
type = 'calculation';
group = 'control';
group = 'calculation';
description = `{{t("Calculate an expression based on a calculation engine and obtain a value as the result. Variables in the upstream nodes can be used in the expression.", { ns: "${NAMESPACE}" })}}`;
fieldset = {
engine: {

465
yarn.lock
View File

@ -21,17 +21,6 @@
query-string "^6.9.0"
tslib "^2.4.1"
"@alicloud/captcha20230305@^1.1.3":
version "1.1.3"
resolved "https://registry.npmmirror.com/@alicloud/captcha20230305/-/captcha20230305-1.1.3.tgz#e6f27c16a1dfb9e22689b867bbc1a3d5e91f82e7"
integrity sha512-AUyW7z6xgtC+Khp0BuzerirKLuxCQcovwcsvXPUib5kCxsrKvWuVWrGyTHP9rIpA1pE9ijOlDw8domtgPlY/KQ==
dependencies:
"@alicloud/endpoint-util" "^0.0.1"
"@alicloud/openapi-client" "^0.4.7"
"@alicloud/openapi-util" "^0.3.2"
"@alicloud/tea-typescript" "^1.7.1"
"@alicloud/tea-util" "^1.4.7"
"@alicloud/credentials@^2":
version "2.3.0"
resolved "https://registry.npmmirror.com/@alicloud/credentials/-/credentials-2.3.0.tgz#941233a07ba74cd2fdaa3f6a5d2a3cca5a10c184"
@ -42,19 +31,6 @@
ini "^1.3.5"
kitx "^2.0.0"
"@alicloud/dingtalk@^2.1.23":
version "2.1.27"
resolved "https://registry.npmmirror.com/@alicloud/dingtalk/-/dingtalk-2.1.27.tgz#fc4785c8c8edde737d82620272fa8b6790724b4d"
integrity sha512-xmXFElqgZBbjH2Ct8UJLQut2TwX2OutPhtdIAjIOkOWM5F6w9MOe6xUv+k+7Jnl6O/35g41OVVMmIK8QJrDSMQ==
dependencies:
"@alicloud/endpoint-util" "^0.0.1"
"@alicloud/gateway-dingtalk" "^1.0.2"
"@alicloud/gateway-spi" "^0.0.8"
"@alicloud/openapi-client" "^0.4.9"
"@alicloud/openapi-util" "^0.3.2"
"@alicloud/tea-typescript" "^1.7.1"
"@alicloud/tea-util" "^1.4.8"
"@alicloud/dysmsapi20170525@2.0.17":
version "2.0.17"
resolved "https://registry.npmmirror.com/@alicloud/dysmsapi20170525/-/dysmsapi20170525-2.0.17.tgz#a350a443f52456b823772345dd57cc5fe2e6c8da"
@ -74,15 +50,6 @@
"@alicloud/tea-typescript" "^1.5.1"
kitx "^2.0.0"
"@alicloud/gateway-dingtalk@^1.0.2":
version "1.0.2"
resolved "https://registry.npmmirror.com/@alicloud/gateway-dingtalk/-/gateway-dingtalk-1.0.2.tgz#3970f07324c59935892f5b9abce66e6c2ae29dfc"
integrity sha512-T8ml6kth/nCRthrtHIYnCYv7+q/41SnJaR8c99491azNSPcmMmgxis5ujYIl5irKm0cvoOCCjI9EWUFb2Tx7JA==
dependencies:
"@alicloud/gateway-spi" "^0.0.8"
"@alicloud/tea-typescript" "^1.7.1"
"@alicloud/tea-util" "^1.4.5"
"@alicloud/gateway-spi@^0.0.8":
version "0.0.8"
resolved "https://registry.npmmirror.com/@alicloud/gateway-spi/-/gateway-spi-0.0.8.tgz#1d251986ed40d8b98690dcac8128fec0c56f0f53"
@ -114,18 +81,6 @@
"@alicloud/tea-util" "^1.4.7"
"@alicloud/tea-xml" "0.0.2"
"@alicloud/openapi-client@^0.4.7", "@alicloud/openapi-client@^0.4.8", "@alicloud/openapi-client@^0.4.9":
version "0.4.9"
resolved "https://registry.npmmirror.com/@alicloud/openapi-client/-/openapi-client-0.4.9.tgz#b5627a889e48ad5223bc6fe26e2361bbff1cace0"
integrity sha512-07LzSvIHrhFmk1yOtDQsrtFU8woj29s80TzG7Bv15b7Uo+Q/3EcyoCZU4phig1FM7B0e+2ZWnTnVnKG3FgXvig==
dependencies:
"@alicloud/credentials" "^2"
"@alicloud/gateway-spi" "^0.0.8"
"@alicloud/openapi-util" "^0.3.2"
"@alicloud/tea-typescript" "^1.7.1"
"@alicloud/tea-util" "^1.4.8"
"@alicloud/tea-xml" "0.0.3"
"@alicloud/openapi-util@^0.2.7", "@alicloud/openapi-util@^0.2.9":
version "0.2.9"
resolved "https://registry.npmmirror.com/@alicloud/openapi-util/-/openapi-util-0.2.9.tgz#2379cd81f993dcab32066a2b892ddcbdd266d51c"
@ -146,7 +101,7 @@
kitx "^2.1.0"
sm3 "^1.0.3"
"@alicloud/tea-typescript@^1", "@alicloud/tea-typescript@^1.5.1", "@alicloud/tea-typescript@^1.5.3", "@alicloud/tea-typescript@^1.7.1", "@alicloud/tea-typescript@^1.8.0":
"@alicloud/tea-typescript@^1", "@alicloud/tea-typescript@^1.5.1", "@alicloud/tea-typescript@^1.5.3", "@alicloud/tea-typescript@^1.7.1":
version "1.8.0"
resolved "https://registry.npmmirror.com/@alicloud/tea-typescript/-/tea-typescript-1.8.0.tgz#aa9b04b6ee53e1b22aa51e224a950ea5bcd966e9"
integrity sha512-CWXWaquauJf0sW30mgJRVu9aaXyBth5uMBCUc+5vKTK1zlgf3hIqRUjJZbjlwHwQ5y9anwcu18r48nOZb7l2QQ==
@ -170,14 +125,6 @@
"@alicloud/tea-typescript" "^1.5.1"
kitx "^2.0.0"
"@alicloud/tea-util@^1.4.5", "@alicloud/tea-util@^1.4.8":
version "1.4.8"
resolved "https://registry.npmmirror.com/@alicloud/tea-util/-/tea-util-1.4.8.tgz#5948a9d14a64edeb244fcbbb065b1f3c018deca7"
integrity sha512-CPmRUAWhUMewZXLVZ8HTCrqRzzcT6F3o/1sB3IY27oU8RLjFj3FMpZe423pJoC/noNXo4Ja3FTTEFF5k8asQBw==
dependencies:
"@alicloud/tea-typescript" "^1.5.1"
kitx "^2.0.0"
"@alicloud/tea-xml@0.0.2":
version "0.0.2"
resolved "https://registry.npmmirror.com/@alicloud/tea-xml/-/tea-xml-0.0.2.tgz#7c97a38255d5e4f009c437facd3a2afc0ef17f45"
@ -187,15 +134,6 @@
"@types/xml2js" "^0.4.5"
xml2js "^0.4.22"
"@alicloud/tea-xml@0.0.3":
version "0.0.3"
resolved "https://registry.npmmirror.com/@alicloud/tea-xml/-/tea-xml-0.0.3.tgz#14561d4dde59da1d5eaf87e898e26a68cea073c4"
integrity sha512-+/9GliugjrLglsXVrd1D80EqqKgGpyA0eQ6+1ZdUOYCaRguaSwz44trX3PaxPu/HhIPJg9PsGQQ3cSLXWZjbAA==
dependencies:
"@alicloud/tea-typescript" "^1"
"@types/xml2js" "^0.4.5"
xml2js "^0.6.0"
"@amap/amap-jsapi-loader@^1.0.1":
version "1.0.1"
resolved "https://registry.npmmirror.com/@amap/amap-jsapi-loader/-/amap-jsapi-loader-1.0.1.tgz#9ec4b4d5d2467eac451f6c852e35db69e9f9f0c0"
@ -4216,77 +4154,6 @@
methods "^1.1.2"
path-to-regexp "^6.1.0"
"@ldapjs/asn1@2.0.0", "@ldapjs/asn1@^2.0.0":
version "2.0.0"
resolved "https://registry.npmmirror.com/@ldapjs/asn1/-/asn1-2.0.0.tgz#e25fa38fcf0b4310275d6a5a05fe4603efef5eb4"
integrity sha512-G9+DkEOirNgdPmD0I8nu57ygQJKOOgFEMKknEuQvIHbGLwP3ny1mY+OTUYLCbCaGJP4sox5eYgBJRuSUpnAddA==
"@ldapjs/asn1@^1.2.0":
version "1.2.0"
resolved "https://registry.npmmirror.com/@ldapjs/asn1/-/asn1-1.2.0.tgz#5e99338fb39ff518c205827bec0fd9a6bf6b42db"
integrity sha512-KX/qQJ2xxzvO2/WOvr1UdQ+8P5dVvuOLk/C9b1bIkXxZss8BaR28njXdPgFCpj5aHaf1t8PmuVnea+N9YG9YMw==
"@ldapjs/attribute@1.0.0", "@ldapjs/attribute@^1.0.0":
version "1.0.0"
resolved "https://registry.npmmirror.com/@ldapjs/attribute/-/attribute-1.0.0.tgz#d81d626080584c1c80ef300a214458f9f78a8abb"
integrity sha512-ptMl2d/5xJ0q+RgmnqOi3Zgwk/TMJYG7dYMC0Keko+yZU6n+oFM59MjQOUht5pxJeS4FWrImhu/LebX24vJNRQ==
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/protocol" "^1.2.1"
process-warning "^2.1.0"
"@ldapjs/change@^1.0.0":
version "1.0.0"
resolved "https://registry.npmmirror.com/@ldapjs/change/-/change-1.0.0.tgz#34818a3a31cb337d3b90ab853bb7fa90517c2c4f"
integrity sha512-EOQNFH1RIku3M1s0OAJOzGfAohuFYXFY4s73wOhRm4KFGhmQQ7MChOh2YtYu9Kwgvuq1B0xKciXVzHCGkB5V+Q==
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/attribute" "1.0.0"
"@ldapjs/controls@^2.1.0":
version "2.1.0"
resolved "https://registry.npmmirror.com/@ldapjs/controls/-/controls-2.1.0.tgz#28449cd4352f9389fb52fbf699cfa62f3e8762e6"
integrity sha512-2pFdD1yRC9V9hXfAWvCCO2RRWK9OdIEcJIos/9cCVP9O4k72BY1bLDQQ4KpUoJnl4y/JoD4iFgM+YWT3IfITWw==
dependencies:
"@ldapjs/asn1" "^1.2.0"
"@ldapjs/protocol" "^1.2.1"
"@ldapjs/dn@^1.1.0":
version "1.1.0"
resolved "https://registry.npmmirror.com/@ldapjs/dn/-/dn-1.1.0.tgz#3687c86d658d2e10aedc2c65a1ef40155dd7370b"
integrity sha512-R72zH5ZeBj/Fujf/yBu78YzpJjJXG46YHFo5E4W1EqfNpo1UsVPqdLrRMXeKIsJT3x9dJVIfR6OpzgINlKpi0A==
dependencies:
"@ldapjs/asn1" "2.0.0"
process-warning "^2.1.0"
"@ldapjs/filter@^2.1.1":
version "2.1.1"
resolved "https://registry.npmmirror.com/@ldapjs/filter/-/filter-2.1.1.tgz#34f4774aa17086ed0186afe11c698f13dd586d56"
integrity sha512-TwPK5eEgNdUO1ABPBUQabcZ+h9heDORE4V9WNZqCtYLKc06+6+UAJ3IAbr0L0bYTnkkWC/JEQD2F+zAFsuikNw==
dependencies:
"@ldapjs/asn1" "2.0.0"
"@ldapjs/protocol" "^1.2.1"
process-warning "^2.1.0"
"@ldapjs/messages@^1.3.0":
version "1.3.0"
resolved "https://registry.npmmirror.com/@ldapjs/messages/-/messages-1.3.0.tgz#dea3c35de6e768e54abd3c7fbaee151d3d01f386"
integrity sha512-K7xZpXJ21bj92jS35wtRbdcNrwmxAtPwy4myeh9duy/eR3xQKvikVycbdWVzkYEAVE5Ce520VXNOwCHjomjCZw==
dependencies:
"@ldapjs/asn1" "^2.0.0"
"@ldapjs/attribute" "^1.0.0"
"@ldapjs/change" "^1.0.0"
"@ldapjs/controls" "^2.1.0"
"@ldapjs/dn" "^1.1.0"
"@ldapjs/filter" "^2.1.1"
"@ldapjs/protocol" "^1.2.1"
process-warning "^2.2.0"
"@ldapjs/protocol@^1.2.1":
version "1.2.1"
resolved "https://registry.npmmirror.com/@ldapjs/protocol/-/protocol-1.2.1.tgz#d58d371d6958f28095e8de23b35341bcaba55cf3"
integrity sha512-O89xFDLW2gBoZWNXuXpBSM32/KealKCTb3JGtJdtUQc7RjAk8XzrRgyz02cPAwGKwKPxy0ivuC7UP9bmN87egQ==
"@lerna/add@4.0.0":
version "4.0.0"
resolved "https://registry.npmmirror.com/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f"
@ -5008,23 +4875,6 @@
dependencies:
eslint-scope "5.1.1"
"@node-saml/node-saml@^4.0.2":
version "4.0.5"
resolved "https://registry.npmmirror.com/@node-saml/node-saml/-/node-saml-4.0.5.tgz#039e387095b54639b06df62b1b4a6d8941c6d907"
integrity sha512-J5DglElbY1tjOuaR1NPtjOXkXY5bpUhDoKVoeucYN98A3w4fwgjIOPqIGcb6cQsqFq2zZ6vTCeKn5C/hvefSaw==
dependencies:
"@types/debug" "^4.1.7"
"@types/passport" "^1.0.11"
"@types/xml-crypto" "^1.4.2"
"@types/xml-encryption" "^1.2.1"
"@types/xml2js" "^0.4.11"
"@xmldom/xmldom" "^0.8.6"
debug "^4.3.4"
xml-crypto "^3.0.1"
xml-encryption "^3.0.2"
xml2js "^0.5.0"
xmlbuilder "^15.1.1"
"@nodelib/fs.scandir@2.1.5":
version "2.1.5"
resolved "https://registry.npmmirror.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5"
@ -5264,15 +5114,6 @@
dependencies:
"@opentelemetry/semantic-conventions" "1.19.0"
"@opentelemetry/exporter-prometheus@^0.46.0":
version "0.46.0"
resolved "https://registry.npmmirror.com/@opentelemetry/exporter-prometheus/-/exporter-prometheus-0.46.0.tgz#c411a1e8a5266f9f3ddc44a088a538c3c1ee4830"
integrity sha512-AXcoCHG31K2PLGizlJJWcfQqZsGfUZkT7ik6C8VJu7U2Cenk0Xhvd3rO+vVNSSjP1+LHkP4MQtqEXpIZttw5cw==
dependencies:
"@opentelemetry/core" "1.19.0"
"@opentelemetry/resources" "1.19.0"
"@opentelemetry/sdk-metrics" "1.19.0"
"@opentelemetry/instrumentation@^0.46.0":
version "0.46.0"
resolved "https://registry.npmmirror.com/@opentelemetry/instrumentation/-/instrumentation-0.46.0.tgz#a8a252306f82e2eace489312798592a14eb9830e"
@ -5306,7 +5147,7 @@
"@opentelemetry/core" "1.19.0"
"@opentelemetry/semantic-conventions" "1.19.0"
"@opentelemetry/sdk-metrics@1.19.0", "@opentelemetry/sdk-metrics@^1.19.0":
"@opentelemetry/sdk-metrics@^1.19.0":
version "1.19.0"
resolved "https://registry.npmmirror.com/@opentelemetry/sdk-metrics/-/sdk-metrics-1.19.0.tgz#fe8029af29402563eb8dba75a85fc02006ea92c4"
integrity sha512-FiMii40zr0Fmys4F1i8gmuCvbinBnBsDeGBr4FQemOf0iPCLytYQm5AZJ/nn4xSc71IgKBQwTFQRAGJI7JvZ4Q==
@ -6826,7 +6667,7 @@
resolved "https://registry.npmmirror.com/@types/date-arithmetic/-/date-arithmetic-4.1.4.tgz#bdb441f61a916f11af1874a8c2cf787f77ffcb94"
integrity sha512-p9eZ2X9B80iKiTW4ukVj8B4K6q9/+xFtQ5MGYA5HWToY9nL4EkhV9+6ftT2VHpVMEZb5Tv00Iel516bVdO+yRw==
"@types/debug@^4.0.0", "@types/debug@^4.1.7", "@types/debug@^4.1.8":
"@types/debug@^4.0.0", "@types/debug@^4.1.8":
version "4.1.12"
resolved "https://registry.npmmirror.com/@types/debug/-/debug-4.1.12.tgz#a155f21690871953410df4b6b6f53187f0500917"
integrity sha512-vIChWdVG3LG1SMxEvI/AK+FWJthlrqlTu7fbrlywTkkaONwk/UAGaULXRlf8vkzFBLVm0zkMdCquhL5aOjhXPQ==
@ -6903,11 +6744,6 @@
resolved "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.13.tgz#e6e77ea9ecf36564980a861e24e62a095988775e"
integrity sha512-bmrNrgKMOhM3WsafmbGmC+6dsF2Z308vLFsQ3a/bT8X8Sv5clVYpPars/UPq+sAaJP+5OoLAYgwbkS5QEJdLUQ==
"@types/geojson@^7946.0.14":
version "7946.0.14"
resolved "https://registry.npmmirror.com/@types/geojson/-/geojson-7946.0.14.tgz#319b63ad6df705ee2a65a73ef042c8271e696613"
integrity sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==
"@types/glob-stream@*":
version "8.0.2"
resolved "https://registry.npmmirror.com/@types/glob-stream/-/glob-stream-8.0.2.tgz#56234435cd20f9b7b08c993be9267d661f9b914d"
@ -7090,13 +6926,6 @@
"@types/koa-compose" "*"
"@types/node" "*"
"@types/ldapjs@^3.0.6":
version "3.0.6"
resolved "https://registry.npmmirror.com/@types/ldapjs/-/ldapjs-3.0.6.tgz#63aec9036c2acfb0e0b7322df336cda2c37f8bbe"
integrity sha512-E2Tn1ltJDYBsidOT9QG4engaQeQzRQ9aYNxVmjCkD33F7cIeLPgrRDXAYs0O35mK2YDU20c/+ZkNjeAPRGLM0Q==
dependencies:
"@types/node" "*"
"@types/lerna__package@*":
version "5.1.3"
resolved "https://registry.npmmirror.com/@types/lerna__package/-/lerna__package-5.1.3.tgz#3604531e882229dee8e3f2bd8c819c405e2fcb43"
@ -7220,13 +7049,6 @@
resolved "https://registry.npmmirror.com/@types/node/-/node-17.0.45.tgz#2c0fafd78705e7a18b7906b5201a522719dc5190"
integrity sha512-w+tIMs3rq2afQdsPJlODhoUEKzFP1ayaoyl1CcnwtIlsVe7K7bA1NGm4s3PraqTLlXnbIN84zuBlxBWo1u9BLw==
"@types/node@^20.11.17":
version "20.14.8"
resolved "https://registry.npmmirror.com/@types/node/-/node-20.14.8.tgz#45c26a2a5de26c3534a9504530ddb3b27ce031ac"
integrity sha512-DO+2/jZinXfROG7j7WKFn/3C6nFwxy2lLpgLjEXJz+0XKphZlTLJ14mo8Vfg8X5BWN6XjyESXq+LcYdT7tR3bA==
dependencies:
undici-types "~5.26.4"
"@types/nodemailer@6.4.4":
version "6.4.4"
resolved "https://registry.npmmirror.com/@types/nodemailer/-/nodemailer-6.4.4.tgz#c265f7e7a51df587597b3a49a023acaf0c741f4b"
@ -7254,22 +7076,6 @@
resolved "https://registry.npmmirror.com/@types/parse5/-/parse5-6.0.3.tgz#705bb349e789efa06f43f128cef51240753424cb"
integrity sha512-SuT16Q1K51EAVPz1K29DJ/sXjhSQ0zjvsypYJ6tlwVsRV9jwW5Adq2ch8Dq8kDBCkYnELS7N7VNCSB5nC56t/g==
"@types/passport@^1.0.11":
version "1.0.16"
resolved "https://registry.npmmirror.com/@types/passport/-/passport-1.0.16.tgz#5a2918b180a16924c4d75c31254c31cdca5ce6cf"
integrity sha512-FD0qD5hbPWQzaM0wHUnJ/T0BBCJBxCeemtnCwc/ThhTg3x9jfrAcRUmj5Dopza+MfFS9acTe3wk7rcVnRIp/0A==
dependencies:
"@types/express" "*"
"@types/pg@^8.10.9":
version "8.11.6"
resolved "https://registry.npmmirror.com/@types/pg/-/pg-8.11.6.tgz#a2d0fb0a14b53951a17df5197401569fb9c0c54b"
integrity sha512-/2WmmBXHLsfRqzfHW7BNZ8SbYzE8OSk7i3WjFYvfgRHj7S1xj+16Je5fUKv3lVdVzk/zn9TXOqf+avFCFIE0yQ==
dependencies:
"@types/node" "*"
pg-protocol "*"
pg-types "^4.0.1"
"@types/picomatch@*":
version "2.3.3"
resolved "https://registry.npmmirror.com/@types/picomatch/-/picomatch-2.3.3.tgz#be60498568c19e989e43fb39aa84be1ed3655e92"
@ -7510,22 +7316,7 @@
dependencies:
"@types/node" "*"
"@types/xml-crypto@^1.4.2":
version "1.4.6"
resolved "https://registry.npmmirror.com/@types/xml-crypto/-/xml-crypto-1.4.6.tgz#6d1fd7d41c91554f2aed97c2ba273af0388fa5cf"
integrity sha512-A6jEW2FxLZo1CXsRWnZHUX2wzR3uDju2Bozt6rDbSmU/W8gkilaVbwFEVN0/NhnUdMVzwYobWtM6bU1QJJFb7Q==
dependencies:
"@types/node" "*"
xpath "0.0.27"
"@types/xml-encryption@^1.2.1":
version "1.2.4"
resolved "https://registry.npmmirror.com/@types/xml-encryption/-/xml-encryption-1.2.4.tgz#0eceea58c82a89f62c0a2dc383a6461dfc2fe1ba"
integrity sha512-I69K/WW1Dv7j6O3jh13z0X8sLWJRXbu5xnHDl9yHzUNDUBtUoBY058eb5s+x/WG6yZC1h8aKdI2EoyEPjyEh+Q==
dependencies:
"@types/node" "*"
"@types/xml2js@^0.4.11", "@types/xml2js@^0.4.5":
"@types/xml2js@^0.4.5":
version "0.4.14"
resolved "https://registry.npmmirror.com/@types/xml2js/-/xml2js-0.4.14.tgz#5d462a2a7330345e2309c6b549a183a376de8f9a"
integrity sha512-4YnrRemBShWRO2QjvUin8ESA41rH+9nQGLUGZV/1IDhi3SL9OhdpNC/MrulTWuptXKwhx/aDxE7toV0f/ypIXQ==
@ -8218,11 +8009,6 @@
loupe "^2.3.7"
pretty-format "^29.7.0"
"@xmldom/xmldom@^0.8.5", "@xmldom/xmldom@^0.8.6", "@xmldom/xmldom@^0.8.8":
version "0.8.10"
resolved "https://registry.npmmirror.com/@xmldom/xmldom/-/xmldom-0.8.10.tgz#a1337ca426aa61cef9fe15b5b28e340a72f6fa99"
integrity sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==
"@zeit/schemas@2.6.0":
version "2.6.0"
resolved "https://registry.npmmirror.com/@zeit/schemas/-/schemas-2.6.0.tgz#004e8e553b4cd53d538bd38eac7bcbf58a867fe3"
@ -8246,11 +8032,6 @@ abbrev@1:
resolved "https://registry.npmmirror.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8"
integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==
abstract-logging@^2.0.1:
version "2.0.1"
resolved "https://registry.npmmirror.com/abstract-logging/-/abstract-logging-2.0.1.tgz#6b0c371df212db7129b57d2e7fcf282b8bf1c839"
integrity sha512-2BjRTZxTPvheOvGbBslFSYOUkr+SjPtOnrLP33f+VIWLzezQpZcqVg7ja3L4dBXmzzgwT+a029jRx5PCi3JuiA==
accepts@^1.3.5, accepts@~1.3.5:
version "1.3.8"
resolved "https://registry.npmmirror.com/accepts/-/accepts-1.3.8.tgz#0bf0be125b67014adcb0b0921e62db7bffe16b2e"
@ -9287,6 +9068,11 @@ aws-sign2@~0.7.0:
resolved "https://registry.npmmirror.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8"
integrity sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==
aws-ssl-profiles@^1.1.1:
version "1.1.1"
resolved "https://registry.npmmirror.com/aws-ssl-profiles/-/aws-ssl-profiles-1.1.1.tgz#21ef8ad77d753927f6c01b144c5ef4cc4f150cdc"
integrity sha512-+H+kuK34PfMaI9PNU/NSjBKL5hh/KDM9J72kwYeYEm0A8B1AC4fuCy3qsjnA7lxklgyXsB68yn8Z2xoZEjgwCQ==
aws4@^1.8.0:
version "1.12.0"
resolved "https://registry.npmmirror.com/aws4/-/aws4-1.12.0.tgz#ce1c9d143389679e253b314241ea9aa5cec980d3"
@ -9461,13 +9247,6 @@ bach@^1.0.0:
async-settle "^1.0.0"
now-and-later "^2.0.0"
backoff@^2.5.0:
version "2.5.0"
resolved "https://registry.npmmirror.com/backoff/-/backoff-2.5.0.tgz#f616eda9d3e4b66b8ca7fca79f695722c5f8e26f"
integrity sha512-wC5ihrnUXmR2douXmXLCe5O3zg3GKIyvRi/hi58a/XyRxVI+3/yM0PYueQOZXPXQ9pxBislYkw+sF9b7C/RuMA==
dependencies:
precond "0.2"
bail@^2.0.0:
version "2.0.2"
resolved "https://registry.npmmirror.com/bail/-/bail-2.0.2.tgz#d26f5cd8fe5d6f832a31517b9f7c356040ba6d5d"
@ -11202,7 +10981,7 @@ copy-props@^2.0.1:
each-props "^1.3.2"
is-plain-object "^5.0.0"
copy-to-clipboard@3.3.3, copy-to-clipboard@^3.3.1, copy-to-clipboard@^3.3.3:
copy-to-clipboard@^3.3.1, copy-to-clipboard@^3.3.3:
version "3.3.3"
resolved "https://registry.npmmirror.com/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz#55ac43a1db8ae639a4bd99511c148cdd1b83a1b0"
integrity sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==
@ -17053,16 +16832,6 @@ jest-worker@^29.7.0:
merge-stream "^2.0.0"
supports-color "^8.0.0"
jmespath@^0.16.0:
version "0.16.0"
resolved "https://registry.npmmirror.com/jmespath/-/jmespath-0.16.0.tgz#b15b0a85dfd4d930d43e69ed605943c802785076"
integrity sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==
jose@^4.15.5:
version "4.15.7"
resolved "https://registry.npmmirror.com/jose/-/jose-4.15.7.tgz#96ad68d786632bd03c9068aa281810dbbe1b60d8"
integrity sha512-L7ioP+JAuZe8v+T5+zVI9Tx8LtU8BL7NxkyDFVMv+Qr3JW0jSoYDedLtodaXwfqMpeCyx4WXFNyu9tJt4WvC1A==
joycon@^3.1.1:
version "3.1.1"
resolved "https://registry.npmmirror.com/joycon/-/joycon-3.1.1.tgz#bce8596d6ae808f8b68168f5fc69280996894f03"
@ -17252,11 +17021,6 @@ json5@^2.1.2, json5@^2.2.3:
resolved "https://registry.npmmirror.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283"
integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==
jsonata@^2.0.3:
version "2.0.5"
resolved "https://registry.npmmirror.com/jsonata/-/jsonata-2.0.5.tgz#2b3b5098c019b264c4fae061a9cb24d59c7115a2"
integrity sha512-wEse9+QLIIU5IaCgtJCPsFi/H4F3qcikWzF4bAELZiRz08ohfx3Q6CjDRf4ZPF5P/92RI3KIHtb7u3jqPaHXdQ==
jsonc-parser@^3.2.0:
version "3.2.0"
resolved "https://registry.npmmirror.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76"
@ -17290,11 +17054,6 @@ jsonparse@^1.2.0, jsonparse@^1.3.1:
resolved "https://registry.npmmirror.com/jsonparse/-/jsonparse-1.3.1.tgz#3f4dae4a91fac315f71062f8521cc239f1366280"
integrity sha512-POQXvpdL69+CluYsillJ7SUhKvytYjW9vG/GKpnf+xP8UWgYEM/RaMzHHofbALDiKbbP1W8UEYmgGl39WkPZsg==
jsonpath-plus@^7.2.0:
version "7.2.0"
resolved "https://registry.npmmirror.com/jsonpath-plus/-/jsonpath-plus-7.2.0.tgz#7ad94e147b3ed42f7939c315d2b9ce490c5a3899"
integrity sha512-zBfiUPM5nD0YZSBT/o/fbCUlCcepMIdP0CJZxM1+KgA4f2T206f6VAg9e7mX35+KlMaIc5qXW34f3BnwJ3w+RA==
jsonwebtoken@^8.5.1:
version "8.5.1"
resolved "https://registry.npmmirror.com/jsonwebtoken/-/jsonwebtoken-8.5.1.tgz#00e71e0b8df54c2121a1f26137df2280673bcc0d"
@ -17559,26 +17318,6 @@ lcid@^1.0.0:
dependencies:
invert-kv "^1.0.0"
ldapjs@^3.0.7:
version "3.0.7"
resolved "https://registry.npmmirror.com/ldapjs/-/ldapjs-3.0.7.tgz#c69fe2965bc50a747bce834f8183f1f77c3be75d"
integrity sha512-1ky+WrN+4CFMuoekUOv7Y1037XWdjKpu0xAPwSP+9KdvmV9PG+qOKlssDV6a+U32apwxdD3is/BZcWOYzN30cg==
dependencies:
"@ldapjs/asn1" "^2.0.0"
"@ldapjs/attribute" "^1.0.0"
"@ldapjs/change" "^1.0.0"
"@ldapjs/controls" "^2.1.0"
"@ldapjs/dn" "^1.1.0"
"@ldapjs/filter" "^2.1.1"
"@ldapjs/messages" "^1.3.0"
"@ldapjs/protocol" "^1.2.1"
abstract-logging "^2.0.1"
assert-plus "^1.0.0"
backoff "^2.5.0"
once "^1.4.0"
vasync "^2.2.1"
verror "^1.10.1"
leac@^0.6.0:
version "0.6.0"
resolved "https://registry.npmmirror.com/leac/-/leac-0.6.0.tgz#dcf136e382e666bd2475f44a1096061b70dc0912"
@ -18358,17 +18097,6 @@ mariadb@^2.5.6:
moment-timezone "^0.5.34"
please-upgrade-node "^3.2.0"
mariadb@^3.3.0:
version "3.3.1"
resolved "https://registry.npmmirror.com/mariadb/-/mariadb-3.3.1.tgz#3ee361242411ba4cf4a80b06e304d1c68c97ad90"
integrity sha512-L8bh4iuZU3J8H7Co7rQ6OY9FDLItAN1rGy8kPA7Dyxo8AiHADuuONoypKKp1pE09drs6e5LR7UW9luLZ/A4znA==
dependencies:
"@types/geojson" "^7946.0.14"
"@types/node" "^20.11.17"
denque "^2.1.0"
iconv-lite "^0.6.3"
lru-cache "^10.2.0"
markdown-it-highlightjs@3.3.1:
version "3.3.1"
resolved "https://registry.npmmirror.com/markdown-it-highlightjs/-/markdown-it-highlightjs-3.3.1.tgz#38403610487292b8a1ae2d1acc7bb66e4ede6be8"
@ -19558,11 +19286,12 @@ mysql2@^2.3.3:
seq-queue "^0.0.5"
sqlstring "^2.3.2"
mysql2@^3.9.1:
version "3.10.1"
resolved "https://registry.npmmirror.com/mysql2/-/mysql2-3.10.1.tgz#c39b8faf24ef4fd56330ef269122471a22d19198"
integrity sha512-6zo1T3GILsXMCex3YEu7hCz2OXLUarxFsxvFcUHWMpkPtmZLeTTWgRdc1gWyNJiYt6AxITmIf9bZDRy/jAfWew==
mysql2@^3.11.0:
version "3.11.0"
resolved "https://registry.npmmirror.com/mysql2/-/mysql2-3.11.0.tgz#2a7bd7c615ab43f8167ed9922063b968f3e48f33"
integrity sha512-J9phbsXGvTOcRVPR95YedzVSxJecpW5A5+cQ57rhHIFXteTP10HCs+VBjS7DHIKfEaI1zQ5tlVrquCd64A6YvA==
dependencies:
aws-ssl-profiles "^1.1.1"
denque "^2.1.0"
generate-function "^2.3.1"
iconv-lite "^0.6.3"
@ -19823,7 +19552,7 @@ node-releases@^2.0.18:
resolved "https://registry.npmmirror.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f"
integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==
node-sql-parser@^4.11.0, node-sql-parser@^4.18.0:
node-sql-parser@^4.18.0:
version "4.18.0"
resolved "https://registry.npmmirror.com/node-sql-parser/-/node-sql-parser-4.18.0.tgz#516b6e633c55c5abbba1ca588ab372db81ae9318"
integrity sha512-2YEOR5qlI1zUFbGMLKNfsrR5JUvFg9LxIRVE+xJe962pfVLH0rnItqLzv96XVs1Y1UIR8FxsXAuvX/lYAWZ2BQ==
@ -20144,11 +19873,6 @@ object-copy@^0.1.0:
define-property "^0.2.5"
kind-of "^3.0.3"
object-hash@^2.2.0:
version "2.2.0"
resolved "https://registry.npmmirror.com/object-hash/-/object-hash-2.2.0.tgz#5ad518581eefc443bd763472b8ff2e9c2c0d54a5"
integrity sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==
object-hash@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/object-hash/-/object-hash-3.0.0.tgz#73f97f753e7baffc0e2cc9d6e079079744ac82e9"
@ -20303,16 +20027,11 @@ object.values@^1.1.6, object.values@^1.1.7:
define-properties "^1.2.0"
es-abstract "^1.22.1"
obuf@^1.0.0, obuf@^1.1.2, obuf@~1.1.2:
obuf@^1.0.0, obuf@^1.1.2:
version "1.1.2"
resolved "https://registry.npmmirror.com/obuf/-/obuf-1.1.2.tgz#09bea3343d41859ebd446292d11c9d4db619084e"
integrity sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==
oidc-token-hash@^5.0.3:
version "5.0.3"
resolved "https://registry.npmmirror.com/oidc-token-hash/-/oidc-token-hash-5.0.3.tgz#9a229f0a1ce9d4fc89bcaee5478c97a889e7b7b6"
integrity sha512-IF4PcGgzAr6XXSff26Sk/+P4KZFJVuHAJZj3wgO3vX2bMdNVp/QXTP3P7CEm9V1IdG8lDLY3HhiqpsE/nOwpPw==
omit-deep@0.3.0:
version "0.3.0"
resolved "https://registry.npmmirror.com/omit-deep/-/omit-deep-0.3.0.tgz#21c8af3499bcadd29651a232cbcacbc52445ebec"
@ -20409,16 +20128,6 @@ open@^9.1.0:
is-inside-container "^1.0.0"
is-wsl "^2.2.0"
openid-client@^5.4.2:
version "5.6.5"
resolved "https://registry.npmmirror.com/openid-client/-/openid-client-5.6.5.tgz#c149ad07b9c399476dc347097e297bbe288b8b00"
integrity sha512-5P4qO9nGJzB5PI0LFlhj4Dzg3m4odt0qsJTfyEtZyOlkgpILwEioOhVVJOrS1iVH494S4Ee5OCjjg6Bf5WOj3w==
dependencies:
jose "^4.15.5"
lru-cache "^6.0.0"
object-hash "^2.2.0"
oidc-token-hash "^5.0.3"
opt-cli@1.5.1:
version "1.5.1"
resolved "https://registry.npmmirror.com/opt-cli/-/opt-cli-1.5.1.tgz#04db447b13c96b992eb31685266f4ed0d9736dc2"
@ -21145,21 +20854,11 @@ pg-int8@1.0.1:
resolved "https://registry.npmmirror.com/pg-int8/-/pg-int8-1.0.1.tgz#943bd463bf5b71b4170115f80f8efc9a0c0eb78c"
integrity sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==
pg-numeric@1.0.2:
version "1.0.2"
resolved "https://registry.npmmirror.com/pg-numeric/-/pg-numeric-1.0.2.tgz#816d9a44026086ae8ae74839acd6a09b0636aa3a"
integrity sha512-BM/Thnrw5jm2kKLE5uJkXqqExRUY/toLHda65XgFTBTFYZyopbKjBe29Ii3RbkvlsMoFwD+tHeGaCjjv0gHlyw==
pg-pool@^3.6.1:
version "3.6.1"
resolved "https://registry.npmmirror.com/pg-pool/-/pg-pool-3.6.1.tgz#5a902eda79a8d7e3c928b77abf776b3cb7d351f7"
integrity sha512-jizsIzhkIitxCGfPRzJn1ZdcosIt3pz9Sh3V01fm1vZnbnCMgmGl5wvGGdNN2EL9Rmb0EcFoCkixH4Pu+sP9Og==
pg-protocol@*:
version "1.6.1"
resolved "https://registry.npmmirror.com/pg-protocol/-/pg-protocol-1.6.1.tgz#21333e6d83b01faaebfe7a33a7ad6bfd9ed38cb3"
integrity sha512-jPIlvgoD63hrEuihvIg+tJhoGjUsLPn6poJY9N5CnlPd91c2T18T/9zBtLxZSb1EhYxBRoZJtzScCaWlYLtktg==
pg-protocol@^1.6.0:
version "1.6.0"
resolved "https://registry.npmmirror.com/pg-protocol/-/pg-protocol-1.6.0.tgz#4c91613c0315349363af2084608db843502f8833"
@ -21176,19 +20875,6 @@ pg-types@^2.1.0:
postgres-date "~1.0.4"
postgres-interval "^1.1.0"
pg-types@^4.0.1:
version "4.0.2"
resolved "https://registry.npmmirror.com/pg-types/-/pg-types-4.0.2.tgz#399209a57c326f162461faa870145bb0f918b76d"
integrity sha512-cRL3JpS3lKMGsKaWndugWQoLOCoP+Cic8oseVcbr0qhPzYD5DWXK+RZ9LY9wxRf7RQia4SCwQlXk0q6FCPrVng==
dependencies:
pg-int8 "1.0.1"
pg-numeric "1.0.2"
postgres-array "~3.0.1"
postgres-bytea "~3.0.0"
postgres-date "~2.1.0"
postgres-interval "^3.0.0"
postgres-range "^1.1.1"
pg@^8.11.3, pg@^8.7.3:
version "8.11.3"
resolved "https://registry.npmmirror.com/pg/-/pg-8.11.3.tgz#d7db6e3fe268fcedd65b8e4599cda0b8b4bf76cb"
@ -21786,33 +21472,16 @@ postgres-array@~2.0.0:
resolved "https://registry.npmmirror.com/postgres-array/-/postgres-array-2.0.0.tgz#48f8fce054fbc69671999329b8834b772652d82e"
integrity sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==
postgres-array@~3.0.1:
version "3.0.2"
resolved "https://registry.npmmirror.com/postgres-array/-/postgres-array-3.0.2.tgz#68d6182cb0f7f152a7e60dc6a6889ed74b0a5f98"
integrity sha512-6faShkdFugNQCLwucjPcY5ARoW1SlbnrZjmGl0IrrqewpvxvhSLHimCVzqeuULCbG0fQv7Dtk1yDbG3xv7Veog==
postgres-bytea@~1.0.0:
version "1.0.0"
resolved "https://registry.npmmirror.com/postgres-bytea/-/postgres-bytea-1.0.0.tgz#027b533c0aa890e26d172d47cf9ccecc521acd35"
integrity sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==
postgres-bytea@~3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/postgres-bytea/-/postgres-bytea-3.0.0.tgz#9048dc461ac7ba70a6a42d109221619ecd1cb089"
integrity sha512-CNd4jim9RFPkObHSjVHlVrxoVQXz7quwNFpz7RY1okNNme49+sVyiTvTRobiLV548Hx/hb1BG+iE7h9493WzFw==
dependencies:
obuf "~1.1.2"
postgres-date@~1.0.4:
version "1.0.7"
resolved "https://registry.npmmirror.com/postgres-date/-/postgres-date-1.0.7.tgz#51bc086006005e5061c591cee727f2531bf641a8"
integrity sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==
postgres-date@~2.1.0:
version "2.1.0"
resolved "https://registry.npmmirror.com/postgres-date/-/postgres-date-2.1.0.tgz#b85d3c1fb6fb3c6c8db1e9942a13a3bf625189d0"
integrity sha512-K7Juri8gtgXVcDfZttFKVmhglp7epKb1K4pgrkLxehjqkrgPhfG6OO8LHLkfaqkbpjNRnra018XwAr1yQFWGcA==
postgres-interval@^1.1.0:
version "1.2.0"
resolved "https://registry.npmmirror.com/postgres-interval/-/postgres-interval-1.2.0.tgz#b460c82cb1587507788819a06aa0fffdb3544695"
@ -21820,21 +21489,6 @@ postgres-interval@^1.1.0:
dependencies:
xtend "^4.0.0"
postgres-interval@^3.0.0:
version "3.0.0"
resolved "https://registry.npmmirror.com/postgres-interval/-/postgres-interval-3.0.0.tgz#baf7a8b3ebab19b7f38f07566c7aab0962f0c86a"
integrity sha512-BSNDnbyZCXSxgA+1f5UU2GmwhoI0aU5yMxRGO8CdFEcY2BQF9xm/7MqKnYoM1nJDk8nONNWDk9WeSmePFhQdlw==
postgres-range@^1.1.1:
version "1.1.4"
resolved "https://registry.npmmirror.com/postgres-range/-/postgres-range-1.1.4.tgz#a59c5f9520909bcec5e63e8cf913a92e4c952863"
integrity sha512-i/hbxIE9803Alj/6ytL7UHQxRvZkI9O4Sy+J3HGc4F4oo/2eQAjTSNJ0bfxyse3bH0nuVesCk+3IRLaMtG3H6w==
precond@0.2:
version "0.2.3"
resolved "https://registry.npmmirror.com/precond/-/precond-0.2.3.tgz#aa9591bcaa24923f1e0f4849d240f47efc1075ac"
integrity sha512-QCYG84SgGyGzqJ/vlMsxeXd/pgL/I94ixdNFyh1PusWmTCyVfPJjZ1K1jvHtsbfnXQs2TSkEP2fR7QiMZAnKFQ==
prelude-ls@^1.2.1:
version "1.2.1"
resolved "https://registry.npmmirror.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396"
@ -21963,11 +21617,6 @@ process-warning@^1.0.0:
resolved "https://registry.npmmirror.com/process-warning/-/process-warning-1.0.0.tgz#980a0b25dc38cd6034181be4b7726d89066b4616"
integrity sha512-du4wfLyj4yCZq1VupnVSZmRsPJsNuxoDQFdCFHLaYiEbFBD7QE0a+I4D7hOxrVnh78QE/YipFAj9lXHiXocV+Q==
process-warning@^2.1.0, process-warning@^2.2.0:
version "2.3.2"
resolved "https://registry.npmmirror.com/process-warning/-/process-warning-2.3.2.tgz#70d8a3251aab0eafe3a595d8ae2c5d2277f096a5"
integrity sha512-n9wh8tvBe5sFmsqlg+XQhaQLumwpqoAUruLwjCopgTmUBjJ/fjtBsJzKleCaIGBOMXYEhp1YfKl4d7rJ5ZKJGA==
process@^0.11.10:
version "0.11.10"
resolved "https://registry.npmmirror.com/process/-/process-0.11.10.tgz#7332300e840161bda3e69a1d1d91a7d4bc16f182"
@ -24130,28 +23779,6 @@ sequelize@^6.26.0:
validator "^13.9.0"
wkx "^0.5.0"
sequelize@^6.35.0:
version "6.37.3"
resolved "https://registry.npmmirror.com/sequelize/-/sequelize-6.37.3.tgz#ed6212029a52c59a18638d2a703da84bc2f81311"
integrity sha512-V2FTqYpdZjPy3VQrZvjTPnOoLm0KudCRXfGWp48QwhyPPp2yW8z0p0sCYZd/em847Tl2dVxJJ1DR+hF+O77T7A==
dependencies:
"@types/debug" "^4.1.8"
"@types/validator" "^13.7.17"
debug "^4.3.4"
dottie "^2.0.6"
inflection "^1.13.4"
lodash "^4.17.21"
moment "^2.29.4"
moment-timezone "^0.5.43"
pg-connection-string "^2.6.1"
retry-as-promised "^7.0.4"
semver "^7.5.4"
sequelize-pool "^7.1.0"
toposort-class "^1.0.1"
uuid "^8.3.2"
validator "^13.9.0"
wkx "^0.5.0"
serve-handler@6.1.3:
version "6.1.3"
resolved "https://registry.npmmirror.com/serve-handler/-/serve-handler-6.1.3.tgz#1bf8c5ae138712af55c758477533b9117f6435e8"
@ -26861,13 +26488,6 @@ vary@^1, vary@^1.1.2, vary@~1.1.2:
resolved "https://registry.npmmirror.com/vary/-/vary-1.1.2.tgz#2299f02c6ded30d4a5961b0b9f74524a18f634fc"
integrity sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==
vasync@^2.2.1:
version "2.2.1"
resolved "https://registry.npmmirror.com/vasync/-/vasync-2.2.1.tgz#d881379ff3685e4affa8e775cf0fd369262a201b"
integrity sha512-Hq72JaTpcTFdWiNA4Y22Amej2GH3BFmBaKPPlDZ4/oC8HNn2ISHLkFrJU4Ds8R3jcUi7oo5Y9jcMHKjES+N9wQ==
dependencies:
verror "1.10.0"
vditor@^3.10.3:
version "3.10.4"
resolved "https://registry.npmmirror.com/vditor/-/vditor-3.10.4.tgz#df7e5cdf8c737b588152b2119942ff0e0904c9cd"
@ -26884,15 +26504,6 @@ verror@1.10.0:
core-util-is "1.0.2"
extsprintf "^1.2.0"
verror@^1.10.1:
version "1.10.1"
resolved "https://registry.npmmirror.com/verror/-/verror-1.10.1.tgz#4bf09eeccf4563b109ed4b3d458380c972b0cdeb"
integrity sha512-veufcmxri4e3XSrT0xwfUR7kguIkaxBeosDg00yDWhk49wdwkSUrvvsm7nc75e1PUyvIeZj6nS8VQRYz2/S4Xg==
dependencies:
assert-plus "^1.0.0"
core-util-is "1.0.2"
extsprintf "^1.2.0"
vfile-location@^4.0.0:
version "4.1.0"
resolved "https://registry.npmmirror.com/vfile-location/-/vfile-location-4.1.0.tgz#69df82fb9ef0a38d0d02b90dd84620e120050dd0"
@ -27501,23 +27112,6 @@ xlsx@^0.17.0:
version "0.20.2"
resolved "https://cdn.sheetjs.com/xlsx-0.20.2/xlsx-0.20.2.tgz#0f64eeed3f1a46e64724620c3553f2dbd3cd2d7d"
xml-crypto@^3.0.1:
version "3.2.0"
resolved "https://registry.npmmirror.com/xml-crypto/-/xml-crypto-3.2.0.tgz#a9debab572c8e895cff5fb351a8d8be3f6e1962e"
integrity sha512-qVurBUOQrmvlgmZqIVBqmb06TD2a/PpEUfFPgD7BuBfjmoH4zgkqaWSIJrnymlCvM2GGt9x+XtJFA+ttoAufqg==
dependencies:
"@xmldom/xmldom" "^0.8.8"
xpath "0.0.32"
xml-encryption@^3.0.2:
version "3.0.2"
resolved "https://registry.npmmirror.com/xml-encryption/-/xml-encryption-3.0.2.tgz#d3cb67d97cdd9673313a42cc0d7fa43ff0886c21"
integrity sha512-VxYXPvsWB01/aqVLd6ZMPWZ+qaj0aIdF+cStrVJMcFj3iymwZeI0ABzB3VqMYv48DkSpRhnrXqTUkR34j+UDyg==
dependencies:
"@xmldom/xmldom" "^0.8.5"
escape-html "^1.0.3"
xpath "0.0.32"
xml-lexer@^0.2.2:
version "0.2.2"
resolved "https://registry.npmmirror.com/xml-lexer/-/xml-lexer-0.2.2.tgz#518193a4aa334d58fc7d248b549079b89907e046"
@ -27546,15 +27140,7 @@ xml2js@^0.4.22:
sax ">=0.6.0"
xmlbuilder "~11.0.0"
xml2js@^0.5.0:
version "0.5.0"
resolved "https://registry.npmmirror.com/xml2js/-/xml2js-0.5.0.tgz#d9440631fbb2ed800203fad106f2724f62c493b7"
integrity sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==
dependencies:
sax ">=0.6.0"
xmlbuilder "~11.0.0"
xml2js@^0.6.0, xml2js@^0.6.2:
xml2js@^0.6.2:
version "0.6.2"
resolved "https://registry.npmmirror.com/xml2js/-/xml2js-0.6.2.tgz#dd0b630083aa09c161e25a4d0901e2b2a929b499"
integrity sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==
@ -27562,11 +27148,6 @@ xml2js@^0.6.0, xml2js@^0.6.2:
sax ">=0.6.0"
xmlbuilder "~11.0.0"
xmlbuilder@^15.1.1:
version "15.1.1"
resolved "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"
integrity sha512-yMqGBqtXyeN1e3TGYvgNgDVZ3j84W4cwkOXQswghol6APgZWaff9lnbvN7MHYJOiXsvGPXtjTYJEiC9J2wv9Eg==
xmlbuilder@~11.0.0:
version "11.0.1"
resolved "https://registry.npmmirror.com/xmlbuilder/-/xmlbuilder-11.0.1.tgz#be9bae1c8a046e76b31127726347d0ad7002beb3"
@ -27577,16 +27158,6 @@ xmlchars@^2.2.0:
resolved "https://registry.npmmirror.com/xmlchars/-/xmlchars-2.2.0.tgz#060fe1bcb7f9c76fe2a17db86a9bc3ab894210cb"
integrity sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==
xpath@0.0.27:
version "0.0.27"
resolved "https://registry.npmmirror.com/xpath/-/xpath-0.0.27.tgz#dd3421fbdcc5646ac32c48531b4d7e9d0c2cfa92"
integrity sha512-fg03WRxtkCV6ohClePNAECYsmpKKTv5L8y/X3Dn1hQrec3POx2jHZ/0P2qQ6HvsrU1BmeqXcof3NGGueG6LxwQ==
xpath@0.0.32:
version "0.0.32"
resolved "https://registry.npmmirror.com/xpath/-/xpath-0.0.32.tgz#1b73d3351af736e17ec078d6da4b8175405c48af"
integrity sha512-rxMJhSIoiO8vXcWvSifKqhvV96GjiD5wYb8/QHdoRyQvraTpp4IEv944nhGausZZ3u7dhQXteZuZbaqfpB7uYw==
xpipe@^1.0.5:
version "1.0.7"
resolved "https://registry.npmmirror.com/xpipe/-/xpipe-1.0.7.tgz#d0aff00e080a44ffbdbe45dd7658ff6c483464c8"