@mintlify/common 1.0.1310 → 1.0.1312

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.
Files changed (54) hide show
  1. package/dist/databases/formula/analyze.d.ts +31 -0
  2. package/dist/databases/formula/analyze.js +296 -0
  3. package/dist/databases/formula/ast.d.ts +52 -0
  4. package/dist/databases/formula/ast.js +20 -0
  5. package/dist/databases/formula/compile.d.ts +10 -0
  6. package/dist/databases/formula/compile.js +409 -0
  7. package/dist/databases/formula/dates.d.ts +5 -0
  8. package/dist/databases/formula/dates.js +55 -0
  9. package/dist/databases/formula/errors.d.ts +18 -0
  10. package/dist/databases/formula/errors.js +33 -0
  11. package/dist/databases/formula/filter.d.ts +9 -0
  12. package/dist/databases/formula/filter.js +16 -0
  13. package/dist/databases/formula/format.d.ts +5 -0
  14. package/dist/databases/formula/format.js +66 -0
  15. package/dist/databases/formula/function-docs.d.ts +6 -0
  16. package/dist/databases/formula/function-docs.js +63 -0
  17. package/dist/databases/formula/functions.d.ts +21 -0
  18. package/dist/databases/formula/functions.js +161 -0
  19. package/dist/databases/formula/highlight.d.ts +7 -0
  20. package/dist/databases/formula/highlight.js +54 -0
  21. package/dist/databases/formula/index.d.ts +16 -0
  22. package/dist/databases/formula/index.js +14 -0
  23. package/dist/databases/formula/limits.d.ts +8 -0
  24. package/dist/databases/formula/limits.js +8 -0
  25. package/dist/databases/formula/lower.d.ts +9 -0
  26. package/dist/databases/formula/lower.js +252 -0
  27. package/dist/databases/formula/parse.d.ts +21 -0
  28. package/dist/databases/formula/parse.js +209 -0
  29. package/dist/databases/formula/references.d.ts +20 -0
  30. package/dist/databases/formula/references.js +76 -0
  31. package/dist/databases/formula/rewrite.d.ts +16 -0
  32. package/dist/databases/formula/rewrite.js +29 -0
  33. package/dist/databases/formula/schema.d.ts +29 -0
  34. package/dist/databases/formula/schema.js +117 -0
  35. package/dist/databases/formula/tokenize.d.ts +11 -0
  36. package/dist/databases/formula/tokenize.js +114 -0
  37. package/dist/databases/formula/typecheck.d.ts +11 -0
  38. package/dist/databases/formula/typecheck.js +16 -0
  39. package/dist/databases/formula/types.d.ts +26 -0
  40. package/dist/databases/formula/types.js +27 -0
  41. package/dist/databases/formula/values.d.ts +8 -0
  42. package/dist/databases/formula/values.js +100 -0
  43. package/dist/databases/query/evaluate.d.ts +25 -0
  44. package/dist/databases/query/evaluate.js +481 -0
  45. package/dist/databases/query/index.d.ts +4 -0
  46. package/dist/databases/query/index.js +4 -0
  47. package/dist/databases/query/types.d.ts +69 -0
  48. package/dist/databases/query/types.js +20 -0
  49. package/dist/databases/query/validate.d.ts +8 -0
  50. package/dist/databases/query/validate.js +138 -0
  51. package/dist/databases/query/values.d.ts +4 -0
  52. package/dist/databases/query/values.js +36 -0
  53. package/dist/tsconfig.build.tsbuildinfo +1 -1
  54. package/package.json +13 -5
@@ -0,0 +1,69 @@
1
+ export type QueryValue = string | number | boolean | null;
2
+ export declare const COMPARE_OPS: readonly ['eq', 'ne', 'lt', 'lte', 'gt', 'gte'];
3
+ export type CompareOp = (typeof COMPARE_OPS)[number];
4
+ export declare const TEXT_OPS: readonly ['contains', 'startsWith', 'endsWith'];
5
+ export type TextOp = (typeof TEXT_OPS)[number];
6
+ export type QueryExpr = {
7
+ kind: 'column';
8
+ id: string;
9
+ } | {
10
+ kind: 'literal';
11
+ value: QueryValue;
12
+ } | {
13
+ kind: 'and' | 'or';
14
+ args: QueryExpr[];
15
+ } | {
16
+ kind: 'not';
17
+ arg: QueryExpr;
18
+ } | {
19
+ kind: 'compare';
20
+ op: CompareOp;
21
+ left: QueryExpr;
22
+ right: QueryExpr;
23
+ } | {
24
+ kind: 'text';
25
+ op: TextOp;
26
+ left: QueryExpr;
27
+ right: QueryExpr;
28
+ } | {
29
+ kind: 'isEmpty';
30
+ arg: QueryExpr;
31
+ } | {
32
+ kind: 'in';
33
+ arg: QueryExpr;
34
+ values: QueryValue[];
35
+ };
36
+ export type SortDirection = 'asc' | 'desc';
37
+ export type QuerySort = {
38
+ columnId: string;
39
+ direction: SortDirection;
40
+ }[];
41
+ export declare const AGGREGATE_FNS: readonly ['count', 'count_empty', 'count_filled', 'sum', 'avg', 'min', 'max'];
42
+ export type AggregateFn = (typeof AGGREGATE_FNS)[number];
43
+ export type QueryAggregate = {
44
+ columnId: string;
45
+ fn: AggregateFn;
46
+ };
47
+ export type QueryRequest = {
48
+ filter?: QueryExpr;
49
+ sort?: QuerySort;
50
+ aggregates?: QueryAggregate[];
51
+ };
52
+ export type QueryColumn = {
53
+ id: string;
54
+ type: string;
55
+ };
56
+ export type QueryRow = {
57
+ id: string;
58
+ createdAt: string;
59
+ columns: Readonly<Record<string, unknown>>;
60
+ };
61
+ export declare const QUERY_LIMITS: {
62
+ readonly depth: 16;
63
+ readonly nodes: 256;
64
+ readonly inValues: 200;
65
+ readonly sortKeys: 3;
66
+ readonly aggregates: 64;
67
+ readonly literalLength: 10000;
68
+ };
69
+ export declare const CLIENT_ONLY = "formula columns are client-only";
@@ -0,0 +1,20 @@
1
+ export const COMPARE_OPS = ['eq', 'ne', 'lt', 'lte', 'gt', 'gte'];
2
+ export const TEXT_OPS = ['contains', 'startsWith', 'endsWith'];
3
+ export const AGGREGATE_FNS = [
4
+ 'count',
5
+ 'count_empty',
6
+ 'count_filled',
7
+ 'sum',
8
+ 'avg',
9
+ 'min',
10
+ 'max',
11
+ ];
12
+ export const QUERY_LIMITS = {
13
+ depth: 16,
14
+ nodes: 256,
15
+ inValues: 200,
16
+ sortKeys: 3,
17
+ aggregates: 64,
18
+ literalLength: 10000,
19
+ };
20
+ export const CLIENT_ONLY = 'formula columns are client-only';
@@ -0,0 +1,8 @@
1
+ import { type QueryRequest } from './types.js';
2
+ export type QueryError = {
3
+ message: string;
4
+ fields: Record<string, string>;
5
+ };
6
+ export declare const validateQueryExpr: (expr: unknown, path?: string) => QueryError | null;
7
+ export declare const validateQueryRequest: (request: unknown) => QueryError | null;
8
+ export declare const isValidQueryRequest: (request: unknown) => request is QueryRequest;
@@ -0,0 +1,138 @@
1
+ import { AGGREGATE_FNS, COMPARE_OPS, QUERY_LIMITS, TEXT_OPS, } from './types.js';
2
+ const COMPARE = new Set(COMPARE_OPS);
3
+ const TEXT = new Set(TEXT_OPS);
4
+ const FNS = new Set(AGGREGATE_FNS);
5
+ const DIRECTIONS = new Set(['asc', 'desc']);
6
+ const isRecord = (value) => typeof value === 'object' && value !== null && !Array.isArray(value);
7
+ const own = (record, key) => Object.hasOwn(record, key) ? record[key] : undefined;
8
+ const isValue = (value) => value === null ||
9
+ typeof value === 'boolean' ||
10
+ (typeof value === 'number' && Number.isFinite(value)) ||
11
+ (typeof value === 'string' && value.length <= QUERY_LIMITS.literalLength);
12
+ class Fields {
13
+ constructor() {
14
+ this.fields = {};
15
+ }
16
+ fail(path, message) {
17
+ if (!Object.hasOwn(this.fields, path))
18
+ this.fields[path] = message;
19
+ }
20
+ error() {
21
+ return Object.keys(this.fields).length
22
+ ? { message: 'query is invalid', fields: this.fields }
23
+ : null;
24
+ }
25
+ }
26
+ const checkExpr = (root, at, out) => {
27
+ const pending = [
28
+ { node: root, path: at, depth: 1 },
29
+ ];
30
+ let nodes = 0;
31
+ for (let next = pending.pop(); next; next = pending.pop()) {
32
+ const { node, path, depth } = next;
33
+ if (++nodes > QUERY_LIMITS.nodes)
34
+ return out.fail(at, `has more than ${QUERY_LIMITS.nodes} nodes`);
35
+ if (depth > QUERY_LIMITS.depth)
36
+ return out.fail(at, `nests deeper than ${QUERY_LIMITS.depth}`);
37
+ if (!isRecord(node)) {
38
+ out.fail(path, 'expected an expression');
39
+ continue;
40
+ }
41
+ const child = (key) => pending.push({ node: own(node, key), path: `${path}.${key}`, depth: depth + 1 });
42
+ const kind = own(node, 'kind');
43
+ switch (kind) {
44
+ case 'column':
45
+ if (typeof own(node, 'id') !== 'string')
46
+ out.fail(`${path}.id`, 'expected a column id');
47
+ break;
48
+ case 'literal':
49
+ if (!isValue(own(node, 'value'))) {
50
+ out.fail(`${path}.value`, 'expected a string, number, boolean or null');
51
+ }
52
+ break;
53
+ case 'and':
54
+ case 'or': {
55
+ const args = own(node, 'args');
56
+ if (!Array.isArray(args)) {
57
+ out.fail(`${path}.args`, 'expected a list of expressions');
58
+ break;
59
+ }
60
+ if (nodes + pending.length + args.length > QUERY_LIMITS.nodes) {
61
+ return out.fail(at, `has more than ${QUERY_LIMITS.nodes} nodes`);
62
+ }
63
+ args.forEach((arg, index) => pending.push({ node: arg, path: `${path}.args.${index}`, depth: depth + 1 }));
64
+ break;
65
+ }
66
+ case 'not':
67
+ case 'isEmpty':
68
+ child('arg');
69
+ break;
70
+ case 'compare':
71
+ case 'text':
72
+ if (!(kind === 'compare' ? COMPARE : TEXT).has(own(node, 'op'))) {
73
+ out.fail(`${path}.op`, `unknown ${kind} operator`);
74
+ }
75
+ child('left');
76
+ child('right');
77
+ break;
78
+ case 'in': {
79
+ child('arg');
80
+ const values = own(node, 'values');
81
+ if (!Array.isArray(values) || !values.every(isValue)) {
82
+ out.fail(`${path}.values`, 'expected a list of values');
83
+ }
84
+ else if (values.length > QUERY_LIMITS.inValues) {
85
+ out.fail(`${path}.values`, `at most ${QUERY_LIMITS.inValues} values`);
86
+ }
87
+ break;
88
+ }
89
+ default:
90
+ out.fail(`${path}.kind`, 'unknown expression kind');
91
+ }
92
+ }
93
+ };
94
+ const checkList = (value, path, limit, noun, out, item) => {
95
+ if (value === undefined)
96
+ return;
97
+ if (!Array.isArray(value))
98
+ return out.fail(path, `expected a list of ${noun}`);
99
+ if (value.length > limit)
100
+ return out.fail(path, `at most ${limit} ${noun}`);
101
+ value.forEach((entry, index) => {
102
+ const at = `${path}.${index}`;
103
+ if (!isRecord(entry))
104
+ out.fail(at, 'expected an object');
105
+ else
106
+ item(entry, at);
107
+ });
108
+ };
109
+ export const validateQueryExpr = (expr, path = 'filter') => {
110
+ const out = new Fields();
111
+ checkExpr(expr, path, out);
112
+ return out.error();
113
+ };
114
+ export const validateQueryRequest = (request) => {
115
+ const out = new Fields();
116
+ if (!isRecord(request)) {
117
+ out.fail('request', 'expected an object');
118
+ return out.error();
119
+ }
120
+ const filter = own(request, 'filter');
121
+ if (filter !== undefined)
122
+ checkExpr(filter, 'filter', out);
123
+ checkList(own(request, 'sort'), 'sort', QUERY_LIMITS.sortKeys, 'sort keys', out, (key, at) => {
124
+ if (typeof own(key, 'columnId') !== 'string')
125
+ out.fail(`${at}.columnId`, 'expected a column id');
126
+ if (!DIRECTIONS.has(own(key, 'direction')))
127
+ out.fail(`${at}.direction`, 'expected asc or desc');
128
+ });
129
+ checkList(own(request, 'aggregates'), 'aggregates', QUERY_LIMITS.aggregates, 'aggregates', out, (aggregate, at) => {
130
+ if (typeof own(aggregate, 'columnId') !== 'string') {
131
+ out.fail(`${at}.columnId`, 'expected a column id');
132
+ }
133
+ if (!FNS.has(own(aggregate, 'fn')))
134
+ out.fail(`${at}.fn`, 'unknown aggregate');
135
+ });
136
+ return out.error();
137
+ };
138
+ export const isValidQueryRequest = (request) => validateQueryRequest(request) === null;
@@ -0,0 +1,4 @@
1
+ export declare const normalizeDate: (value: unknown) => string | null;
2
+ export declare const isEmptyValue: (value: unknown) => boolean;
3
+ export declare const asciiLower: (value: string) => string;
4
+ export declare const compareCodePoints: (a: string, b: string) => -1 | 0 | 1;
@@ -0,0 +1,36 @@
1
+ const ISO_DATE = /^(\d{4})-(\d{2})-(\d{2})(?:T\d{2}:\d{2}(?::\d{2}(?:\.\d{1,3})?)?(?:Z|[+-]\d{2}:\d{2}))?$/;
2
+ export const normalizeDate = (value) => {
3
+ if (typeof value !== 'string')
4
+ return null;
5
+ const match = ISO_DATE.exec(value);
6
+ if (!match)
7
+ return null;
8
+ const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
9
+ const calendar = new Date(Date.UTC(year, month - 1, day));
10
+ const valid = calendar.getUTCFullYear() === year &&
11
+ calendar.getUTCMonth() === month - 1 &&
12
+ calendar.getUTCDate() === day;
13
+ const time = Date.parse(value);
14
+ return valid && !Number.isNaN(time) ? new Date(time).toISOString() : null;
15
+ };
16
+ export const isEmptyValue = (value) => value === null ||
17
+ value === undefined ||
18
+ value === '' ||
19
+ (Array.isArray(value) && value.length === 0);
20
+ const UPPER = /[A-Z]/;
21
+ export const asciiLower = (value) => UPPER.test(value)
22
+ ? value.replace(/[A-Z]/g, (char) => String.fromCharCode(char.charCodeAt(0) + 32))
23
+ : value;
24
+ export const compareCodePoints = (a, b) => {
25
+ var _a, _b;
26
+ const length = Math.min(a.length, b.length);
27
+ for (let index = 0; index < length; index++) {
28
+ const left = (_a = a.codePointAt(index)) !== null && _a !== void 0 ? _a : 0;
29
+ const right = (_b = b.codePointAt(index)) !== null && _b !== void 0 ? _b : 0;
30
+ if (left !== right)
31
+ return left < right ? -1 : 1;
32
+ if (left > 0xffff)
33
+ index++;
34
+ }
35
+ return a.length === b.length ? 0 : a.length < b.length ? -1 : 1;
36
+ };