@mintlify/common 1.0.1309 → 1.0.1311

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 (56) 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/mdx/snippets/resolveAllImports.d.ts +1 -0
  54. package/dist/mdx/snippets/resolveAllImports.js +9 -7
  55. package/dist/tsconfig.build.tsbuildinfo +1 -1
  56. package/package.json +10 -2
@@ -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
+ };
@@ -5,6 +5,7 @@ import { type PackageImportOptions } from '../islands/packageImports.js';
5
5
  export type ResolveImportsWarning = {
6
6
  type: 'invalid-import-path' | 'missing-file' | 'import-resolution-error' | 'default-import-no-default-export' | 'export-collision' | 'undeclared-package' | 'package-import-conflict';
7
7
  message: string;
8
+ file?: string;
8
9
  };
9
10
  export declare const resolveAllImports: (params: {
10
11
  snippets: (FileType & {
@@ -10,6 +10,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  import { jsx, toJs } from 'estree-util-to-js';
11
11
  import { remove } from 'unist-util-remove';
12
12
  import { visit } from 'unist-util-visit';
13
+ import { normalizeRelativePath } from '../../fs/normalizeRelativePath.js';
13
14
  import { MdxImportSpecifier } from '../../types/mdx/snippets/import.js';
14
15
  import { createImportNode, isDeclaredPackageImport, isNonHostBareImport, mergeImports, } from '../islands/packageImports.js';
15
16
  import { estreeIsProgram, isImportDeclaration, isMdxJsEsm } from '../utils.js';
@@ -109,6 +110,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
109
110
  var _a;
110
111
  var _b, _c, _d, _e;
111
112
  const { snippets, fileWithImports, onWarning, packages } = params;
113
+ const file = normalizeRelativePath(fileWithImports.filename);
112
114
  let ast = fileWithImports.tree;
113
115
  const kept = packages && /\.mdx?$/.test(fileWithImports.filename)
114
116
  ? takePackageReExports(ast, packages.packageNames)
@@ -125,7 +127,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
125
127
  }
126
128
  const message = `Package ${(_c = getSpecifierPackageName(source)) !== null && _c !== void 0 ? _c : source} imported in ${fileWithImports.filename} is not declared in package.json dependencies.`;
127
129
  if (onWarning) {
128
- onWarning({ type: 'undeclared-package', message });
130
+ onWarning({ type: 'undeclared-package', message, file });
129
131
  }
130
132
  else {
131
133
  console.log(message);
@@ -139,7 +141,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
139
141
  if (resolvedPath == null) {
140
142
  const message = `Invalid import path ${source} in ${fileWithImports.filename}. Only local imports are supported.`;
141
143
  if (onWarning) {
142
- onWarning({ type: 'invalid-import-path', message });
144
+ onWarning({ type: 'invalid-import-path', message, file });
143
145
  }
144
146
  else {
145
147
  console.log(message);
@@ -150,7 +152,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
150
152
  if (foundSnippet == undefined) {
151
153
  const message = `Could not find file ${resolvedPath} - imported from ${fileWithImports.filename}`;
152
154
  if (onWarning) {
153
- onWarning({ type: 'missing-file', message });
155
+ onWarning({ type: 'missing-file', message, file });
154
156
  }
155
157
  else {
156
158
  console.log(message);
@@ -178,7 +180,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
178
180
  importedSnippet.tree.children.every((node) => node.type === 'yaml' || node.type === 'mdxjsEsm')) {
179
181
  const message = `Default import "${specifier.name}" in ${fileWithImports.filename} will not render — ${resolvedPath} has no default export. Use a named import instead: import { ExportName } from '${source}'`;
180
182
  if (onWarning) {
181
- onWarning({ type: 'default-import-no-default-export', message });
183
+ onWarning({ type: 'default-import-no-default-export', message, file });
182
184
  }
183
185
  else {
184
186
  console.log(message);
@@ -187,7 +189,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
187
189
  try {
188
190
  const contentWithResolvedImport = yield resolveImport(specifier, ast, importedSnippet.tree, exportMap, (warning) => {
189
191
  // the collision itself doesn't know which page it happened in, so add it here
190
- const located = Object.assign(Object.assign({}, warning), { message: `${warning.message} (in ${fileWithImports.filename}, importing ${resolvedPath})` });
192
+ const located = Object.assign(Object.assign({}, warning), { message: `${warning.message} (in ${fileWithImports.filename}, importing ${resolvedPath})`, file });
191
193
  if (onWarning) {
192
194
  onWarning(located);
193
195
  }
@@ -203,7 +205,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
203
205
  catch (err) {
204
206
  const message = `Error resolving import "${specifier.name}" in ${fileWithImports.filename}: ${err instanceof Error ? err.message : String(err)}`;
205
207
  if (onWarning) {
206
- onWarning({ type: 'import-resolution-error', message });
208
+ onWarning({ type: 'import-resolution-error', message, file });
207
209
  }
208
210
  else {
209
211
  console.log(message);
@@ -221,7 +223,7 @@ export const resolveAllImports = (params) => __awaiter(void 0, void 0, void 0, f
221
223
  for (const { local, first, second } of conflicts) {
222
224
  const message = `${local} is imported twice in ${fileWithImports.filename}, as ${first} and as ${second}. Snippets inlined into a page share its imports, so import one of them under another name.`;
223
225
  if (onWarning) {
224
- onWarning({ type: 'package-import-conflict', message });
226
+ onWarning({ type: 'package-import-conflict', message, file });
225
227
  }
226
228
  else {
227
229
  console.log(message);