@teleporthq/teleport-plugin-next-data-source 0.42.35 → 0.43.3
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/__tests__/ecommerce-product-out-of-stock.test.ts +112 -0
- package/__tests__/fetchers.test.ts +0 -42
- package/__tests__/filter-utils.test.ts +149 -0
- package/__tests__/mocks.ts +0 -12
- package/__tests__/utils.test.ts +0 -2
- package/dist/cjs/array-mapper-registry.d.ts +2 -0
- package/dist/cjs/array-mapper-registry.d.ts.map +1 -1
- package/dist/cjs/array-mapper-registry.js +9 -1
- package/dist/cjs/array-mapper-registry.js.map +1 -1
- package/dist/cjs/count-fetchers.d.ts +2 -2
- package/dist/cjs/count-fetchers.d.ts.map +1 -1
- package/dist/cjs/count-fetchers.js +5 -5
- package/dist/cjs/count-fetchers.js.map +1 -1
- package/dist/cjs/data-source-fetchers.d.ts +2 -1
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +11 -9
- package/dist/cjs/data-source-fetchers.js.map +1 -1
- package/dist/cjs/fetchers/airtable.d.ts.map +1 -1
- package/dist/cjs/fetchers/airtable.js +1 -1
- package/dist/cjs/fetchers/airtable.js.map +1 -1
- package/dist/cjs/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/cjs/fetchers/clickhouse.js +1 -1
- package/dist/cjs/fetchers/clickhouse.js.map +1 -1
- package/dist/cjs/fetchers/csv-file.js +1 -1
- package/dist/cjs/fetchers/csv-file.js.map +1 -1
- package/dist/cjs/fetchers/firestore.js +1 -1
- package/dist/cjs/fetchers/firestore.js.map +1 -1
- package/dist/cjs/fetchers/google-sheets.js +1 -1
- package/dist/cjs/fetchers/google-sheets.js.map +1 -1
- package/dist/cjs/fetchers/index.d.ts +2 -1
- package/dist/cjs/fetchers/index.d.ts.map +1 -1
- package/dist/cjs/fetchers/index.js +8 -5
- package/dist/cjs/fetchers/index.js.map +1 -1
- package/dist/cjs/fetchers/javascript.js +1 -1
- package/dist/cjs/fetchers/javascript.js.map +1 -1
- package/dist/cjs/fetchers/mariadb.d.ts.map +1 -1
- package/dist/cjs/fetchers/mariadb.js +3 -3
- package/dist/cjs/fetchers/mariadb.js.map +1 -1
- package/dist/cjs/fetchers/mongodb.js +1 -1
- package/dist/cjs/fetchers/mongodb.js.map +1 -1
- package/dist/cjs/fetchers/mysql.d.ts.map +1 -1
- package/dist/cjs/fetchers/mysql.js +2 -2
- package/dist/cjs/fetchers/mysql.js.map +1 -1
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +2 -2
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/raw-query.d.ts +18 -0
- package/dist/cjs/fetchers/raw-query.d.ts.map +1 -0
- package/dist/cjs/fetchers/raw-query.js +70 -0
- package/dist/cjs/fetchers/raw-query.js.map +1 -0
- package/dist/cjs/fetchers/redis.js +1 -1
- package/dist/cjs/fetchers/redis.js.map +1 -1
- package/dist/cjs/fetchers/redshift.d.ts.map +1 -1
- package/dist/cjs/fetchers/redshift.js +2 -2
- package/dist/cjs/fetchers/redshift.js.map +1 -1
- package/dist/cjs/fetchers/rest-api.js +1 -1
- package/dist/cjs/fetchers/rest-api.js.map +1 -1
- package/dist/cjs/fetchers/supabase.d.ts.map +1 -1
- package/dist/cjs/fetchers/supabase.js +62 -2
- package/dist/cjs/fetchers/supabase.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts +7 -0
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -0
- package/dist/cjs/fetchers/teleport.js +63 -0
- package/dist/cjs/fetchers/teleport.js.map +1 -0
- package/dist/cjs/fetchers/turso.d.ts.map +1 -1
- package/dist/cjs/fetchers/turso.js +1 -1
- package/dist/cjs/fetchers/turso.js.map +1 -1
- package/dist/cjs/filter-utils.d.ts +13 -0
- package/dist/cjs/filter-utils.d.ts.map +1 -0
- package/dist/cjs/filter-utils.js +95 -0
- package/dist/cjs/filter-utils.js.map +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +112 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +389 -128
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/sort-utils.d.ts +10 -0
- package/dist/cjs/sort-utils.d.ts.map +1 -0
- package/dist/cjs/sort-utils.js +141 -0
- package/dist/cjs/sort-utils.js.map +1 -0
- package/dist/cjs/transformations/blog-post.d.ts +7 -0
- package/dist/cjs/transformations/blog-post.d.ts.map +1 -0
- package/dist/cjs/transformations/blog-post.js +13 -0
- package/dist/cjs/transformations/blog-post.js.map +1 -0
- package/dist/cjs/transformations/ecommerce-product.d.ts +7 -0
- package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -0
- package/dist/cjs/transformations/ecommerce-product.js +13 -0
- package/dist/cjs/transformations/ecommerce-product.js.map +1 -0
- package/dist/cjs/transformations/index.d.ts +26 -0
- package/dist/cjs/transformations/index.d.ts.map +1 -0
- package/dist/cjs/transformations/index.js +81 -0
- package/dist/cjs/transformations/index.js.map +1 -0
- package/dist/cjs/transformations/shared-utils.d.ts +7 -0
- package/dist/cjs/transformations/shared-utils.d.ts.map +1 -0
- package/dist/cjs/transformations/shared-utils.js +13 -0
- package/dist/cjs/transformations/shared-utils.js.map +1 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +30 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +173 -10
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/array-mapper-registry.d.ts +2 -0
- package/dist/esm/array-mapper-registry.d.ts.map +1 -1
- package/dist/esm/array-mapper-registry.js +9 -1
- package/dist/esm/array-mapper-registry.js.map +1 -1
- package/dist/esm/count-fetchers.d.ts +2 -2
- package/dist/esm/count-fetchers.d.ts.map +1 -1
- package/dist/esm/count-fetchers.js +4 -4
- package/dist/esm/count-fetchers.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts +2 -1
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +10 -9
- package/dist/esm/data-source-fetchers.js.map +1 -1
- package/dist/esm/fetchers/airtable.d.ts.map +1 -1
- package/dist/esm/fetchers/airtable.js +1 -1
- package/dist/esm/fetchers/airtable.js.map +1 -1
- package/dist/esm/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/esm/fetchers/clickhouse.js +1 -1
- package/dist/esm/fetchers/clickhouse.js.map +1 -1
- package/dist/esm/fetchers/csv-file.js +1 -1
- package/dist/esm/fetchers/csv-file.js.map +1 -1
- package/dist/esm/fetchers/firestore.js +1 -1
- package/dist/esm/fetchers/firestore.js.map +1 -1
- package/dist/esm/fetchers/google-sheets.js +1 -1
- package/dist/esm/fetchers/google-sheets.js.map +1 -1
- package/dist/esm/fetchers/index.d.ts +2 -1
- package/dist/esm/fetchers/index.d.ts.map +1 -1
- package/dist/esm/fetchers/index.js +2 -1
- package/dist/esm/fetchers/index.js.map +1 -1
- package/dist/esm/fetchers/javascript.js +1 -1
- package/dist/esm/fetchers/javascript.js.map +1 -1
- package/dist/esm/fetchers/mariadb.d.ts.map +1 -1
- package/dist/esm/fetchers/mariadb.js +4 -4
- package/dist/esm/fetchers/mariadb.js.map +1 -1
- package/dist/esm/fetchers/mongodb.js +1 -1
- package/dist/esm/fetchers/mongodb.js.map +1 -1
- package/dist/esm/fetchers/mysql.d.ts.map +1 -1
- package/dist/esm/fetchers/mysql.js +3 -3
- package/dist/esm/fetchers/mysql.js.map +1 -1
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +3 -3
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/raw-query.d.ts +18 -0
- package/dist/esm/fetchers/raw-query.d.ts.map +1 -0
- package/dist/esm/fetchers/raw-query.js +65 -0
- package/dist/esm/fetchers/raw-query.js.map +1 -0
- package/dist/esm/fetchers/redis.js +1 -1
- package/dist/esm/fetchers/redis.js.map +1 -1
- package/dist/esm/fetchers/redshift.d.ts.map +1 -1
- package/dist/esm/fetchers/redshift.js +3 -3
- package/dist/esm/fetchers/redshift.js.map +1 -1
- package/dist/esm/fetchers/rest-api.js +1 -1
- package/dist/esm/fetchers/rest-api.js.map +1 -1
- package/dist/esm/fetchers/supabase.d.ts.map +1 -1
- package/dist/esm/fetchers/supabase.js +63 -3
- package/dist/esm/fetchers/supabase.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts +7 -0
- package/dist/esm/fetchers/teleport.d.ts.map +1 -0
- package/dist/esm/fetchers/teleport.js +57 -0
- package/dist/esm/fetchers/teleport.js.map +1 -0
- package/dist/esm/fetchers/turso.d.ts.map +1 -1
- package/dist/esm/fetchers/turso.js +2 -2
- package/dist/esm/fetchers/turso.js.map +1 -1
- package/dist/esm/filter-utils.d.ts +13 -0
- package/dist/esm/filter-utils.d.ts.map +1 -0
- package/dist/esm/filter-utils.js +66 -0
- package/dist/esm/filter-utils.js.map +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +113 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +389 -128
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/sort-utils.d.ts +10 -0
- package/dist/esm/sort-utils.d.ts.map +1 -0
- package/dist/esm/sort-utils.js +113 -0
- package/dist/esm/sort-utils.js.map +1 -0
- package/dist/esm/transformations/blog-post.d.ts +7 -0
- package/dist/esm/transformations/blog-post.d.ts.map +1 -0
- package/dist/esm/transformations/blog-post.js +9 -0
- package/dist/esm/transformations/blog-post.js.map +1 -0
- package/dist/esm/transformations/ecommerce-product.d.ts +7 -0
- package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -0
- package/dist/esm/transformations/ecommerce-product.js +9 -0
- package/dist/esm/transformations/ecommerce-product.js.map +1 -0
- package/dist/esm/transformations/index.d.ts +26 -0
- package/dist/esm/transformations/index.d.ts.map +1 -0
- package/dist/esm/transformations/index.js +74 -0
- package/dist/esm/transformations/index.js.map +1 -0
- package/dist/esm/transformations/shared-utils.d.ts +7 -0
- package/dist/esm/transformations/shared-utils.d.ts.map +1 -0
- package/dist/esm/transformations/shared-utils.js +9 -0
- package/dist/esm/transformations/shared-utils.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +30 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +170 -9
- package/dist/esm/utils.js.map +1 -1
- package/package.json +6 -5
- package/src/array-mapper-registry.ts +13 -0
- package/src/count-fetchers.ts +5 -5
- package/src/data-source-fetchers.ts +15 -11
- package/src/fetchers/airtable.ts +54 -8
- package/src/fetchers/clickhouse.ts +25 -19
- package/src/fetchers/csv-file.ts +2 -2
- package/src/fetchers/firestore.ts +2 -2
- package/src/fetchers/google-sheets.ts +2 -2
- package/src/fetchers/index.ts +6 -5
- package/src/fetchers/javascript.ts +2 -2
- package/src/fetchers/mariadb.ts +27 -12
- package/src/fetchers/mongodb.ts +2 -2
- package/src/fetchers/mysql.ts +27 -12
- package/src/fetchers/postgresql.ts +31 -18
- package/src/fetchers/raw-query.ts +178 -0
- package/src/fetchers/redis.ts +2 -2
- package/src/fetchers/redshift.ts +14 -10
- package/src/fetchers/rest-api.ts +2 -2
- package/src/fetchers/supabase.ts +97 -14
- package/src/fetchers/teleport.ts +485 -0
- package/src/fetchers/turso.ts +15 -7
- package/src/filter-utils.ts +111 -0
- package/src/index.ts +146 -6
- package/src/pagination-plugin.ts +547 -308
- package/src/sort-utils.ts +150 -0
- package/src/transformations/blog-post.ts +128 -0
- package/src/transformations/ecommerce-product.ts +173 -0
- package/src/transformations/index.ts +97 -0
- package/src/transformations/shared-utils.ts +271 -0
- package/src/utils.ts +227 -11
- package/dist/cjs/fetchers/static-collection.d.ts +0 -7
- package/dist/cjs/fetchers/static-collection.d.ts.map +0 -1
- package/dist/cjs/fetchers/static-collection.js +0 -25
- package/dist/cjs/fetchers/static-collection.js.map +0 -1
- package/dist/esm/fetchers/static-collection.d.ts +0 -7
- package/dist/esm/fetchers/static-collection.d.ts.map +0 -1
- package/dist/esm/fetchers/static-collection.js +0 -19
- package/dist/esm/fetchers/static-collection.js.map +0 -1
- package/src/fetchers/static-collection.ts +0 -231
|
@@ -36,10 +36,220 @@ var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
|
36
36
|
};
|
|
37
37
|
import { ChunkType, FileType, } from '@teleporthq/teleport-types';
|
|
38
38
|
import * as types from '@babel/types';
|
|
39
|
+
import { parseExpression } from '@babel/parser';
|
|
39
40
|
import { StringUtils } from '@teleporthq/teleport-shared';
|
|
40
41
|
import { ASTUtils } from '@teleporthq/teleport-plugin-common';
|
|
41
42
|
import { generateSafeFileName } from './utils';
|
|
42
43
|
import { generateDataSourceFetcherWithCore } from './data-source-fetchers';
|
|
44
|
+
import { appendSortsParam, extractDynamicSort } from './sort-utils';
|
|
45
|
+
import { appendFiltersParam, pushStateIdsAsDeps } from './filter-utils';
|
|
46
|
+
// tslint:disable-next-line:no-any
|
|
47
|
+
function parseSearchDefaultValue(raw) {
|
|
48
|
+
if (!raw || typeof raw !== 'object') {
|
|
49
|
+
return undefined;
|
|
50
|
+
}
|
|
51
|
+
if (raw.type === 'static' && typeof raw.content === 'string' && raw.content.length > 0) {
|
|
52
|
+
return { kind: 'static', value: raw.content };
|
|
53
|
+
}
|
|
54
|
+
if ((raw.type === 'expr' || raw.type === 'dynamic') && typeof raw.content === 'string') {
|
|
55
|
+
var src = raw.content.trim();
|
|
56
|
+
if (src.length === 0) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
try {
|
|
60
|
+
var ast = parseExpression(src, { sourceType: 'module', plugins: ['jsx'] });
|
|
61
|
+
return { kind: 'expression', ast: ast };
|
|
62
|
+
}
|
|
63
|
+
catch (_a) {
|
|
64
|
+
// Fall back to no seed if the expression is malformed — better to
|
|
65
|
+
// render an empty input than to emit broken code.
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return undefined;
|
|
70
|
+
}
|
|
71
|
+
function searchDefaultValueInitAST(value) {
|
|
72
|
+
if (!value) {
|
|
73
|
+
return types.stringLiteral('');
|
|
74
|
+
}
|
|
75
|
+
if (value.kind === 'static') {
|
|
76
|
+
return types.stringLiteral(value.value);
|
|
77
|
+
}
|
|
78
|
+
// Clone so multiple `useState(...)` call sites each get an
|
|
79
|
+
// independent AST node — Babel does not support shared references.
|
|
80
|
+
return types.cloneNode(value.ast, /* deep */ true);
|
|
81
|
+
}
|
|
82
|
+
// The UIDL's `filters.content` array can wrap one or more conditions inside
|
|
83
|
+
// a `{ type: 'group', operator: 'and' | 'or', children: [...] }` entry — the
|
|
84
|
+
// GUI builds this shape when the inspector adds a logical group. The data
|
|
85
|
+
// source API endpoint (`processFilters` in the generated data-source module)
|
|
86
|
+
// only knows how to consume a FLAT array of `{ source, destination, operand }`
|
|
87
|
+
// conditions, so we walk groups recursively here and collect their leaf
|
|
88
|
+
// conditions in order. Anything that isn't a group AND isn't a condition is
|
|
89
|
+
// dropped — defensive against partially-built filter entries that would
|
|
90
|
+
// otherwise emit `{ source: '', destination: '', operand: '' }` rows the
|
|
91
|
+
// API ignores anyway.
|
|
92
|
+
//
|
|
93
|
+
// `or`-grouped conditions are flattened just like `and`-grouped ones — the
|
|
94
|
+
// downstream SQL builder always joins flat filters with `AND`, so emitting
|
|
95
|
+
// the conditions side-by-side approximates AND semantics. A future API
|
|
96
|
+
// upgrade that respects group operators would key off the original tree
|
|
97
|
+
// directly; until then, AND-flattening is the closest correct behaviour and
|
|
98
|
+
// matches what the inspector preview shows for the common single-group case
|
|
99
|
+
// the GUI emits today.
|
|
100
|
+
function flattenFilterGroups(filters) {
|
|
101
|
+
if (!Array.isArray(filters)) {
|
|
102
|
+
return [];
|
|
103
|
+
}
|
|
104
|
+
var out = [];
|
|
105
|
+
var walk = function (entry) {
|
|
106
|
+
if (!entry || typeof entry !== 'object') {
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (entry.type === 'group' && Array.isArray(entry.children)) {
|
|
110
|
+
for (var _i = 0, _a = entry.children; _i < _a.length; _i++) {
|
|
111
|
+
var child = _a[_i];
|
|
112
|
+
walk(child);
|
|
113
|
+
}
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
// Backwards-compatible: entries without an explicit `type` (legacy flat
|
|
117
|
+
// form) and entries explicitly tagged `condition` are both treated as
|
|
118
|
+
// condition leaves.
|
|
119
|
+
if (entry.type === undefined || entry.type === 'condition') {
|
|
120
|
+
out.push(entry);
|
|
121
|
+
}
|
|
122
|
+
};
|
|
123
|
+
for (var _i = 0, filters_1 = filters; _i < filters_1.length; _i++) {
|
|
124
|
+
var entry = filters_1[_i];
|
|
125
|
+
walk(entry);
|
|
126
|
+
}
|
|
127
|
+
return out;
|
|
128
|
+
}
|
|
129
|
+
// Walks a flat filter list to extract every `urlSearchParams` reference key
|
|
130
|
+
// (e.g. `'categoryFilter'`). Used to (a) inject `const router = useRouter()`
|
|
131
|
+
// once at the top of the component, (b) wire `router.query.<key>` into the
|
|
132
|
+
// `useMemo` dependency array so the client-side fetch reruns whenever the
|
|
133
|
+
// buyer navigates to a URL with a different `?key=value`. Returned in the
|
|
134
|
+
// order keys first appear so the generated dep array stays stable.
|
|
135
|
+
function collectFilterUrlSearchParamKeys(filters) {
|
|
136
|
+
var seen = new Set();
|
|
137
|
+
var out = [];
|
|
138
|
+
for (var _i = 0, filters_2 = filters; _i < filters_2.length; _i++) {
|
|
139
|
+
var f = filters_2[_i];
|
|
140
|
+
var dest = f === null || f === void 0 ? void 0 : f.destination;
|
|
141
|
+
if (!ASTUtils.isUIDLDynamicReference(dest)) {
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
var content = dest.content;
|
|
145
|
+
if (!content || content.referenceType !== 'urlSearchParams' || !content.id) {
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
if (seen.has(content.id)) {
|
|
149
|
+
continue;
|
|
150
|
+
}
|
|
151
|
+
seen.add(content.id);
|
|
152
|
+
out.push(content.id);
|
|
153
|
+
}
|
|
154
|
+
return out;
|
|
155
|
+
}
|
|
156
|
+
// Returns true when any filter destination is a `urlSearchParams` dynamic
|
|
157
|
+
// reference — used by the plugin to know it needs to import `useRouter` and
|
|
158
|
+
// emit `const router = useRouter()` at the top of the component. Cheaper to
|
|
159
|
+
// test against the precomputed key list once than to walk all filters on
|
|
160
|
+
// every check.
|
|
161
|
+
function hasUrlSearchParamFilters(usage) {
|
|
162
|
+
return usage.filterUrlSearchParamKeys.length > 0;
|
|
163
|
+
}
|
|
164
|
+
// Appends `router.query.<key>` member expressions to a useMemo deps array so
|
|
165
|
+
// every client-side fetch refires when the buyer navigates between URLs
|
|
166
|
+
// that differ only by `?key=value`. React's shallow-compare semantics treat
|
|
167
|
+
// the member expression as a distinct value per render, so the array stays
|
|
168
|
+
// stable across paints with the same query string and changes the moment
|
|
169
|
+
// the URL does. Skip the bare-identifier dedupe `filterStateIds` uses —
|
|
170
|
+
// member expressions never collide with state identifiers, and the deps
|
|
171
|
+
// array allows duplicates without harm.
|
|
172
|
+
function pushUrlSearchParamMemoDeps(memoDeps, usage) {
|
|
173
|
+
for (var _i = 0, _a = usage.filterUrlSearchParamKeys; _i < _a.length; _i++) {
|
|
174
|
+
var key = _a[_i];
|
|
175
|
+
memoDeps.push(types.memberExpression(types.memberExpression(types.identifier('router'), types.identifier('query')), types.identifier(key)));
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
// Builds the AST for `!router.query.<key1> && !router.query.<key2> && ...`,
|
|
179
|
+
// used as a runtime guard around `initialData={props.X}` so the server-
|
|
180
|
+
// prefetched (unfiltered) data is only handed to `DataProvider` when the
|
|
181
|
+
// URL has no active filter. Without this guard, navigating to
|
|
182
|
+
// `/products-list?categoryFilter=Rings` (especially via soft Next.js
|
|
183
|
+
// transitions where the page component remounts with fresh getStaticProps
|
|
184
|
+
// but the buyer's URL filter is still in scope) shows the unfiltered list
|
|
185
|
+
// for the first paint AND keeps it on screen because `DataProvider`'s
|
|
186
|
+
// `passFetchBecauseWeHaveInitialData` ref skips the very first fetch when
|
|
187
|
+
// `initialData !== undefined`. By emitting `undefined` here whenever ANY
|
|
188
|
+
// url-search-param filter is set, the DataProvider's mount-time fetch runs
|
|
189
|
+
// immediately with the filtered params instead of presenting stale data.
|
|
190
|
+
//
|
|
191
|
+
// Returns `null` when the usage has no url-search-param filters at all —
|
|
192
|
+
// callers fall back to the existing `props.X` expression unchanged so
|
|
193
|
+
// non-filtered pages still benefit from the SSR prefetch.
|
|
194
|
+
function buildNoUrlFilterGuard(usage) {
|
|
195
|
+
if (usage.filterUrlSearchParamKeys.length === 0 && usage.filterStateIds.length === 0) {
|
|
196
|
+
return null;
|
|
197
|
+
}
|
|
198
|
+
var guards = [];
|
|
199
|
+
for (var _i = 0, _a = usage.filterUrlSearchParamKeys; _i < _a.length; _i++) {
|
|
200
|
+
var key = _a[_i];
|
|
201
|
+
guards.push(types.unaryExpression('!', types.memberExpression(types.memberExpression(types.identifier('router'), types.identifier('query')), types.identifier(key)), true));
|
|
202
|
+
}
|
|
203
|
+
// State-bound filter destinations (e.g. `selectedCategory`) emit as bare
|
|
204
|
+
// identifiers, so the corresponding guard is `!selectedCategory`. An empty
|
|
205
|
+
// string ('') for the state — which the GUI emits when the user picks the
|
|
206
|
+
// "All Categories" reset option — is falsy and so passes through the guard
|
|
207
|
+
// exactly like a missing URL param: initialData (unfiltered prefetch) wins
|
|
208
|
+
// until the user picks a real value.
|
|
209
|
+
for (var _b = 0, _c = usage.filterStateIds; _b < _c.length; _b++) {
|
|
210
|
+
var id = _c[_b];
|
|
211
|
+
guards.push(types.unaryExpression('!', types.identifier(id), true));
|
|
212
|
+
}
|
|
213
|
+
return guards.reduce(function (acc, next) { return types.logicalExpression('&&', acc, next); });
|
|
214
|
+
}
|
|
215
|
+
// Wraps an existing `initialData` condition with the additional "no URL
|
|
216
|
+
// filter active" guard so server-prefetched data is only handed to
|
|
217
|
+
// DataProvider when both (a) the original guard (page === 1, no search
|
|
218
|
+
// query, etc.) AND (b) every relevant `router.query.<key>` is falsy. See
|
|
219
|
+
// `buildNoUrlFilterGuard` for the rationale on why bare-identity feature
|
|
220
|
+
// detection is safer than the `dynamicSort`-style "always undefined" path.
|
|
221
|
+
function wrapInitialDataWithUrlFilterGuard(baseCondition, usage) {
|
|
222
|
+
var noFilterGuard = buildNoUrlFilterGuard(usage);
|
|
223
|
+
if (!noFilterGuard) {
|
|
224
|
+
return baseCondition;
|
|
225
|
+
}
|
|
226
|
+
return types.logicalExpression('&&', baseCondition, noFilterGuard);
|
|
227
|
+
}
|
|
228
|
+
// Builds the destination AST for a single filter entry. Replaces the bare
|
|
229
|
+
// `ASTUtils.convertFilterDestinationToExpression(filter.destination)` call
|
|
230
|
+
// at every emit site so `urlSearchParams` references resolve to
|
|
231
|
+
// `router?.query?.<key>` instead of falling through to a bare identifier
|
|
232
|
+
// (which the existing helper would emit, leaving the client-side fetch
|
|
233
|
+
// referencing an undeclared symbol).
|
|
234
|
+
//
|
|
235
|
+
// State and prop references delegate back to the shared helper so the
|
|
236
|
+
// existing inspector behaviour (state-bound filter destinations) keeps
|
|
237
|
+
// working unchanged. `router?.query?.<key>` is the same shape the
|
|
238
|
+
// `createNextUrlSearchParamsPlugin`-driven `dynamicReferencePrefixMap`
|
|
239
|
+
// emits for page-level navlink reads.
|
|
240
|
+
function buildFilterDestinationExpression(destination) {
|
|
241
|
+
if (ASTUtils.isUIDLDynamicReference(destination)) {
|
|
242
|
+
var content = destination.content;
|
|
243
|
+
if ((content === null || content === void 0 ? void 0 : content.referenceType) === 'urlSearchParams' && (content === null || content === void 0 ? void 0 : content.id)) {
|
|
244
|
+
// router?.query?.<id> — the optional-chain survives the first paint
|
|
245
|
+
// where Next.js's `useRouter()` returns `null` during static export
|
|
246
|
+
// hydration, so the fetch doesn't crash with "Cannot read properties
|
|
247
|
+
// of null" before the router is ready.
|
|
248
|
+
return types.optionalMemberExpression(types.optionalMemberExpression(types.identifier('router'), types.identifier('query'), false, true), types.identifier(content.id), false, true);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return ASTUtils.convertFilterDestinationToExpression(destination);
|
|
252
|
+
}
|
|
43
253
|
// Scan UIDL to find all data source usages and build a registry
|
|
44
254
|
function buildStateRegistry(uidlNode) {
|
|
45
255
|
var usages = [];
|
|
@@ -86,20 +296,48 @@ function buildStateRegistry(uidlNode) {
|
|
|
86
296
|
if ((_h = (_g = parentDataSource.resourceParams) === null || _g === void 0 ? void 0 : _g.queryColumns) === null || _h === void 0 ? void 0 : _h.content) {
|
|
87
297
|
queryColumns = parentDataSource.resourceParams.queryColumns.content;
|
|
88
298
|
}
|
|
89
|
-
// Extract sorts from parent's resource params
|
|
299
|
+
// Extract sorts from parent's resource params (legacy static array form)
|
|
90
300
|
var sorts = [];
|
|
91
301
|
if ((_k = (_j = parentDataSource.resourceParams) === null || _j === void 0 ? void 0 : _j.sorts) === null || _k === void 0 ? void 0 : _k.content) {
|
|
92
302
|
sorts = parentDataSource.resourceParams.sorts.content;
|
|
93
303
|
}
|
|
94
|
-
//
|
|
304
|
+
// If legacy sorts aren't set, fall back to the new dynamic single-column
|
|
305
|
+
// sort fields on the cms-list-repeater (used by admin-panel listing pages).
|
|
306
|
+
var dynamicSort = void 0;
|
|
307
|
+
if ((!sorts || sorts.length === 0) && content.sort) {
|
|
308
|
+
dynamicSort = extractDynamicSort(content.sort, content.sortDirection);
|
|
309
|
+
}
|
|
310
|
+
// Extract filters from parent's resource params. The inspector wraps
|
|
311
|
+
// every condition in a `{ type: 'group' }` envelope (single-group or
|
|
312
|
+
// nested), so flatten to leaf conditions before the downstream emit
|
|
313
|
+
// sites consume `.source` / `.destination` / `.operand` directly —
|
|
314
|
+
// they expect a flat condition array. See `flattenFilterGroups`'s
|
|
315
|
+
// header comment for why AND-flattening is the correct fallback for
|
|
316
|
+
// the API endpoint's flat-condition contract.
|
|
95
317
|
var filters = [];
|
|
96
318
|
if ((_m = (_l = parentDataSource.resourceParams) === null || _l === void 0 ? void 0 : _l.filters) === null || _m === void 0 ? void 0 : _m.content) {
|
|
97
|
-
filters = parentDataSource.resourceParams.filters.content;
|
|
319
|
+
filters = flattenFilterGroups(parentDataSource.resourceParams.filters.content);
|
|
320
|
+
}
|
|
321
|
+
// Split dynamic destination keys by reference type. `state`/`prop`
|
|
322
|
+
// refs resolve to bare identifiers (so they're useMemo deps as-is);
|
|
323
|
+
// `urlSearchParams` refs resolve to `router.query.<key>` and need a
|
|
324
|
+
// `useRouter()` declaration injected separately.
|
|
325
|
+
var filterStateIds = [];
|
|
326
|
+
for (var _i = 0, filters_3 = filters; _i < filters_3.length; _i++) {
|
|
327
|
+
var f = filters_3[_i];
|
|
328
|
+
if (!ASTUtils.isUIDLDynamicReference(f.destination)) {
|
|
329
|
+
continue;
|
|
330
|
+
}
|
|
331
|
+
var destinationContent = f.destination.content;
|
|
332
|
+
if (!destinationContent || !destinationContent.id) {
|
|
333
|
+
continue;
|
|
334
|
+
}
|
|
335
|
+
if (destinationContent.referenceType === 'urlSearchParams') {
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
filterStateIds.push(destinationContent.id);
|
|
98
339
|
}
|
|
99
|
-
|
|
100
|
-
var filterStateIds = filters
|
|
101
|
-
.filter(function (f) { return ASTUtils.isUIDLDynamicReference(f.destination); })
|
|
102
|
-
.map(function (f) { return f.destination.content.id; });
|
|
340
|
+
var filterUrlSearchParamKeys = collectFilterUrlSearchParamKeys(filters);
|
|
103
341
|
// Extract limit from parent's resource params (for plain array mappers)
|
|
104
342
|
var limit = 0;
|
|
105
343
|
if ((_p = (_o = parentDataSource.resourceParams) === null || _o === void 0 ? void 0 : _o.limit) === null || _p === void 0 ? void 0 : _p.content) {
|
|
@@ -108,6 +346,7 @@ function buildStateRegistry(uidlNode) {
|
|
|
108
346
|
// For paginated mappers, use perPage from cms-list-repeater
|
|
109
347
|
// For plain mappers, use limit from data-source-list resource params
|
|
110
348
|
var effectivePerPage = content.paginated ? content.perPage : limit || content.perPage;
|
|
349
|
+
var searchDefaultValue = parseSearchDefaultValue(content.searchDefaultValue);
|
|
111
350
|
var usage = {
|
|
112
351
|
index: index++,
|
|
113
352
|
dataSourceIdentifier: parentDataSource.identifier,
|
|
@@ -121,10 +360,13 @@ function buildStateRegistry(uidlNode) {
|
|
|
121
360
|
perPage: effectivePerPage,
|
|
122
361
|
searchEnabled: !!content.searchEnabled,
|
|
123
362
|
searchDebounce: content.searchDebounce || 300,
|
|
363
|
+
searchDefaultValue: searchDefaultValue,
|
|
124
364
|
queryColumns: queryColumns,
|
|
125
365
|
sorts: sorts,
|
|
366
|
+
dynamicSort: dynamicSort,
|
|
126
367
|
filters: filters,
|
|
127
368
|
filterStateIds: filterStateIds,
|
|
369
|
+
filterUrlSearchParamKeys: filterUrlSearchParamKeys,
|
|
128
370
|
category: 'plain',
|
|
129
371
|
};
|
|
130
372
|
// Determine category
|
|
@@ -153,8 +395,8 @@ function buildStateRegistry(uidlNode) {
|
|
|
153
395
|
}
|
|
154
396
|
// Recurse into children
|
|
155
397
|
if (((_r = node.content) === null || _r === void 0 ? void 0 : _r.children) && Array.isArray(node.content.children)) {
|
|
156
|
-
for (var
|
|
157
|
-
var child = _u
|
|
398
|
+
for (var _u = 0, _v = node.content.children; _u < _v.length; _u++) {
|
|
399
|
+
var child = _v[_u];
|
|
158
400
|
traverse(child, parentDataSource);
|
|
159
401
|
}
|
|
160
402
|
}
|
|
@@ -179,8 +421,8 @@ function buildStateRegistry(uidlNode) {
|
|
|
179
421
|
}
|
|
180
422
|
}
|
|
181
423
|
if (Array.isArray(node.children)) {
|
|
182
|
-
for (var
|
|
183
|
-
var child = _w
|
|
424
|
+
for (var _w = 0, _x = node.children; _w < _x.length; _w++) {
|
|
425
|
+
var child = _x[_w];
|
|
184
426
|
traverse(child, parentDataSource);
|
|
185
427
|
}
|
|
186
428
|
}
|
|
@@ -210,8 +452,9 @@ function getStateVarsForUsage(usage) {
|
|
|
210
452
|
// ==================== MAIN PLUGIN ====================
|
|
211
453
|
export var createNextArrayMapperPaginationPlugin = function () {
|
|
212
454
|
var paginationPlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
|
|
213
|
-
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages, paginationNodes, paginatedUsages;
|
|
214
|
-
|
|
455
|
+
var uidl, chunks, dependencies, options, componentChunk, variableDeclaration, declarator, arrowFunction, blockStatement, registry, getStaticPropsChunk, isPage, stateDeclarations, effectStatements, needsUseRouter, hasRouterDecl, returnIndex, insertIndex, dataProviders, dataProvidersWithRepeaters, usageIndexByDataSourceId, dataProvidersWithoutRepeaters, searchInputs, searchEnabledUsages, paginationNodes, paginatedUsages;
|
|
456
|
+
var _a;
|
|
457
|
+
return __generator(this, function (_b) {
|
|
215
458
|
uidl = structure.uidl, chunks = structure.chunks, dependencies = structure.dependencies, options = structure.options;
|
|
216
459
|
componentChunk = chunks.find(function (chunk) { return chunk.name === 'jsx-component'; });
|
|
217
460
|
if (!componentChunk || componentChunk.type !== ChunkType.AST) {
|
|
@@ -321,16 +564,19 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
321
564
|
]), types.callExpression(types.identifier('useState'), [
|
|
322
565
|
types.objectExpression([
|
|
323
566
|
types.objectProperty(types.identifier('page'), types.numericLiteral(1)),
|
|
324
|
-
types.objectProperty(types.identifier('debouncedQuery'),
|
|
567
|
+
types.objectProperty(types.identifier('debouncedQuery'), searchDefaultValueInitAST(usage.searchDefaultValue)),
|
|
325
568
|
]),
|
|
326
569
|
])),
|
|
327
570
|
]));
|
|
328
|
-
// Immediate search query state
|
|
571
|
+
// Immediate search query state — seeded with `searchDefaultValue`
|
|
572
|
+
// when provided so the input is pre-filled on mount.
|
|
329
573
|
stateDeclarations.push(types.variableDeclaration('const', [
|
|
330
574
|
types.variableDeclarator(types.arrayPattern([
|
|
331
575
|
types.identifier(vars.searchQueryVar),
|
|
332
576
|
types.identifier(vars.setSearchQueryVar),
|
|
333
|
-
]), types.callExpression(types.identifier('useState'), [
|
|
577
|
+
]), types.callExpression(types.identifier('useState'), [
|
|
578
|
+
searchDefaultValueInitAST(usage.searchDefaultValue),
|
|
579
|
+
])),
|
|
334
580
|
]));
|
|
335
581
|
// Debounce effect
|
|
336
582
|
effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
|
|
@@ -378,17 +624,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
378
624
|
])));
|
|
379
625
|
}
|
|
380
626
|
// Add filters to count fetch params if present
|
|
381
|
-
|
|
382
|
-
urlParams.push(types.objectProperty(types.identifier('filters'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
|
|
383
|
-
types.arrayExpression(usage.filters.map(function (filter) {
|
|
384
|
-
return types.objectExpression([
|
|
385
|
-
types.objectProperty(types.identifier('source'), types.stringLiteral(filter.source || '')),
|
|
386
|
-
types.objectProperty(types.identifier('destination'), ASTUtils.convertFilterDestinationToExpression(filter.destination)),
|
|
387
|
-
types.objectProperty(types.identifier('operand'), types.stringLiteral(filter.operand || '')),
|
|
388
|
-
]);
|
|
389
|
-
})),
|
|
390
|
-
])));
|
|
391
|
-
}
|
|
627
|
+
appendFiltersParam(urlParams, usage.filters, buildFilterDestinationExpression);
|
|
392
628
|
// Build the count fetch effect body
|
|
393
629
|
var countFetchEffectBody = [];
|
|
394
630
|
// Only add skip-on-mount check for pages (where we have server-side count)
|
|
@@ -424,11 +660,21 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
424
660
|
])),
|
|
425
661
|
])),
|
|
426
662
|
])));
|
|
663
|
+
var countEffectDeps = [
|
|
664
|
+
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
|
|
665
|
+
];
|
|
666
|
+
// Refresh the count whenever a state-bound filter destination changes
|
|
667
|
+
// (e.g. user picks a category) so pagination tracks the filtered
|
|
668
|
+
// result-set, not the mount-time unfiltered total. Without these
|
|
669
|
+
// deps, ds_0_maxPages stays at the original count and the "Next"
|
|
670
|
+
// button stays enabled past the actual last page of the filtered
|
|
671
|
+
// results — letting the user click into empty pages.
|
|
672
|
+
pushStateIdsAsDeps(countEffectDeps, new Set(), usage.filterStateIds);
|
|
673
|
+
// Same goes for URL-driven filters (already documented above).
|
|
674
|
+
pushUrlSearchParamMemoDeps(countEffectDeps, usage);
|
|
427
675
|
effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
|
|
428
676
|
types.arrowFunctionExpression([], types.blockStatement(countFetchEffectBody)),
|
|
429
|
-
types.arrayExpression(
|
|
430
|
-
types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')),
|
|
431
|
-
]),
|
|
677
|
+
types.arrayExpression(countEffectDeps),
|
|
432
678
|
])));
|
|
433
679
|
}
|
|
434
680
|
else if (usage.category === 'paginated-only') {
|
|
@@ -470,7 +716,16 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
470
716
|
])),
|
|
471
717
|
])),
|
|
472
718
|
])),
|
|
473
|
-
|
|
719
|
+
// Default to mount-only; refresh when ANY filter destination
|
|
720
|
+
// changes — state-bound (e.g. `selectedCategory`) and
|
|
721
|
+
// URL-driven — so the pagination control reflects the current
|
|
722
|
+
// filtered count instead of the unfiltered mount-time total.
|
|
723
|
+
types.arrayExpression((function () {
|
|
724
|
+
var deps = [];
|
|
725
|
+
pushStateIdsAsDeps(deps, new Set(), usage.filterStateIds);
|
|
726
|
+
pushUrlSearchParamMemoDeps(deps, usage);
|
|
727
|
+
return deps;
|
|
728
|
+
})()),
|
|
474
729
|
])));
|
|
475
730
|
}
|
|
476
731
|
}
|
|
@@ -483,13 +738,17 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
483
738
|
types.variableDeclarator(types.arrayPattern([
|
|
484
739
|
types.identifier(vars.debouncedSearchQueryVar),
|
|
485
740
|
types.identifier(vars.setDebouncedSearchQueryVar),
|
|
486
|
-
]), types.callExpression(types.identifier('useState'), [
|
|
741
|
+
]), types.callExpression(types.identifier('useState'), [
|
|
742
|
+
searchDefaultValueInitAST(usage.searchDefaultValue),
|
|
743
|
+
])),
|
|
487
744
|
]));
|
|
488
745
|
stateDeclarations.push(types.variableDeclaration('const', [
|
|
489
746
|
types.variableDeclarator(types.arrayPattern([
|
|
490
747
|
types.identifier(vars.searchQueryVar),
|
|
491
748
|
types.identifier(vars.setSearchQueryVar),
|
|
492
|
-
]), types.callExpression(types.identifier('useState'), [
|
|
749
|
+
]), types.callExpression(types.identifier('useState'), [
|
|
750
|
+
searchDefaultValueInitAST(usage.searchDefaultValue),
|
|
751
|
+
])),
|
|
493
752
|
]));
|
|
494
753
|
// Debounce effect
|
|
495
754
|
effectStatements.push(types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
|
|
@@ -516,6 +775,36 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
516
775
|
});
|
|
517
776
|
// Insert state declarations at the beginning
|
|
518
777
|
stateDeclarations.reverse().forEach(function (s) { return blockStatement.body.unshift(s); });
|
|
778
|
+
needsUseRouter = registry.usages.some(function (u) { return hasUrlSearchParamFilters(u); });
|
|
779
|
+
if (needsUseRouter) {
|
|
780
|
+
if (!dependencies.useRouter) {
|
|
781
|
+
// Match the shape the sibling Next.js plugins use (i18n locale mapper,
|
|
782
|
+
// search-params plugin) so the deduped import line is identical and
|
|
783
|
+
// the dependency-resolver merges instead of emitting a second one.
|
|
784
|
+
dependencies.useRouter = {
|
|
785
|
+
type: 'library',
|
|
786
|
+
path: 'next/router',
|
|
787
|
+
version: '^12.1.10',
|
|
788
|
+
meta: { namedImport: true },
|
|
789
|
+
};
|
|
790
|
+
}
|
|
791
|
+
hasRouterDecl = blockStatement.body.some(function (statement) {
|
|
792
|
+
return statement.type === 'VariableDeclaration' &&
|
|
793
|
+
statement.declarations.some(function (decl) {
|
|
794
|
+
var _a;
|
|
795
|
+
return decl.id.type === 'Identifier' &&
|
|
796
|
+
decl.id.name === 'router' &&
|
|
797
|
+
((_a = decl.init) === null || _a === void 0 ? void 0 : _a.type) === 'CallExpression' &&
|
|
798
|
+
decl.init.callee.type === 'Identifier' &&
|
|
799
|
+
decl.init.callee.name === 'useRouter';
|
|
800
|
+
});
|
|
801
|
+
});
|
|
802
|
+
if (!hasRouterDecl) {
|
|
803
|
+
blockStatement.body.unshift(types.variableDeclaration('const', [
|
|
804
|
+
types.variableDeclarator(types.identifier('router'), types.callExpression(types.identifier('useRouter'), [])),
|
|
805
|
+
]));
|
|
806
|
+
}
|
|
807
|
+
}
|
|
519
808
|
returnIndex = blockStatement.body.findIndex(function (s) { return s.type === 'ReturnStatement'; });
|
|
520
809
|
insertIndex = returnIndex !== -1 ? returnIndex : blockStatement.body.length;
|
|
521
810
|
effectStatements.reverse().forEach(function (e) { return blockStatement.body.splice(insertIndex, 0, e); });
|
|
@@ -589,7 +878,7 @@ export var createNextArrayMapperPaginationPlugin = function () {
|
|
|
589
878
|
});
|
|
590
879
|
// STEP 6: Update getStaticProps if this is a page
|
|
591
880
|
if (isPage) {
|
|
592
|
-
updateGetStaticProps(chunks, registry, dependencies);
|
|
881
|
+
updateGetStaticProps(chunks, registry, dependencies, (_a = uidl.outputOptions) === null || _a === void 0 ? void 0 : _a.folderPath);
|
|
593
882
|
}
|
|
594
883
|
return [2 /*return*/, structure];
|
|
595
884
|
});
|
|
@@ -773,42 +1062,37 @@ function updateDataProviderForPaginatedSearch(dp, usage, vars, fileName) {
|
|
|
773
1062
|
if (usage.queryColumns.length > 0) {
|
|
774
1063
|
paramsProps.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
|
|
775
1064
|
}
|
|
776
|
-
// Add sorts if present
|
|
777
|
-
|
|
778
|
-
paramsProps.push(types.objectProperty(types.identifier('sorts'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
|
|
779
|
-
types.arrayExpression(usage.sorts.map(function (sort) {
|
|
780
|
-
return types.objectExpression([
|
|
781
|
-
types.objectProperty(types.identifier('field'), types.stringLiteral(sort.field || '')),
|
|
782
|
-
types.objectProperty(types.identifier('order'), types.stringLiteral(sort.order || '')),
|
|
783
|
-
]);
|
|
784
|
-
})),
|
|
785
|
-
])));
|
|
786
|
-
}
|
|
1065
|
+
// Add sorts if present (legacy static array wins; otherwise dynamic state-bound sort)
|
|
1066
|
+
appendSortsParam(paramsProps, usage.sorts, usage.dynamicSort);
|
|
787
1067
|
// Add filters if present
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
types.arrayExpression(usage.filters.map(function (filter) {
|
|
791
|
-
return types.objectExpression([
|
|
792
|
-
types.objectProperty(types.identifier('source'), types.stringLiteral(filter.source || '')),
|
|
793
|
-
types.objectProperty(types.identifier('destination'), ASTUtils.convertFilterDestinationToExpression(filter.destination)),
|
|
794
|
-
types.objectProperty(types.identifier('operand'), types.stringLiteral(filter.operand || '')),
|
|
795
|
-
]);
|
|
796
|
-
})),
|
|
797
|
-
])));
|
|
798
|
-
}
|
|
799
|
-
// Build useMemo dependencies including filter state IDs
|
|
1068
|
+
appendFiltersParam(paramsProps, usage.filters, buildFilterDestinationExpression);
|
|
1069
|
+
// Build useMemo dependencies including filter state IDs and dynamic sort state IDs
|
|
800
1070
|
var memoDeps = [types.identifier(vars.combinedStateVar)];
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
|
|
1071
|
+
var seenDeps = new Set([vars.combinedStateVar]);
|
|
1072
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds);
|
|
1073
|
+
if (usage.dynamicSort) {
|
|
1074
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds);
|
|
1075
|
+
}
|
|
1076
|
+
pushUrlSearchParamMemoDeps(memoDeps, usage);
|
|
804
1077
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
|
|
805
1078
|
types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
|
|
806
1079
|
types.arrayExpression(memoDeps),
|
|
807
1080
|
]))));
|
|
808
|
-
// Add initialData
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
//
|
|
1081
|
+
// Add initialData. Skip the server-prefetched data entirely when a dynamic
|
|
1082
|
+
// state-bound sort is active — the prefetch ran without sort parameters, so
|
|
1083
|
+
// reusing it would mask the current sort state AND cause DataProvider to skip
|
|
1084
|
+
// the first client fetch (its internal guard only skips when initialData is
|
|
1085
|
+
// defined on mount). Without that skip, toggling sort correctly triggers a
|
|
1086
|
+
// refetch via the useMemo params dependency chain.
|
|
1087
|
+
if (!usage.dynamicSort) {
|
|
1088
|
+
var initialDataCondition = wrapInitialDataWithUrlFilterGuard(types.logicalExpression('&&', types.binaryExpression('===', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('page')), types.numericLiteral(1)), types.unaryExpression('!', types.memberExpression(types.identifier(vars.combinedStateVar), types.identifier('debouncedQuery')), true)), usage);
|
|
1089
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(initialDataCondition, types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), types.identifier('undefined')))));
|
|
1090
|
+
}
|
|
1091
|
+
// Add key. Sort is intentionally NOT part of the key — a key change would
|
|
1092
|
+
// remount the DataProvider, and a fresh mount re-arms the internal
|
|
1093
|
+
// "skip-first-fetch-when-we-have-initialData" guard, which would prevent the
|
|
1094
|
+
// new sort params from reaching the fetcher. Leaving sort out of the key
|
|
1095
|
+
// lets the useMemo params identity change alone drive refetch.
|
|
812
1096
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
|
|
813
1097
|
types.templateElement({
|
|
814
1098
|
raw: "".concat(usage.dataSourceIdentifier, "-"),
|
|
@@ -836,42 +1120,29 @@ function updateDataProviderForPaginationOnly(dp, usage, vars, fileName) {
|
|
|
836
1120
|
types.objectProperty(types.identifier('page'), types.identifier(vars.pageStateVar)),
|
|
837
1121
|
types.objectProperty(types.identifier('perPage'), types.numericLiteral(usage.perPage)),
|
|
838
1122
|
];
|
|
839
|
-
// Add sorts if present
|
|
840
|
-
|
|
841
|
-
paramsProps.push(types.objectProperty(types.identifier('sorts'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
|
|
842
|
-
types.arrayExpression(usage.sorts.map(function (sort) {
|
|
843
|
-
return types.objectExpression([
|
|
844
|
-
types.objectProperty(types.identifier('field'), types.stringLiteral(sort.field || '')),
|
|
845
|
-
types.objectProperty(types.identifier('order'), types.stringLiteral(sort.order || '')),
|
|
846
|
-
]);
|
|
847
|
-
})),
|
|
848
|
-
])));
|
|
849
|
-
}
|
|
1123
|
+
// Add sorts if present (legacy static array wins; otherwise dynamic state-bound sort)
|
|
1124
|
+
appendSortsParam(paramsProps, usage.sorts, usage.dynamicSort);
|
|
850
1125
|
// Add filters if present
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
types.arrayExpression(usage.filters.map(function (filter) {
|
|
854
|
-
return types.objectExpression([
|
|
855
|
-
types.objectProperty(types.identifier('source'), types.stringLiteral(filter.source || '')),
|
|
856
|
-
types.objectProperty(types.identifier('destination'), ASTUtils.convertFilterDestinationToExpression(filter.destination)),
|
|
857
|
-
types.objectProperty(types.identifier('operand'), types.stringLiteral(filter.operand || '')),
|
|
858
|
-
]);
|
|
859
|
-
})),
|
|
860
|
-
])));
|
|
861
|
-
}
|
|
862
|
-
// Build useMemo dependencies including filter state IDs
|
|
1126
|
+
appendFiltersParam(paramsProps, usage.filters, buildFilterDestinationExpression);
|
|
1127
|
+
// Build useMemo dependencies including filter state IDs and dynamic sort state IDs
|
|
863
1128
|
var memoDeps = [types.identifier(vars.pageStateVar)];
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
1129
|
+
var seenDeps = new Set([vars.pageStateVar]);
|
|
1130
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds);
|
|
1131
|
+
if (usage.dynamicSort) {
|
|
1132
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds);
|
|
1133
|
+
}
|
|
1134
|
+
pushUrlSearchParamMemoDeps(memoDeps, usage);
|
|
867
1135
|
// Add params
|
|
868
1136
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
|
|
869
1137
|
types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
|
|
870
1138
|
types.arrayExpression(memoDeps),
|
|
871
1139
|
]))));
|
|
872
|
-
// Add initialData
|
|
873
|
-
|
|
874
|
-
|
|
1140
|
+
// Add initialData. See paginated+search updater for why we skip prefetch
|
|
1141
|
+
// reuse when a dynamic state-bound sort is active.
|
|
1142
|
+
if (!usage.dynamicSort) {
|
|
1143
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(types.binaryExpression('===', types.identifier(vars.pageStateVar), types.numericLiteral(1)), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), types.identifier('undefined')))));
|
|
1144
|
+
}
|
|
1145
|
+
// Add key — sort is intentionally NOT included; see paginated+search updater.
|
|
875
1146
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
|
|
876
1147
|
types.templateElement({
|
|
877
1148
|
raw: "".concat(usage.dataSourceIdentifier, "-page-"),
|
|
@@ -896,41 +1167,28 @@ function updateDataProviderForSearchOnly(dp, usage, vars, fileName) {
|
|
|
896
1167
|
if (usage.queryColumns.length > 0) {
|
|
897
1168
|
paramsProps.push(types.objectProperty(types.identifier('queryColumns'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(usage.queryColumns.map(function (c) { return types.stringLiteral(c); }))])));
|
|
898
1169
|
}
|
|
899
|
-
// Add sorts if present
|
|
900
|
-
|
|
901
|
-
paramsProps.push(types.objectProperty(types.identifier('sorts'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
|
|
902
|
-
types.arrayExpression(usage.sorts.map(function (sort) {
|
|
903
|
-
return types.objectExpression([
|
|
904
|
-
types.objectProperty(types.identifier('field'), types.stringLiteral(sort.field || '')),
|
|
905
|
-
types.objectProperty(types.identifier('order'), types.stringLiteral(sort.order || '')),
|
|
906
|
-
]);
|
|
907
|
-
})),
|
|
908
|
-
])));
|
|
909
|
-
}
|
|
1170
|
+
// Add sorts if present (legacy static array wins; otherwise dynamic state-bound sort)
|
|
1171
|
+
appendSortsParam(paramsProps, usage.sorts, usage.dynamicSort);
|
|
910
1172
|
// Add filters if present
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
types.arrayExpression(usage.filters.map(function (filter) {
|
|
914
|
-
return types.objectExpression([
|
|
915
|
-
types.objectProperty(types.identifier('source'), types.stringLiteral(filter.source || '')),
|
|
916
|
-
types.objectProperty(types.identifier('destination'), ASTUtils.convertFilterDestinationToExpression(filter.destination)),
|
|
917
|
-
types.objectProperty(types.identifier('operand'), types.stringLiteral(filter.operand || '')),
|
|
918
|
-
]);
|
|
919
|
-
})),
|
|
920
|
-
])));
|
|
921
|
-
}
|
|
922
|
-
// Build useMemo dependencies including filter state IDs
|
|
1173
|
+
appendFiltersParam(paramsProps, usage.filters, buildFilterDestinationExpression);
|
|
1174
|
+
// Build useMemo dependencies including filter state IDs and dynamic sort state IDs
|
|
923
1175
|
var memoDeps = [types.identifier(vars.debouncedSearchQueryVar)];
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
1176
|
+
var seenDeps = new Set([vars.debouncedSearchQueryVar]);
|
|
1177
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.filterStateIds);
|
|
1178
|
+
if (usage.dynamicSort) {
|
|
1179
|
+
pushStateIdsAsDeps(memoDeps, seenDeps, usage.dynamicSort.depStateIds);
|
|
1180
|
+
}
|
|
1181
|
+
pushUrlSearchParamMemoDeps(memoDeps, usage);
|
|
927
1182
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('params'), types.jsxExpressionContainer(types.callExpression(types.identifier('useMemo'), [
|
|
928
1183
|
types.arrowFunctionExpression([], types.objectExpression(paramsProps)),
|
|
929
1184
|
types.arrayExpression(memoDeps),
|
|
930
1185
|
]))));
|
|
931
|
-
// Add initialData
|
|
932
|
-
|
|
933
|
-
|
|
1186
|
+
// Add initialData. See paginated+search updater for why we skip prefetch
|
|
1187
|
+
// reuse when a dynamic state-bound sort is active.
|
|
1188
|
+
if (!usage.dynamicSort) {
|
|
1189
|
+
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('initialData'), types.jsxExpressionContainer(types.conditionalExpression(wrapInitialDataWithUrlFilterGuard(types.unaryExpression('!', types.identifier(vars.debouncedSearchQueryVar), true), usage), types.optionalMemberExpression(types.identifier('props'), types.identifier(vars.propsPrefix), false, true), types.identifier('undefined')))));
|
|
1190
|
+
}
|
|
1191
|
+
// Add key — sort is intentionally NOT included; see paginated+search updater.
|
|
934
1192
|
dp.openingElement.attributes.push(types.jsxAttribute(types.jsxIdentifier('key'), types.jsxExpressionContainer(types.templateLiteral([
|
|
935
1193
|
types.templateElement({ raw: 'search-', cooked: 'search-' }),
|
|
936
1194
|
types.templateElement({ raw: '', cooked: '' }),
|
|
@@ -976,9 +1234,8 @@ function updateDataProviderForPlain(dp, fileName, usage) {
|
|
|
976
1234
|
}
|
|
977
1235
|
// Build useMemo dependencies including filter state IDs
|
|
978
1236
|
var memoDeps = [];
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
});
|
|
1237
|
+
pushStateIdsAsDeps(memoDeps, new Set(), usage.filterStateIds);
|
|
1238
|
+
pushUrlSearchParamMemoDeps(memoDeps, usage);
|
|
982
1239
|
// Wrap params in useMemo with filter state dependencies
|
|
983
1240
|
var memoizedParams = types.callExpression(types.identifier('useMemo'), [
|
|
984
1241
|
types.arrowFunctionExpression([], paramsExpression),
|
|
@@ -1198,7 +1455,7 @@ function ensureAPIRouteExists(extractedResources, usage, dataSources) {
|
|
|
1198
1455
|
};
|
|
1199
1456
|
}
|
|
1200
1457
|
}
|
|
1201
|
-
function updateGetStaticProps(chunks, registry, dependencies) {
|
|
1458
|
+
function updateGetStaticProps(chunks, registry, dependencies, folderPath) {
|
|
1202
1459
|
var _a;
|
|
1203
1460
|
var getStaticPropsChunk = chunks.find(function (c) { return c.name === 'getStaticProps'; });
|
|
1204
1461
|
if (!getStaticPropsChunk || getStaticPropsChunk.type !== ChunkType.AST) {
|
|
@@ -1308,9 +1565,11 @@ function updateGetStaticProps(chunks, registry, dependencies) {
|
|
|
1308
1565
|
]));
|
|
1309
1566
|
// Add import dependency for the fetcher
|
|
1310
1567
|
if (!dependencies[fetcherImportName]) {
|
|
1568
|
+
var depth = (folderPath ? folderPath.length : 0) + 1;
|
|
1569
|
+
var relativePrefix = '../'.repeat(depth);
|
|
1311
1570
|
dependencies[fetcherImportName] = {
|
|
1312
1571
|
type: 'local',
|
|
1313
|
-
path: "
|
|
1572
|
+
path: "".concat(relativePrefix, "utils/data-sources/").concat(fileName),
|
|
1314
1573
|
};
|
|
1315
1574
|
}
|
|
1316
1575
|
// Add to props
|
|
@@ -1421,9 +1680,11 @@ function updateGetStaticProps(chunks, registry, dependencies) {
|
|
|
1421
1680
|
}
|
|
1422
1681
|
// Add import dependency for the fetcher
|
|
1423
1682
|
if (!dependencies[fetcherImportName]) {
|
|
1683
|
+
var depth = (folderPath ? folderPath.length : 0) + 1;
|
|
1684
|
+
var relativePrefix = '../'.repeat(depth);
|
|
1424
1685
|
dependencies[fetcherImportName] = {
|
|
1425
1686
|
type: 'local',
|
|
1426
|
-
path: "
|
|
1687
|
+
path: "".concat(relativePrefix, "utils/data-sources/").concat(fileName),
|
|
1427
1688
|
};
|
|
1428
1689
|
}
|
|
1429
1690
|
}
|