Skip to content

Commit a5c11dc

Browse files
authored
Import from SQL (#1103)
* wip * . * wip * wip * remove rsync * use ConfigUtils for (de)compress * isObject * setIn, mergeIn * fix mergeIn * progr * . * deepCopyObj, arrayMergeMode, symbols . . . , * . * . * IF() * add sqlImport for funcs * . * . * fix imports cycles . . . * wip sqlImport for ops * . * . * fixes after merge * example app: load from sql * valueFuncs * pre-defined sqlImportDate * fix #1024 . * linear * fix ops like, not_like ; fix multiselect value type * lint * . * . * . * pr * . * tableName * . * lint fix
1 parent 5769193 commit a5c11dc

File tree

114 files changed

+5580
-2574
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

114 files changed

+5580
-2574
lines changed

.codesandbox/ci.json

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"packages": [
33
"packages/core",
4+
"packages/sql",
45
"packages/ui",
56
"packages/antd",
67
"packages/mui",

.eslintrc.js

+86-62
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ module.exports = {
2020
"eslint:recommended",
2121
"plugin:import/recommended",
2222
// "plugin:import/typescript", // not needed for JS
23-
"plugin:react/recommended",
23+
// "plugin:react/recommended", // not needed for core
2424
// "plugin:@typescript-eslint/eslint-recommended", // not needed for JS
2525
],
2626
"globals": {
@@ -134,73 +134,97 @@ module.exports = {
134134
]
135135
},
136136
"overrides": [
137-
{
138-
"files": ["packages/tests/**/*"],
139-
"env": {
140-
"mocha": true,
141-
// "jasmine": true,
137+
{
138+
"files": ["packages/sql/**/*"],
139+
"settings": {
140+
"import/resolver": {
141+
"typescript": {
142+
"project": [
143+
"packages/sql/tsconfig.json",
144+
],
145+
},
146+
},
147+
},
142148
},
143-
"settings": {
144-
"import/core-modules": [
145-
"sinon",
146-
"chai",
147-
"mocha"
148-
],
149-
// "import/resolver": {
150-
// "webpack": {
151-
// "config": "./webpack.config.js"
152-
// }
153-
// },
149+
150+
{
151+
"files": ["packages/tests/**/*"],
152+
"env": {
153+
"mocha": true,
154+
// "jasmine": true,
155+
},
156+
"settings": {
157+
"import/core-modules": [
158+
"sinon",
159+
"chai",
160+
"mocha"
161+
],
162+
// "import/resolver": {
163+
// "webpack": {
164+
// "config": "./webpack.config.js"
165+
// }
166+
// },
167+
},
154168
},
155-
},
156-
{
157-
"files": ["packages/sandbox_simple/**/*"],
158-
"parser": "@babel/eslint-parser",
159-
"parserOptions": {
160-
"requireConfigFile": false,
161-
"babelOptions": {
162-
"presets": [
163-
"@babel/preset-env",
164-
"@babel/preset-react"
169+
170+
{
171+
"files": ["packages/sandbox_simple/**/*"],
172+
"parser": "@babel/eslint-parser",
173+
"parserOptions": {
174+
"requireConfigFile": false,
175+
"babelOptions": {
176+
"presets": [
177+
"@babel/preset-env",
178+
"@babel/preset-react"
179+
],
180+
},
181+
"sourceType": "module",
182+
},
183+
"settings": {
184+
"import/core-modules": [
185+
"react",
186+
"@react-awesome-query-builder/ui/css/styles.css"
165187
],
166188
},
167-
"sourceType": "module",
168189
},
169-
"settings": {
170-
"import/core-modules": [
171-
"react",
172-
"@react-awesome-query-builder/ui/css/styles.css"
190+
191+
{
192+
"files": ["**/*.ts", "**/*.tsx"],
193+
"extends": [
194+
"eslint:recommended",
195+
"plugin:import/recommended",
196+
"plugin:import/typescript",
197+
"plugin:@typescript-eslint/eslint-recommended",
198+
"plugin:@typescript-eslint/recommended",
199+
"plugin:@typescript-eslint/recommended-requiring-type-checking"
173200
],
201+
"rules": {
202+
"@typescript-eslint/no-unnecessary-type-assertion": 0,
203+
//todo
204+
"@typescript-eslint/no-unused-vars": 0,
205+
"@typescript-eslint/ban-types": 0,
206+
"@typescript-eslint/explicit-module-boundary-types": 0,
207+
"@typescript-eslint/no-explicit-any": 0,
208+
"@typescript-eslint/no-empty-interface": 0,
209+
"@typescript-eslint/unbound-method": 0,
210+
"@typescript-eslint/prefer-regexp-exec": 0,
211+
"@typescript-eslint/no-empty-function": 0,
212+
"@typescript-eslint/ban-ts-comment": 0,
213+
"@typescript-eslint/no-floating-promises": 0,
214+
"@typescript-eslint/no-non-null-assertion": 0,
215+
"@typescript-eslint/no-non-null-asserted-optional-chain": 0,
216+
}
217+
},
218+
{
219+
"files": ["**/*.jsx", "**/*.tsx"],
220+
"extends": [
221+
"plugin:react/recommended",
222+
],
223+
"rules": {
224+
//todo
225+
"react/display-name": 0,
226+
"react/prop-types": 0,
227+
}
174228
},
175-
},
176-
177-
{
178-
"files": ["**/*.ts", "**/*.tsx"],
179-
"extends": [
180-
"eslint:recommended",
181-
"plugin:import/recommended",
182-
"plugin:import/typescript",
183-
"plugin:react/recommended",
184-
"plugin:@typescript-eslint/eslint-recommended",
185-
"plugin:@typescript-eslint/recommended",
186-
"plugin:@typescript-eslint/recommended-requiring-type-checking"
187-
],
188-
"rules": {
189-
"@typescript-eslint/no-unnecessary-type-assertion": 0,
190-
//todo
191-
"@typescript-eslint/no-unused-vars": 0,
192-
"@typescript-eslint/ban-types": 0,
193-
"@typescript-eslint/explicit-module-boundary-types": 0,
194-
"@typescript-eslint/no-explicit-any": 0,
195-
"@typescript-eslint/no-empty-interface": 0,
196-
"@typescript-eslint/unbound-method": 0,
197-
"@typescript-eslint/prefer-regexp-exec": 0,
198-
"@typescript-eslint/no-empty-function": 0,
199-
"@typescript-eslint/ban-ts-comment": 0,
200-
"@typescript-eslint/no-floating-promises": 0,
201-
"@typescript-eslint/no-non-null-assertion": 0,
202-
"@typescript-eslint/no-non-null-asserted-optional-chain": 0,
203-
}
204-
},
205229
],
206230
}

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -19,3 +19,4 @@ yarn.lock
1919
packages/*/cjs/
2020
packages/*/esm/
2121
packages/*/css/
22+
packages/*/types/

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
# Changelog
2+
- 6.6.5
3+
- Support import fom SQL (`SqlUtils.loadFromSql`) (PR #1103) (issue #911, #593)
4+
- Fixed type issue with SerializedFunction (PR #1103) (issue #1024)
25
- 6.6.4
36
- Support groups inside rule-group (PR #1111) (issue #1108)
47
- Fixed cardinality issue (PR #1136) (issue #1118)

CONFIG.adoc

+13-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ endif::[]
1919
:renderSwitch: https://github.com/ukrbublik/react-awesome-query-builder/blob/master/packages/antd/modules/config/index.jsx#L54
2020
:config_ser: https://github.com/ukrbublik/react-awesome-query-builder/blob/master/packages/sandbox_next/lib/config_ser.js
2121
:d_ts: https://github.com/ukrbublik/react-awesome-query-builder/blob/master/packages/core/modules/index.d.ts
22+
:ts-pattern: https://github.com/gvergnaud/ts-pattern
2223

2324
= Config format
2425

@@ -37,7 +38,7 @@ Optionally you can override some options in basic config or add your own types/w
3738
There are functions for building query string: `formatConj`, `formatValue`, `formatOp`, `formatField`, `formatFunc` which are used for `QbUtils.queryString()`. +
3839
They have common param `isForDisplay` - false by default, true will be used for {queryString}[`QbUtils.queryString(immutableTree, config, true)`] (see 3rd param true). +
3940
Also there are similar `mongoConj`, `mongoFormatOp`, `mongoFormatValue`, `mongoFunc`, `mongoFormatFunc`, `mongoArgsAsObject` for building MongoDb query with `QbUtils.mongodbFormat()`. +
40-
And `sqlFormatConj`, `sqlOp`, `sqlFormatOp`, `sqlFormatValue`, `sqlFormatReverse`, `formatSpelField`, `sqlFunc`, `sqlFormatFunc` for building SQL where query with `QbUtils.sqlFormat()`. +
41+
And `sqlFormatConj`, `sqlOp`, `sqlOps`, `sqlFormatOp`, `sqlFormatValue`, `sqlFormatReverse`, `formatSpelField`, `sqlFunc`, `sqlFormatFunc`, `sqlImport` for building SQL where query with `QbUtils.sqlFormat()`. +
4142
And `spelFormatConj`, `spelOp`, `spelFormatOp`, `spelFormatValue`, `spelFormatReverse`, `spelFunc`, `spelFormatFunc` for building query in (https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html)[Spring Expression Language (SpEL)] with `QbUtils.spelFormat()`. +
4243
And `jsonLogic` for building http://jsonlogic.com[JsonLogic] with `QbUtils.jsonLogicFormat()`. +
4344

@@ -347,7 +348,7 @@ Behaviour settings:
347348
|removeEmptyGroupsOnLoad |true |Remove empty groups during initial validation of `value` prop passed to `<Query>`
348349
|removeInvalidMultiSelectValuesOnLoad |true |Remove values that are not in `listValues` during initial validation of `value` prop passed to `<Query>`? +
349350
By default `true`, but `false` for AntDesign as can be removed manually
350-
|useConfigCompress |false |Set to `true` if you use `Utils.decompressConfig()`
351+
|useConfigCompress |false |Set to `true` if you use `Utils.ConfigUtils.decompressConfig()`
351352
|fieldItemKeysForSearch |`["label", "path", "altLabel", "grouplabel"]` |Keys in field item (see {d_ts}[type] `FieldItem`) available for search. Available keys: "key", "path", "label", "altLabel" (label2), "tooltip", "grouplabel" (label of parent group, for subfields of complex fields)
352353
|listKeysForSearch |`["title", "value"]` |Keys in list item (see {d_ts}[type] `ListItem`) available for search. Available keys: "title", "value", "groupTitle"
353354
|reverseOperatorsForNot |false |True to convert "!(x == 1)" to "x != 1" on import and export
@@ -549,9 +550,11 @@ where `AND` and `OR` - available conjuctions (logical operators). You can add `N
549550
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2` +
550551
`useExpr` - true if resulted expression will be wrapped in https://docs.mongodb.com/manual/reference/operator/query/expr/index.html[`{'$expr': {...}}`] (used only if you compare field with another field or function) (you need to use aggregation operators in this case, like https://docs.mongodb.com/manual/reference/operator/aggregation/eq/[$eq (aggregation)] instead of https://docs.mongodb.com/manual/reference/operator/query/eq/[$eq])
551552
|sqlOp |+ for SQL format | |Operator name in SQL
553+
|sqlOps |- for SQL format | |Operator names in SQL
552554
|sqlFormatOp |- for SQL format | |Function for advanced formatting SQL WHERE query when just `sqlOp` is not enough. +
553555
`(string field, string op, mixed value, string valueSrc, string valueType, Object opDef, Object operatorOptions, Object fieldDef) => string` +
554556
`value` - mixed for `cardinality==1` -or- `Array` for `cardinality>2`
557+
|sqlImport |- for SQL format | |Function to convert given raw SQL value (not string, but object got from `node-sql-parser`) to `{ children: Array }`. If given expression can't be parsed into current operator, throw an error.
555558
|spelOp |+ for SpEL format | |Operator name in SpEL
556559
|spelFormatOp |- for SpEL format | |Function for advanced formatting query in SpEL when just `spelOp` is not enough. +
557560
`(string field, string op, mixed value, string valueSrc, string valueType, Object opDef, Object operatorOptions, Object fieldDef) => string` +
@@ -768,6 +771,7 @@ To enable this feature set `valueSources` of type to `['value', 'func']` (see be
768771
|sqlFunc |- for SQL format |same as func key |Func name in SQL
769772
|sqlFormatFunc |- for SQL format | |Can be used instead of `sqlFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression string. +
770773
Example: SUM function can be formatted with `({a, b}) => a + " + " + b`
774+
|sqlImport |- for SQL format | |Function to convert given raw SQL value (not string, but object got from `node-sql-parser`) to `{args: Object}`. If given expression can't be parsed into current function, throw an error.
771775
|spelFunc |- for SpEL format |same as func key |Func name in SpEL
772776
|spelFormatFunc |- for SpEL format | |Can be used instead of `spelFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression string. +
773777
Example: SUM function can be formatted with `({a, b}) => a + " + " + b`
@@ -776,7 +780,7 @@ To enable this feature set `valueSources` of type to `['value', 'func']` (see be
776780
|mongoFormatFunc |- for MongoDB format | |Can be used instead of `mongoFunc`. Function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression object.
777781
|jsonLogic |+ for http://jsonlogic.com[JsonLogic] | |String (function name) or function with 1 param - args object `{<arg name> : <arg value>}`, should return formatted function expression for JsonLogic.
778782
|jsonLogicImport | | |Function to convert given JsonLogic expression to array of arguments of current function. If given expression can't be parsed into current function, throw an error.
779-
|spelImport | | |Function to convert given raw SpEL value to array of arguments of current function. If given value can't be parsed into current function, throw an error.
783+
|spelImport | | |Function to convert given raw SpEL value to object of arguments of current function. If given value can't be parsed into current function, throw an error or return undefined.
780784
|args.* | | |Arguments of function. Config is almost same as for simple link:#configfields[fields]
781785
|args.<arg>.label | |arg's key |Label to be displayed in arg's label or placeholder (if `config.settings.showLabels` is false)
782786
|args.<arg>.type |+ | |One of types described in link:#configtypes[config.types]
@@ -850,13 +854,13 @@ const ctx = {
850854
const zipConfig = {
851855
fields,
852856
settings: {
853-
useConfigCompress: true, // this is required to use Utils.decompressConfig()
857+
useConfigCompress: true, // this is required to use Utils.ConfigUtils.decompressConfig()
854858
},
855859
// you can add here other sections like `widgets` or `types`, but don't add `ctx`
856860
};
857861
858862
// Config can be loaded from backend with providing `ctx`
859-
const config = Utils.decompressConfig(zipConfig, BasicConfig, ctx);
863+
const config = Utils.ConfigUtils.decompressConfig(zipConfig, BasicConfig, ctx);
860864
----
861865

862866
You _can't_ just pass JS function to `validateValue` in `fieldSettings` because functions can't be serialized to JSON.
@@ -932,7 +936,7 @@ const zipConfig = {
932936
To build zip config from full config you can use this util:
933937
[source,javascript]
934938
----
935-
const zipConfig = Utils.compressConfig(config, BasicConfig);
939+
const zipConfig = Utils.ConfigUtils.compressConfig(config, BasicConfig);
936940
----
937941
In order to generate zip config corretly (to JSON-serializable object), you should put your custom functions to `ctx` and refer to them by names as in examples above.
938942
[source,javascript]
@@ -954,11 +958,11 @@ const config = merge({}, BasicConfig, {
954958
},
955959
ctx,
956960
});
957-
const zipConfig = Utils.compressConfig(config, BasicConfig);
958-
const config2 = Utils.decompressConfig(zipConfig, BasicConfig, ctx); // should be same as `config`
961+
const zipConfig = Utils.ConfigUtils.compressConfig(config, BasicConfig);
962+
const config2 = Utils.ConfigUtils.decompressConfig(zipConfig, BasicConfig, ctx); // should be same as `config`
959963
----
960964

961-
NOTE: `settings.useConfigCompress` should be `true` if you use `Utils.decompressConfig()`
965+
NOTE: `settings.useConfigCompress` should be `true` if you use `Utils.ConfigUtils.decompressConfig()`
962966

963967

964968
{nbsp} +

CONTRIBUTING.md

+1
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ Or with VSCode:
3636
- [`stores`](/packages/core/modules/stores) - Tree store reducer
3737
- [`actions`](/packages/core/modules/actions) - Actions to dispatch on store
3838
- [`index.d.ts`](/packages/core/modules/index.d.ts) - TS definitions
39+
- [`packages/sql/modules`](/packages/sql/modules) - SQL support
3940
- [`packages/ui/modules`](/packages/ui/modules) - Core React components
4041
- [`stores`](/packages/ui/modules/stores) - Tree store reducer for Redux (reused from `core`)
4142
- [`actions`](/packages/ui/modules/actions) - Actions to dispatch on store (reused from `core`, added `drag`)

README.md

+11-4
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,8 @@ From v6 library is divided into packages:
105105

106106
```mermaid
107107
graph LR;
108-
core((core))-->ui(ui);
108+
core-->ui;
109+
core-->sql((sql));
109110
ui-->antd;
110111
ui-->mui;
111112
ui-->material;
@@ -528,6 +529,12 @@ Wrapping in `div.query-builder-container` is necessary if you put query builder
528529
`Utils.Import.loadFromSpel (string, config) -> [Immutable, errors]`
529530
Convert query value from [Spring Expression Language (SpEL)](https://docs.spring.io/spring-framework/docs/3.2.x/spring-framework-reference/html/expressions.html) format to internal Immutable format.
530531

532+
#### `loadFromSql`
533+
`SqlUtils.loadFromSql (string, config) -> {tree: Immutable, errors: string[]}`
534+
Convert query value from SQL format to internal Immutable format.
535+
Requires import of `@react-awesome-query-builder/sql`:
536+
`import { SqlUtils } from "@react-awesome-query-builder/sql"`
537+
531538
### Save/load config from server
532539

533540
#### `compressConfig`
@@ -673,15 +680,15 @@ See [example](/packages/examples/src/demo_switch/index.tsx)
673680

674681
## SSR
675682
You can save and load config from server with help of utils:
676-
- [Utils.compressConfig()](#compressconfig)
677-
- [Utils.decompressConfig()](#decompressconfig)
683+
- [Utils.ConfigUtils.compressConfig()](#compressconfig)
684+
- [Utils.ConfigUtils.decompressConfig()](#decompressconfig)
678685

679686
You need these utils because you can't just send config *as-is* to server, as it contains functions that can't be serialized to JSON.
680687
Note that you need to set `config.settings.useConfigCompress = true` to enable this feature.
681688

682689
To put it simple:
683690
- `ZipConfig` type is a JSON that contains only changes against basic config (differences). At minimum it contains your `fields`. It does not contain [`ctx`](#ctx).
684-
- `Utils.decompressConfig()` will merge `ZipConfig` to basic config (and add `ctx` if passed).
691+
- `Utils.ConfigUtils.decompressConfig()` will merge `ZipConfig` to basic config (and add `ctx` if passed).
685692

686693
See [sandbox_next demo app](/packages/sandbox_next) that demonstrates server-side features.
687694

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"author": "Denis Oblogin <[email protected]> (https://github.com/ukrbublik)",
4646
"workspaces": [
4747
"packages/core",
48+
"packages/sql",
4849
"packages/ui",
4950
"packages/antd",
5051
"packages/mui",
@@ -111,6 +112,7 @@
111112
"eslint-plugin-import": "^2.29.1",
112113
"eslint-plugin-react": "^7.34.1",
113114
"lerna": "^8.1.9",
115+
"madge": "^8.0.0",
114116
"typescript": "~5.4.5"
115117
},
116118
"engines": {

packages/antd/modules/utils/stuff.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
import { Utils } from "@react-awesome-query-builder/ui";
22
const { getItemInListValues, listValuesToArray } = Utils.ListUtils;
3+
const { isObjectOrArray } = Utils.OtherUtils;
34

45

5-
const isObject = (v) => (typeof v == "object" && v !== null); // object or array
6-
76
export const defaultTreeDataMap = {id: "value", pId: "parent", rootPId: undefined};
87

98
// converts from treeData to treeDataSimpleMode format (https://ant.design/components/tree-select/)
@@ -39,7 +38,7 @@ const flatizeTreeData = (treeData) => {
3938
len = treeData.length;
4039
for (rind = 0 ; rind < len ; rind++) {
4140
const c = treeData[rind];
42-
if (!isObject(c))
41+
if (!isObjectOrArray(c))
4342
continue;
4443
if (c[tdm.pId] !== undefined && c[tdm.pId] != tdm.rootPId)
4544
continue; //not lev 1

packages/antd/scripts/build-npm.sh

+8-2
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,18 @@ rm -rf ./cjs
33
rm -rf ./esm
44

55
babel --extensions ".tsx,.jsx,.ts,.js" -d ./cjs ./modules
6+
find cjs/ -type f -name "*.d.js" | xargs -I{} rm {}
67
#find ./cjs -name "*.js" -exec sed -i.bak "s+antd/es/+antd/lib/+g" {} +
78
#rm ./cjs/**/*.bak
89
node ./scripts/fix-antd.js
10+
911
ESM=1 babel --extensions ".tsx,.jsx,.ts,.js" -d ./esm ./modules
10-
cp ./modules/index.d.ts ./cjs/index.d.ts
11-
cp ./modules/index.d.ts ./esm/index.d.ts
12+
find esm/ -type f -name "*.d.js" | xargs -I{} rm {}
13+
14+
# rsync -ma --include '*/' --include '*.d.ts' --exclude '*' ./modules/ ./cjs/
15+
# rsync -ma --include '*/' --include '*.d.ts' --exclude '*' ./modules/ ./esm/
16+
find modules/ -type f -name "*.d.ts" | cut -d'/' -f2- | xargs -I{} cp modules/{} cjs/{}
17+
find modules/ -type f -name "*.d.ts" | cut -d'/' -f2- | xargs -I{} cp modules/{} esm/{}
1218

1319
rm -rf ./css
1420
sass -I node_modules -I ../../node_modules styles/:css/ --no-source-map --style=expanded

packages/antd/tsconfig.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"module": "esnext",
55
"jsx": "preserve",
66
"lib": [
7-
"es2015",
7+
"es2016",
88
"dom",
99
"dom.iterable"
1010
],

0 commit comments

Comments
 (0)