@budibase/shared-core 2.3.21-alpha.1 → 2.4.8-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,16 +1,23 @@
1
1
  {
2
2
  "name": "@budibase/shared-core",
3
- "version": "2.3.21-alpha.1",
3
+ "version": "2.4.8-alpha.0",
4
4
  "description": "Shared data utils",
5
5
  "main": "dist/src/index.js",
6
+ "module": "dist/src/index.js",
6
7
  "types": "dist/src/index.d.ts",
7
8
  "author": "Budibase",
8
9
  "license": "GPL-3.0",
9
10
  "scripts": {
10
- "build": "tsc",
11
- "dev:builder": "tsc --watch"
11
+ "prebuild": "rimraf dist/",
12
+ "build": "tsc -p tsconfig.build.json",
13
+ "build:dev": "yarn prebuild && tsc --build --watch --preserveWatchOutput",
14
+ "dev:builder": "tsc -p tsconfig.build.json --watch"
15
+ },
16
+ "dependencies": {
17
+ "@budibase/types": "2.4.5-alpha.0"
12
18
  },
13
19
  "devDependencies": {
14
- "typescript": "4.7.3"
20
+ "typescript": "4.7.3",
21
+ "rimraf": "3.0.2"
15
22
  }
16
23
  }
package/src/filters.ts CHANGED
@@ -1,4 +1,6 @@
1
+ import { Datasource, FieldType, SortDirection, SortType } from "@budibase/types"
1
2
  import { OperatorOptions, SqlNumberTypeRangeMap } from "./constants"
3
+ import { deepGet } from "./helpers"
2
4
 
3
5
  const HBS_REGEX = /{{([^{].*?)}}/g
4
6
 
@@ -7,9 +9,9 @@ const HBS_REGEX = /{{([^{].*?)}}/g
7
9
  * @param type the data type
8
10
  */
9
11
  export const getValidOperatorsForType = (
10
- type: string,
12
+ type: FieldType,
11
13
  field: string,
12
- datasource: { tableId: string | string[]; type: string }
14
+ datasource: Datasource & { tableId: any } // TODO: is this table id ever populated?
13
15
  ) => {
14
16
  const Op = OperatorOptions
15
17
  const stringOps = [
@@ -30,7 +32,10 @@ export const getValidOperatorsForType = (
30
32
  Op.NotEmpty,
31
33
  Op.In,
32
34
  ]
33
- let ops: any[] = []
35
+ let ops: {
36
+ value: string
37
+ label: string
38
+ }[] = []
34
39
  if (type === "string") {
35
40
  ops = stringOps
36
41
  } else if (type === "number") {
@@ -73,13 +78,13 @@ export const NoEmptyFilterStrings = [
73
78
  OperatorOptions.NotEquals.value,
74
79
  OperatorOptions.Contains.value,
75
80
  OperatorOptions.NotContains.value,
76
- ]
81
+ ] as (keyof QueryFields)[]
77
82
 
78
83
  /**
79
84
  * Removes any fields that contain empty strings that would cause inconsistent
80
85
  * behaviour with how backend tables are filtered (no value means no filter).
81
86
  */
82
- const cleanupQuery = (query: { [x: string]: { [x: string]: any } }) => {
87
+ const cleanupQuery = (query: Query) => {
83
88
  if (!query) {
84
89
  return query
85
90
  }
@@ -87,9 +92,10 @@ const cleanupQuery = (query: { [x: string]: { [x: string]: any } }) => {
87
92
  if (!query[filterField]) {
88
93
  continue
89
94
  }
90
- for (let [key, value] of Object.entries(query[filterField])) {
95
+
96
+ for (let [key, value] of Object.entries(query[filterField]!)) {
91
97
  if (value == null || value === "") {
92
- delete query[filterField][key]
98
+ delete query[filterField]![key]
93
99
  }
94
100
  }
95
101
  }
@@ -117,21 +123,52 @@ type Filter = {
117
123
  externalType: keyof typeof SqlNumberTypeRangeMap
118
124
  }
119
125
 
120
- type Query = {
121
- string: Record<string, any>
122
- fuzzy: Record<string, any>
123
- range: Record<string, { low: string | number; high: string | number }>
124
- equal: Record<string, true>
125
- notEqual: Record<string, true>
126
- empty: Record<string, any>
127
- notEmpty: Record<string, any>
128
- contains: Record<string, any>
129
- notContains: Record<string, any>
130
- oneOf: Record<string, any>
131
- containsAny: Record<string, any>
126
+ type Query = QueryFields & QueryConfig
127
+ type QueryFields = {
128
+ string?: {
129
+ [key: string]: string
130
+ }
131
+ fuzzy?: {
132
+ [key: string]: string
133
+ }
134
+ range?: {
135
+ [key: string]: {
136
+ high: number | string
137
+ low: number | string
138
+ }
139
+ }
140
+ equal?: {
141
+ [key: string]: any
142
+ }
143
+ notEqual?: {
144
+ [key: string]: any
145
+ }
146
+ empty?: {
147
+ [key: string]: any
148
+ }
149
+ notEmpty?: {
150
+ [key: string]: any
151
+ }
152
+ oneOf?: {
153
+ [key: string]: any[]
154
+ }
155
+ contains?: {
156
+ [key: string]: any[]
157
+ }
158
+ notContains?: {
159
+ [key: string]: any[]
160
+ }
161
+ containsAny?: {
162
+ [key: string]: any[]
163
+ }
164
+ }
165
+
166
+ type QueryConfig = {
132
167
  allOr?: boolean
133
168
  }
134
169
 
170
+ type QueryFieldsType = keyof QueryFields
171
+
135
172
  /**
136
173
  * Builds a lucene JSON query from the filter structure generated in the builder
137
174
  * @param filter the builder filter structure
@@ -193,7 +230,7 @@ export const buildLuceneQuery = (filter: Filter[]) => {
193
230
  ) {
194
231
  value = value.split(",")
195
232
  }
196
- if (operator.startsWith("range")) {
233
+ if (operator.startsWith("range") && query.range) {
197
234
  const minint =
198
235
  SqlNumberTypeRangeMap[externalType]?.min || Number.MIN_SAFE_INTEGER
199
236
  const maxint =
@@ -219,14 +256,18 @@ export const buildLuceneQuery = (filter: Filter[]) => {
219
256
  // "equals false" needs to be "not equals true"
220
257
  // "not equals false" needs to be "equals true"
221
258
  if (operator === "equal" && value === false) {
259
+ query.notEqual = query.notEqual || {}
222
260
  query.notEqual[field] = true
223
261
  } else if (operator === "notEqual" && value === false) {
262
+ query.equal = query.equal || {}
224
263
  query.equal[field] = true
225
264
  } else {
226
- query[operator][field] = value
265
+ query[operator] = query[operator] || {}
266
+ query[operator]![field] = value
227
267
  }
228
268
  } else {
229
- query[operator][field] = value
269
+ query[operator] = query[operator] || {}
270
+ query[operator]![field] = value
230
271
  }
231
272
  }
232
273
  })
@@ -234,29 +275,12 @@ export const buildLuceneQuery = (filter: Filter[]) => {
234
275
  return query
235
276
  }
236
277
 
237
- const deepGet = (obj: { [x: string]: any }, key: string) => {
238
- if (!obj || !key) {
239
- return null
240
- }
241
- if (Object.prototype.hasOwnProperty.call(obj, key)) {
242
- return obj[key]
243
- }
244
- const split = key.split(".")
245
- for (let i = 0; i < split.length; i++) {
246
- obj = obj?.[split[i]]
247
- }
248
- return obj
249
- }
250
-
251
278
  /**
252
279
  * Performs a client-side lucene search on an array of data
253
280
  * @param docs the data
254
281
  * @param query the JSON lucene query
255
282
  */
256
- export const runLuceneQuery = (
257
- docs: any[],
258
- query?: { [x: string]: any; sheet?: string }
259
- ) => {
283
+ export const runLuceneQuery = (docs: any[], query?: Query) => {
260
284
  if (!docs || !Array.isArray(docs)) {
261
285
  return []
262
286
  }
@@ -269,7 +293,10 @@ export const runLuceneQuery = (
269
293
 
270
294
  // Iterates over a set of filters and evaluates a fail function against a doc
271
295
  const match =
272
- (type: string, failFn: (docValue: any, testValue: any) => boolean) =>
296
+ (
297
+ type: QueryFieldsType,
298
+ failFn: (docValue: any, testValue: any) => boolean
299
+ ) =>
273
300
  (doc: any) => {
274
301
  const filters = Object.entries(query![type] || {})
275
302
  for (let i = 0; i < filters.length; i++) {
@@ -398,9 +425,9 @@ export const runLuceneQuery = (
398
425
  */
399
426
  export const luceneSort = (
400
427
  docs: any[],
401
- sort: string | number,
402
- sortOrder: string,
403
- sortType = "string"
428
+ sort: string,
429
+ sortOrder: SortDirection,
430
+ sortType = SortType.STRING
404
431
  ) => {
405
432
  if (!sort || !sortOrder || !sortType) {
406
433
  return docs
@@ -412,7 +439,7 @@ export const luceneSort = (
412
439
  .sort((a: { [x: string]: any }, b: { [x: string]: any }) => {
413
440
  const colA = parse(a[sort])
414
441
  const colB = parse(b[sort])
415
- if (sortOrder === "Descending") {
442
+ if (sortOrder.toLowerCase() === "descending") {
416
443
  return colA > colB ? -1 : 1
417
444
  } else {
418
445
  return colA > colB ? 1 : -1
@@ -426,7 +453,7 @@ export const luceneSort = (
426
453
  * @param docs the data
427
454
  * @param limit the number of docs to limit to
428
455
  */
429
- export const luceneLimit = (docs: string | any[], limit: string) => {
456
+ export const luceneLimit = (docs: any[], limit: string) => {
430
457
  const numLimit = parseFloat(limit)
431
458
  if (isNaN(numLimit)) {
432
459
  return docs
package/src/helpers.ts ADDED
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Gets a key within an object. The key supports dot syntax for retrieving deep
3
+ * fields - e.g. "a.b.c".
4
+ * Exact matches of keys with dots in them take precedence over nested keys of
5
+ * the same path - e.g. getting "a.b" from { "a.b": "foo", a: { b: "bar" } }
6
+ * will return "foo" over "bar".
7
+ * @param obj the object
8
+ * @param key the key
9
+ * @return {*|null} the value or null if a value was not found for this key
10
+ */
11
+ export const deepGet = (obj: { [x: string]: any }, key: string) => {
12
+ if (!obj || !key) {
13
+ return null
14
+ }
15
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
16
+ return obj[key]
17
+ }
18
+ const split = key.split(".")
19
+ for (let i = 0; i < split.length; i++) {
20
+ obj = obj?.[split[i]]
21
+ }
22
+ return obj
23
+ }
package/src/index.ts CHANGED
@@ -1,2 +1,4 @@
1
1
  export * from "./constants"
2
2
  export * as dataFilters from "./filters"
3
+ export * as helpers from "./helpers"
4
+ export * as utils from "./utils"
package/src/utils.ts ADDED
@@ -0,0 +1,6 @@
1
+ export function unreachable(
2
+ value: never,
3
+ message = `No such case in exhaustive switch: ${value}`
4
+ ) {
5
+ throw new Error(message)
6
+ }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "compilerOptions": {
3
3
  "target": "es6",
4
- "module": "commonjs",
4
+ "moduleResolution": "node",
5
5
  "lib": ["es2020"],
6
6
  "strict": true,
7
7
  "noImplicitAny": true,
package/tsconfig.json CHANGED
@@ -1,6 +1,11 @@
1
1
  {
2
2
  "extends": "./tsconfig.build.json",
3
3
  "compilerOptions": {
4
- "composite": true
5
- }
4
+ "composite": true,
5
+ "baseUrl": ".",
6
+ "paths": {
7
+ "@budibase/types": ["../types/src"]
8
+ }
9
+ },
10
+ "references": [{ "path": "../types" }]
6
11
  }
package/dist/src/index.js DELETED
@@ -1,32 +0,0 @@
1
- "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
- var __exportStar = (this && this.__exportStar) || function(m, exports) {
19
- for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
20
- };
21
- var __importStar = (this && this.__importStar) || function (mod) {
22
- if (mod && mod.__esModule) return mod;
23
- var result = {};
24
- if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
25
- __setModuleDefault(result, mod);
26
- return result;
27
- };
28
- Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.dataFilters = void 0;
30
- __exportStar(require("./constants"), exports);
31
- exports.dataFilters = __importStar(require("./filters"));
32
- //# sourceMappingURL=index.js.map