@teleporthq/teleport-plugin-next-data-source 0.43.75 → 0.44.1

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 (199) hide show
  1. package/__tests__/_helpers/first-page-runtime.ts +184 -0
  2. package/__tests__/_helpers/pagination-widget-fixture.ts +154 -5
  3. package/__tests__/booking-item-transform.test.ts +120 -0
  4. package/__tests__/browser-row-policy.test.ts +210 -4
  5. package/__tests__/data-source-request-locale.test.ts +4 -3
  6. package/__tests__/fetchers.test.ts +7 -3
  7. package/__tests__/fixed-list-sort.test.ts +1 -1
  8. package/__tests__/infinite-scroll.test.ts +363 -9
  9. package/__tests__/list-sort-order.test.ts +61 -0
  10. package/__tests__/null-filter-where.test.ts +132 -0
  11. package/__tests__/page-data-visitor-read.test.ts +196 -0
  12. package/__tests__/pg-date-parser.test.ts +73 -0
  13. package/__tests__/plain-list-sort.test.ts +2 -2
  14. package/__tests__/plain-list-starting-sort.test.ts +323 -0
  15. package/__tests__/product-price-sort.ts +11 -6
  16. package/__tests__/range-control.test.ts +159 -0
  17. package/__tests__/refetch-loading-state.test.ts +158 -2
  18. package/__tests__/search-input-marker.test.ts +86 -0
  19. package/__tests__/search-url-sync.test.ts +34 -8
  20. package/__tests__/starting-sort-first-page.test.ts +285 -0
  21. package/__tests__/table-read-route-protected-tables.test.ts +33 -3
  22. package/dist/cjs/cache/ast.d.ts +2 -0
  23. package/dist/cjs/cache/ast.d.ts.map +1 -1
  24. package/dist/cjs/cache/ast.js +5 -2
  25. package/dist/cjs/cache/ast.js.map +1 -1
  26. package/dist/cjs/count-effect.d.ts +7 -1
  27. package/dist/cjs/count-effect.d.ts.map +1 -1
  28. package/dist/cjs/count-effect.js +15 -5
  29. package/dist/cjs/count-effect.js.map +1 -1
  30. package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
  31. package/dist/cjs/data-source-fetchers.js +10 -2
  32. package/dist/cjs/data-source-fetchers.js.map +1 -1
  33. package/dist/cjs/fetchers/pg-client-import.d.ts +12 -0
  34. package/dist/cjs/fetchers/pg-client-import.d.ts.map +1 -0
  35. package/dist/cjs/fetchers/pg-client-import.js +15 -0
  36. package/dist/cjs/fetchers/pg-client-import.js.map +1 -0
  37. package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
  38. package/dist/cjs/fetchers/postgresql.js +3 -1
  39. package/dist/cjs/fetchers/postgresql.js.map +1 -1
  40. package/dist/cjs/fetchers/raw-query.d.ts.map +1 -1
  41. package/dist/cjs/fetchers/raw-query.js +2 -1
  42. package/dist/cjs/fetchers/raw-query.js.map +1 -1
  43. package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
  44. package/dist/cjs/fetchers/teleport.js +4 -2
  45. package/dist/cjs/fetchers/teleport.js.map +1 -1
  46. package/dist/cjs/fetchers/utils/browser-row-policy.d.ts.map +1 -1
  47. package/dist/cjs/fetchers/utils/browser-row-policy.js +5 -1
  48. package/dist/cjs/fetchers/utils/browser-row-policy.js.map +1 -1
  49. package/dist/cjs/index.d.ts.map +1 -1
  50. package/dist/cjs/index.js +14 -2
  51. package/dist/cjs/index.js.map +1 -1
  52. package/dist/cjs/infinite-scroll.d.ts +89 -4
  53. package/dist/cjs/infinite-scroll.d.ts.map +1 -1
  54. package/dist/cjs/infinite-scroll.js +243 -33
  55. package/dist/cjs/infinite-scroll.js.map +1 -1
  56. package/dist/cjs/list-sort-order.d.ts +14 -0
  57. package/dist/cjs/list-sort-order.d.ts.map +1 -0
  58. package/dist/cjs/list-sort-order.js +36 -0
  59. package/dist/cjs/list-sort-order.js.map +1 -0
  60. package/dist/cjs/loading-state.d.ts +23 -2
  61. package/dist/cjs/loading-state.d.ts.map +1 -1
  62. package/dist/cjs/loading-state.js +50 -15
  63. package/dist/cjs/loading-state.js.map +1 -1
  64. package/dist/cjs/pagination-controls.d.ts +22 -3
  65. package/dist/cjs/pagination-controls.d.ts.map +1 -1
  66. package/dist/cjs/pagination-controls.js +29 -3
  67. package/dist/cjs/pagination-controls.js.map +1 -1
  68. package/dist/cjs/pagination-plugin.d.ts.map +1 -1
  69. package/dist/cjs/pagination-plugin.js +336 -164
  70. package/dist/cjs/pagination-plugin.js.map +1 -1
  71. package/dist/cjs/range-control.d.ts +45 -0
  72. package/dist/cjs/range-control.d.ts.map +1 -0
  73. package/dist/cjs/range-control.js +165 -0
  74. package/dist/cjs/range-control.js.map +1 -0
  75. package/dist/cjs/row-order.d.ts +3 -2
  76. package/dist/cjs/row-order.d.ts.map +1 -1
  77. package/dist/cjs/row-order.js +5 -4
  78. package/dist/cjs/row-order.js.map +1 -1
  79. package/dist/cjs/search-input.d.ts +42 -0
  80. package/dist/cjs/search-input.d.ts.map +1 -0
  81. package/dist/cjs/search-input.js +158 -0
  82. package/dist/cjs/search-input.js.map +1 -0
  83. package/dist/cjs/sort-utils.d.ts +53 -1
  84. package/dist/cjs/sort-utils.d.ts.map +1 -1
  85. package/dist/cjs/sort-utils.js +105 -13
  86. package/dist/cjs/sort-utils.js.map +1 -1
  87. package/dist/cjs/transformations/booking-item.d.ts +24 -0
  88. package/dist/cjs/transformations/booking-item.d.ts.map +1 -0
  89. package/dist/cjs/transformations/booking-item.js +27 -0
  90. package/dist/cjs/transformations/booking-item.js.map +1 -0
  91. package/dist/cjs/transformations/index.d.ts +4 -2
  92. package/dist/cjs/transformations/index.d.ts.map +1 -1
  93. package/dist/cjs/transformations/index.js +14 -5
  94. package/dist/cjs/transformations/index.js.map +1 -1
  95. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  96. package/dist/cjs/utils.d.ts +3 -2
  97. package/dist/cjs/utils.d.ts.map +1 -1
  98. package/dist/cjs/utils.js +48 -18
  99. package/dist/cjs/utils.js.map +1 -1
  100. package/dist/esm/cache/ast.d.ts +2 -0
  101. package/dist/esm/cache/ast.d.ts.map +1 -1
  102. package/dist/esm/cache/ast.js +3 -1
  103. package/dist/esm/cache/ast.js.map +1 -1
  104. package/dist/esm/count-effect.d.ts +7 -1
  105. package/dist/esm/count-effect.d.ts.map +1 -1
  106. package/dist/esm/count-effect.js +15 -5
  107. package/dist/esm/count-effect.js.map +1 -1
  108. package/dist/esm/data-source-fetchers.d.ts.map +1 -1
  109. package/dist/esm/data-source-fetchers.js +10 -2
  110. package/dist/esm/data-source-fetchers.js.map +1 -1
  111. package/dist/esm/fetchers/pg-client-import.d.ts +12 -0
  112. package/dist/esm/fetchers/pg-client-import.d.ts.map +1 -0
  113. package/dist/esm/fetchers/pg-client-import.js +12 -0
  114. package/dist/esm/fetchers/pg-client-import.js.map +1 -0
  115. package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
  116. package/dist/esm/fetchers/postgresql.js +3 -1
  117. package/dist/esm/fetchers/postgresql.js.map +1 -1
  118. package/dist/esm/fetchers/raw-query.d.ts.map +1 -1
  119. package/dist/esm/fetchers/raw-query.js +2 -1
  120. package/dist/esm/fetchers/raw-query.js.map +1 -1
  121. package/dist/esm/fetchers/teleport.d.ts.map +1 -1
  122. package/dist/esm/fetchers/teleport.js +4 -2
  123. package/dist/esm/fetchers/teleport.js.map +1 -1
  124. package/dist/esm/fetchers/utils/browser-row-policy.d.ts.map +1 -1
  125. package/dist/esm/fetchers/utils/browser-row-policy.js +6 -2
  126. package/dist/esm/fetchers/utils/browser-row-policy.js.map +1 -1
  127. package/dist/esm/index.d.ts.map +1 -1
  128. package/dist/esm/index.js +14 -2
  129. package/dist/esm/index.js.map +1 -1
  130. package/dist/esm/infinite-scroll.d.ts +89 -4
  131. package/dist/esm/infinite-scroll.d.ts.map +1 -1
  132. package/dist/esm/infinite-scroll.js +237 -32
  133. package/dist/esm/infinite-scroll.js.map +1 -1
  134. package/dist/esm/list-sort-order.d.ts +14 -0
  135. package/dist/esm/list-sort-order.d.ts.map +1 -0
  136. package/dist/esm/list-sort-order.js +32 -0
  137. package/dist/esm/list-sort-order.js.map +1 -0
  138. package/dist/esm/loading-state.d.ts +23 -2
  139. package/dist/esm/loading-state.d.ts.map +1 -1
  140. package/dist/esm/loading-state.js +50 -15
  141. package/dist/esm/loading-state.js.map +1 -1
  142. package/dist/esm/pagination-controls.d.ts +22 -3
  143. package/dist/esm/pagination-controls.d.ts.map +1 -1
  144. package/dist/esm/pagination-controls.js +28 -2
  145. package/dist/esm/pagination-controls.js.map +1 -1
  146. package/dist/esm/pagination-plugin.d.ts.map +1 -1
  147. package/dist/esm/pagination-plugin.js +340 -168
  148. package/dist/esm/pagination-plugin.js.map +1 -1
  149. package/dist/esm/range-control.d.ts +45 -0
  150. package/dist/esm/range-control.d.ts.map +1 -0
  151. package/dist/esm/range-control.js +137 -0
  152. package/dist/esm/range-control.js.map +1 -0
  153. package/dist/esm/row-order.d.ts +3 -2
  154. package/dist/esm/row-order.d.ts.map +1 -1
  155. package/dist/esm/row-order.js +5 -4
  156. package/dist/esm/row-order.js.map +1 -1
  157. package/dist/esm/search-input.d.ts +42 -0
  158. package/dist/esm/search-input.d.ts.map +1 -0
  159. package/dist/esm/search-input.js +129 -0
  160. package/dist/esm/search-input.js.map +1 -0
  161. package/dist/esm/sort-utils.d.ts +53 -1
  162. package/dist/esm/sort-utils.d.ts.map +1 -1
  163. package/dist/esm/sort-utils.js +100 -12
  164. package/dist/esm/sort-utils.js.map +1 -1
  165. package/dist/esm/transformations/booking-item.d.ts +24 -0
  166. package/dist/esm/transformations/booking-item.d.ts.map +1 -0
  167. package/dist/esm/transformations/booking-item.js +23 -0
  168. package/dist/esm/transformations/booking-item.js.map +1 -0
  169. package/dist/esm/transformations/index.d.ts +4 -2
  170. package/dist/esm/transformations/index.d.ts.map +1 -1
  171. package/dist/esm/transformations/index.js +14 -5
  172. package/dist/esm/transformations/index.js.map +1 -1
  173. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  174. package/dist/esm/utils.d.ts +3 -2
  175. package/dist/esm/utils.d.ts.map +1 -1
  176. package/dist/esm/utils.js +49 -19
  177. package/dist/esm/utils.js.map +1 -1
  178. package/package.json +5 -5
  179. package/src/cache/ast.ts +4 -1
  180. package/src/count-effect.ts +31 -8
  181. package/src/data-source-fetchers.ts +33 -14
  182. package/src/fetchers/pg-client-import.ts +16 -0
  183. package/src/fetchers/postgresql.ts +15 -9
  184. package/src/fetchers/raw-query.ts +2 -1
  185. package/src/fetchers/teleport.ts +19 -10
  186. package/src/fetchers/utils/browser-row-policy.ts +79 -5
  187. package/src/index.ts +8 -2
  188. package/src/infinite-scroll.ts +420 -81
  189. package/src/list-sort-order.ts +34 -0
  190. package/src/loading-state.ts +85 -13
  191. package/src/pagination-controls.ts +26 -3
  192. package/src/pagination-plugin.ts +532 -218
  193. package/src/range-control.ts +207 -0
  194. package/src/row-order.ts +5 -4
  195. package/src/search-input.ts +190 -0
  196. package/src/sort-utils.ts +164 -21
  197. package/src/transformations/booking-item.ts +71 -0
  198. package/src/transformations/index.ts +25 -2
  199. package/src/utils.ts +55 -18
@@ -0,0 +1,137 @@
1
+ import * as types from '@babel/types';
2
+ import { DEFAULT_RANGE_TEMPLATE, PAGINATION_CONTROL_ATTR, RANGE_TEMPLATE_ATTR, readJSXAttributeString, } from './pagination-controls';
3
+ var PLACEHOLDER = /\{(from|to|total)\}/g;
4
+ var total = function (vars) { return types.identifier(vars.totalVar); };
5
+ var page = function (vars) {
6
+ return types.cloneNode(vars.currentPageExpr, true);
7
+ };
8
+ /** `total === 0 ? 0 : <firstRow>` */
9
+ var unlessEmpty = function (vars, firstRow) {
10
+ return types.conditionalExpression(types.binaryExpression('===', total(vars), types.numericLiteral(0)), types.numericLiteral(0), firstRow);
11
+ };
12
+ var buildFrom = function (vars) {
13
+ return unlessEmpty(vars, vars.infiniteScroll
14
+ ? types.numericLiteral(1)
15
+ : types.binaryExpression('+', types.binaryExpression('*', types.binaryExpression('-', page(vars), types.numericLiteral(1)), types.numericLiteral(vars.perPage)), types.numericLiteral(1)));
16
+ };
17
+ /** `Math.min(page * perPage, total)` */
18
+ var buildTo = function (vars) {
19
+ return types.callExpression(types.memberExpression(types.identifier('Math'), types.identifier('min')), [
20
+ types.binaryExpression('*', page(vars), types.numericLiteral(vars.perPage)),
21
+ total(vars),
22
+ ]);
23
+ };
24
+ var buildNumber = function (placeholder, vars) {
25
+ var value = placeholder === 'from' ? buildFrom(vars) : placeholder === 'to' ? buildTo(vars) : total(vars);
26
+ return types.callExpression(types.memberExpression(value, types.identifier('toLocaleString')), [
27
+ types.stringLiteral('en-US'),
28
+ ]);
29
+ };
30
+ var templateElement = function (text, tail) {
31
+ return types.templateElement({ raw: text.replace(/\\|`|\$\{/g, function (match) { return "\\".concat(match); }), cooked: text }, tail);
32
+ };
33
+ /**
34
+ * The JSX printer writes a brace inside a static attribute as `&#123;` /
35
+ * `&#125;` so it is never read as an expression; the placeholders are braces,
36
+ * so the template is read back through that escaping.
37
+ */
38
+ var decodeBraces = function (text) {
39
+ return text
40
+ .replace(/&#123;|&#x7b;|&lbrace;/gi, '{')
41
+ .replace(/&#125;|&#x7d;|&rbrace;/gi, '}')
42
+ .replace(/&amp;/g, '&');
43
+ };
44
+ /** The author's template as a template literal, each placeholder a live number. */
45
+ var buildLiveText = function (template, vars) {
46
+ var quasis = [];
47
+ var expressions = [];
48
+ var placeholder = new RegExp(PLACEHOLDER.source, 'g');
49
+ var last = 0;
50
+ var match = placeholder.exec(template);
51
+ while (match) {
52
+ quasis.push(templateElement(template.slice(last, match.index), false));
53
+ expressions.push(buildNumber(match[1], vars));
54
+ last = match.index + match[0].length;
55
+ match = placeholder.exec(template);
56
+ }
57
+ quasis.push(templateElement(template.slice(last), true));
58
+ return types.templateLiteral(quasis, expressions);
59
+ };
60
+ /**
61
+ * Every `range` control under a component body, in document order. The body is
62
+ * a `BlockStatement`, so the walk has to cross statements, ternaries and the
63
+ * `cond && <jsx/>` of a gated section, not only JSX children.
64
+ */
65
+ export var findRangeControls = function (root) {
66
+ var found = [];
67
+ var traverse = function (node) {
68
+ if (!node || typeof node !== 'object') {
69
+ return;
70
+ }
71
+ if (node.type === 'JSXElement' &&
72
+ readJSXAttributeString(node, PAGINATION_CONTROL_ATTR) === 'range') {
73
+ found.push(node);
74
+ }
75
+ if (Array.isArray(node.children)) {
76
+ node.children.forEach(traverse);
77
+ }
78
+ if (Array.isArray(node.body)) {
79
+ node.body.forEach(traverse);
80
+ }
81
+ else {
82
+ traverse(node.body);
83
+ }
84
+ traverse(node.consequent);
85
+ traverse(node.alternate);
86
+ traverse(node.left);
87
+ traverse(node.right);
88
+ traverse(node.test);
89
+ traverse(node.expression);
90
+ traverse(node.argument);
91
+ };
92
+ traverse(root);
93
+ return found;
94
+ };
95
+ /**
96
+ * The element's own children as one expression, so they can be the fallback of
97
+ * a ternary: plain text becomes a string, anything richer rides along in a
98
+ * fragment.
99
+ */
100
+ var drawnText = function (children) {
101
+ var _a;
102
+ var texts = [];
103
+ for (var _i = 0, children_1 = children; _i < children_1.length; _i++) {
104
+ var child = children_1[_i];
105
+ if (child.type === 'JSXText') {
106
+ texts.push(child.value);
107
+ }
108
+ else if (child.type === 'JSXExpressionContainer' &&
109
+ ((_a = child.expression) === null || _a === void 0 ? void 0 : _a.type) === 'StringLiteral') {
110
+ texts.push(child.expression.value);
111
+ }
112
+ else {
113
+ return types.jsxFragment(types.jsxOpeningFragment(), types.jsxClosingFragment(), children);
114
+ }
115
+ }
116
+ return types.stringLiteral(texts.join('').replace(/\s+/g, ' ').trim());
117
+ };
118
+ /**
119
+ * `{total === null ? <drawn text> : `<template with live numbers>`}` in place of
120
+ * the element's children. The marker and template attributes stay on the
121
+ * element, so the published DOM carries the same contract the canvas reads.
122
+ */
123
+ export var wireRangeControl = function (node, vars) {
124
+ var _a;
125
+ var template = decodeBraces(readJSXAttributeString(node, RANGE_TEMPLATE_ATTR)) || DEFAULT_RANGE_TEMPLATE;
126
+ var drawn = drawnText(Array.isArray(node.children) ? node.children : []);
127
+ node.children = [
128
+ types.jsxExpressionContainer(types.conditionalExpression(types.binaryExpression('===', total(vars), types.nullLiteral()), drawn, buildLiveText(template, vars))),
129
+ ];
130
+ if (node.openingElement) {
131
+ node.openingElement.selfClosing = false;
132
+ }
133
+ if (!node.closingElement && ((_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name)) {
134
+ node.closingElement = types.jsxClosingElement(types.cloneNode(node.openingElement.name, true));
135
+ }
136
+ };
137
+ //# sourceMappingURL=range-control.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"range-control.js","sourceRoot":"","sources":["../../src/range-control.ts"],"names":[],"mappings":"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"}
@@ -1,7 +1,8 @@
1
1
  /**
2
2
  * The column that tells a table's rows apart, read from the table the project
3
- * saved: its primary key, else a column named `id`. The products table has `id`
4
- * from its first migration. Null when neither is known — then nothing is added,
3
+ * saved: its primary key, else a column named `id`. The platform listing
4
+ * tables (products, blog posts, booking items) have `id` from their first
5
+ * migration. Null when neither is known — then nothing is added,
5
6
  * rather than a column that may not exist.
6
7
  */
7
8
  export declare const rowIdentityColumn: (config: Record<string, unknown>, tableName: string) => string | null;
@@ -1 +1 @@
1
- {"version":3,"file":"row-order.d.ts","sourceRoot":"","sources":["../../src/row-order.ts"],"names":[],"mappings":"AAOA;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,WACpB,OAAO,MAAM,EAAE,OAAO,CAAC,aACpB,MAAM,KAChB,MAAM,GAAG,IAcX,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,mBAAoB,MAAM,GAAG,IAAI,KAAG,MAW9E,CAAA"}
1
+ {"version":3,"file":"row-order.d.ts","sourceRoot":"","sources":["../../src/row-order.ts"],"names":[],"mappings":"AAOA;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,WACpB,OAAO,MAAM,EAAE,OAAO,CAAC,aACpB,MAAM,KAChB,MAAM,GAAG,IAcX,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,8BAA8B,mBAAoB,MAAM,GAAG,IAAI,KAAG,MAW9E,CAAA"}
@@ -1,8 +1,9 @@
1
- import { supportsProductPriceSort } from './product-price-sort';
1
+ import { isListingTableWithId } from './list-sort-order';
2
2
  /**
3
3
  * The column that tells a table's rows apart, read from the table the project
4
- * saved: its primary key, else a column named `id`. The products table has `id`
5
- * from its first migration. Null when neither is known — then nothing is added,
4
+ * saved: its primary key, else a column named `id`. The platform listing
5
+ * tables (products, blog posts, booking items) have `id` from their first
6
+ * migration. Null when neither is known — then nothing is added,
6
7
  * rather than a column that may not exist.
7
8
  */
8
9
  export var rowIdentityColumn = function (config, tableName) {
@@ -15,7 +16,7 @@ export var rowIdentityColumn = function (config, tableName) {
15
16
  if (typeof key === 'string') {
16
17
  return key;
17
18
  }
18
- return supportsProductPriceSort(tableName) ? 'id' : null;
19
+ return isListingTableWithId(tableName) ? 'id' : null;
19
20
  };
20
21
  /**
21
22
  * The `rowOrderTiebreak(fields, direction)` helper a SQL fetcher embeds: what
@@ -1 +1 @@
1
- {"version":3,"file":"row-order.js","sourceRoot":"","sources":["../../src/row-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,wBAAwB,EAAE,MAAM,sBAAsB,CAAA;AAO/D;;;;;GAKG;AACH,MAAM,CAAC,IAAM,iBAAiB,GAAG,UAC/B,MAA+B,EAC/B,SAAiB;;IAEjB,IAAM,cAAc,GAAI,MAAqE;SAC1F,cAAc,CAAA;IACjB,IAAM,KAAK,GAAG,MAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAG,SAAS,CAAC,0CAAE,OAAO,CAAA;IAClD,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAsB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAC1E,UAAC,MAAM,IAAK,OAAA,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAA,KAAK,QAAQ,EAAhC,CAAgC,CAC7C,CAAA;IACD,IAAM,GAAG,GACP,MAAA,MAAA,OAAO,CAAC,IAAI,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,YAAY,KAAK,IAAI,EAA5B,CAA4B,CAAC,0CAAE,IAAI,mCAC5D,MAAA,OAAO,CAAC,IAAI,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,IAAI,KAAK,IAAI,EAApB,CAAoB,CAAC,0CAAE,IAAI,CAAA;IACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,OAAO,GAAG,CAAA;KACX;IACD,OAAO,wBAAwB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;AAC1D,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,IAAM,8BAA8B,GAAG,UAAC,cAA6B;IAC1E,IAAI,CAAC,cAAc,EAAE;QACnB,OAAO,mCAAmC,CAAA;KAC3C;IACD,IAAM,MAAM,GAAG,YAAI,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAG,CAAA;IACxD,OAAO;QACL,iDAAiD;QACjD,4BAAqB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,sBAAY,IAAI,CAAC,SAAS,CAC3E,YAAK,MAAM,MAAG,CACf,iBAAc;KAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC,CAAA"}
1
+ {"version":3,"file":"row-order.js","sourceRoot":"","sources":["../../src/row-order.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAA;AAOxD;;;;;;GAMG;AACH,MAAM,CAAC,IAAM,iBAAiB,GAAG,UAC/B,MAA+B,EAC/B,SAAiB;;IAEjB,IAAM,cAAc,GAAI,MAAqE;SAC1F,cAAc,CAAA;IACjB,IAAM,KAAK,GAAG,MAAA,cAAc,aAAd,cAAc,uBAAd,cAAc,CAAG,SAAS,CAAC,0CAAE,OAAO,CAAA;IAClD,IAAM,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAE,KAAsB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,MAAM,CAC1E,UAAC,MAAM,IAAK,OAAA,OAAO,CAAA,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,IAAI,CAAA,KAAK,QAAQ,EAAhC,CAAgC,CAC7C,CAAA;IACD,IAAM,GAAG,GACP,MAAA,MAAA,OAAO,CAAC,IAAI,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,YAAY,KAAK,IAAI,EAA5B,CAA4B,CAAC,0CAAE,IAAI,mCAC5D,MAAA,OAAO,CAAC,IAAI,CAAC,UAAC,MAAM,IAAK,OAAA,MAAM,CAAC,IAAI,KAAK,IAAI,EAApB,CAAoB,CAAC,0CAAE,IAAI,CAAA;IACtD,IAAI,OAAO,GAAG,KAAK,QAAQ,EAAE;QAC3B,OAAO,GAAG,CAAA;KACX;IACD,OAAO,oBAAoB,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAA;AACtD,CAAC,CAAA;AAED;;;;;;;;;GASG;AACH,MAAM,CAAC,IAAM,8BAA8B,GAAG,UAAC,cAA6B;IAC1E,IAAI,CAAC,cAAc,EAAE;QACnB,OAAO,mCAAmC,CAAA;KAC3C;IACD,IAAM,MAAM,GAAG,YAAI,cAAc,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,OAAG,CAAA;IACxD,OAAO;QACL,iDAAiD;QACjD,4BAAqB,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,sBAAY,IAAI,CAAC,SAAS,CAC3E,YAAK,MAAM,MAAG,CACf,iBAAc;KAChB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;AACd,CAAC,CAAA"}
@@ -0,0 +1,42 @@
1
+ /**
2
+ * The search inputs of a page, and the mapper each one searches.
3
+ *
4
+ * Two kinds exist. The platform's own `DataSourceSearchInputNode` renders with
5
+ * a `search-input` class and is paired with a search-enabled mapper BY ORDER
6
+ * — the first such input searches the first such mapper. A page's OWN text
7
+ * input, kept where its author drew it, is marked `data-tq-search-for` with
8
+ * the node id of the mapper it searches — the marker the editor writes
9
+ * (`listing-search-field.ts`) and the canvas renderer binds by
10
+ * (`mapper-search-registry.ts`). Marked inputs are paired by that id and
11
+ * never take a place in the order, so a template's toolbar box beside a
12
+ * platform listing shifts nothing.
13
+ *
14
+ * Both are wired the same way: controlled by the mapper's search query state,
15
+ * which the mapper debounces into its fetch and keeps in the address.
16
+ */
17
+ export declare const SEARCH_FOR_ATTR = "data-tq-search-for";
18
+ export interface SearchInput {
19
+ node: any;
20
+ /** The mapper node id a marked input names; undefined for a platform input paired by order. */
21
+ forNodeId?: string;
22
+ }
23
+ /** Every search input under `root`, in document order. */
24
+ export declare function findAllSearchInputsInJSX(root: any): SearchInput[];
25
+ /**
26
+ * The search-enabled usage each input searches: a marked input's by the mapper
27
+ * node id it names, a platform input's by its place among the platform inputs.
28
+ */
29
+ export declare function pairSearchInputs<Usage extends {
30
+ searchEnabled: boolean;
31
+ nodeId?: string;
32
+ }>(inputs: SearchInput[], usages: Usage[]): Map<any, Usage>;
33
+ /**
34
+ * Controls the input by the mapper's query: `value` reads it, `onChange`
35
+ * writes it. A marked input may sit inside a form of the page's own; Enter
36
+ * in it must not submit that form and reload the filtered list away.
37
+ */
38
+ export declare function wireSearchInput(input: SearchInput, vars: {
39
+ searchQueryVar: string;
40
+ setSearchQueryVar: string;
41
+ }): void;
42
+ //# sourceMappingURL=search-input.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-input.d.ts","sourceRoot":"","sources":["../../src/search-input.ts"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;GAeG;AAEH,eAAO,MAAM,eAAe,uBAAuB,CAAA;AAInD,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,GAAG,CAAA;IACT,+FAA+F;IAC/F,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAUD,0DAA0D;AAC1D,wBAAgB,wBAAwB,CAAC,IAAI,EAAE,GAAG,GAAG,WAAW,EAAE,CAyDjE;AAED;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,SAAS;IAAE,aAAa,EAAE,OAAO,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,EACxF,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,KAAK,EAAE,GACd,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAmBjB;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,EAClB,IAAI,EAAE;IAAE,cAAc,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAA;CAAE,GAC1D,IAAI,CAuDN"}
@@ -0,0 +1,129 @@
1
+ import * as types from '@babel/types';
2
+ import { readJSXAttributeString } from './pagination-controls';
3
+ /**
4
+ * The search inputs of a page, and the mapper each one searches.
5
+ *
6
+ * Two kinds exist. The platform's own `DataSourceSearchInputNode` renders with
7
+ * a `search-input` class and is paired with a search-enabled mapper BY ORDER
8
+ * — the first such input searches the first such mapper. A page's OWN text
9
+ * input, kept where its author drew it, is marked `data-tq-search-for` with
10
+ * the node id of the mapper it searches — the marker the editor writes
11
+ * (`listing-search-field.ts`) and the canvas renderer binds by
12
+ * (`mapper-search-registry.ts`). Marked inputs are paired by that id and
13
+ * never take a place in the order, so a template's toolbar box beside a
14
+ * platform listing shifts nothing.
15
+ *
16
+ * Both are wired the same way: controlled by the mapper's search query state,
17
+ * which the mapper debounces into its fetch and keeps in the address.
18
+ */
19
+ export var SEARCH_FOR_ATTR = 'data-tq-search-for';
20
+ function isInput(node) {
21
+ var _a, _b;
22
+ return (node === null || node === void 0 ? void 0 : node.type) === 'JSXElement' && ((_b = (_a = node.openingElement) === null || _a === void 0 ? void 0 : _a.name) === null || _b === void 0 ? void 0 : _b.name) === 'input';
23
+ }
24
+ function hasSearchInputClass(node) {
25
+ return readJSXAttributeString(node, 'className').includes('search-input');
26
+ }
27
+ /** Every search input under `root`, in document order. */
28
+ export function findAllSearchInputsInJSX(root) {
29
+ var results = [];
30
+ var traverse = function (node) {
31
+ if (!node) {
32
+ return;
33
+ }
34
+ if (isInput(node)) {
35
+ var forNodeId = readJSXAttributeString(node, SEARCH_FOR_ATTR);
36
+ if (forNodeId) {
37
+ results.push({ node: node, forNodeId: forNodeId });
38
+ }
39
+ else if (hasSearchInputClass(node)) {
40
+ results.push({ node: node });
41
+ }
42
+ }
43
+ if (node.children && Array.isArray(node.children)) {
44
+ node.children.forEach(function (c) { return traverse(c); });
45
+ }
46
+ if (node.body) {
47
+ if (Array.isArray(node.body)) {
48
+ node.body.forEach(function (s) { return traverse(s); });
49
+ }
50
+ else {
51
+ traverse(node.body);
52
+ }
53
+ }
54
+ if (node.consequent) {
55
+ traverse(node.consequent);
56
+ }
57
+ if (node.alternate) {
58
+ traverse(node.alternate);
59
+ }
60
+ // `{activeTabIndex === 0 && (<div>…<DataProvider/>…</div>)}` — a tab
61
+ // panel, a gated section: the provider sits on the RIGHT of a logical
62
+ // expression (or in a ternary's `test`), which is not a child, a body or
63
+ // an argument. Left unvisited, the products list under the first tab of
64
+ // a shop was never paginated or seeded, and rendered nothing.
65
+ if (node.left) {
66
+ traverse(node.left);
67
+ }
68
+ if (node.right) {
69
+ traverse(node.right);
70
+ }
71
+ if (node.test) {
72
+ traverse(node.test);
73
+ }
74
+ if (node.expression) {
75
+ traverse(node.expression);
76
+ }
77
+ if (node.argument) {
78
+ traverse(node.argument);
79
+ }
80
+ };
81
+ traverse(root);
82
+ return results;
83
+ }
84
+ /**
85
+ * The search-enabled usage each input searches: a marked input's by the mapper
86
+ * node id it names, a platform input's by its place among the platform inputs.
87
+ */
88
+ export function pairSearchInputs(inputs, usages) {
89
+ var searchable = usages.filter(function (usage) { return usage.searchEnabled; });
90
+ var paired = new Map();
91
+ var position = 0;
92
+ var _loop_1 = function (input) {
93
+ if (input.forNodeId) {
94
+ var named = searchable.find(function (candidate) { return candidate.nodeId === input.forNodeId; });
95
+ if (named) {
96
+ paired.set(input.node, named);
97
+ }
98
+ return "continue";
99
+ }
100
+ var next = searchable[position];
101
+ position += 1;
102
+ if (next) {
103
+ paired.set(input.node, next);
104
+ }
105
+ };
106
+ for (var _i = 0, inputs_1 = inputs; _i < inputs_1.length; _i++) {
107
+ var input = inputs_1[_i];
108
+ _loop_1(input);
109
+ }
110
+ return paired;
111
+ }
112
+ /**
113
+ * Controls the input by the mapper's query: `value` reads it, `onChange`
114
+ * writes it. A marked input may sit inside a form of the page's own; Enter
115
+ * in it must not submit that form and reload the filtered list away.
116
+ */
117
+ export function wireSearchInput(input, vars) {
118
+ var attributes = input.node.openingElement.attributes.filter(function (attr) { var _a; return !['onChange', 'value', 'onKeyDown'].includes((_a = attr.name) === null || _a === void 0 ? void 0 : _a.name); });
119
+ attributes.push(types.jsxAttribute(types.jsxIdentifier('onChange'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier('e')], types.callExpression(types.identifier(vars.setSearchQueryVar), [
120
+ types.memberExpression(types.memberExpression(types.identifier('e'), types.identifier('target')), types.identifier('value')),
121
+ ])))), types.jsxAttribute(types.jsxIdentifier('value'), types.jsxExpressionContainer(types.identifier(vars.searchQueryVar))));
122
+ if (input.forNodeId) {
123
+ attributes.push(types.jsxAttribute(types.jsxIdentifier('onKeyDown'), types.jsxExpressionContainer(types.arrowFunctionExpression([types.identifier('e')], types.blockStatement([
124
+ types.ifStatement(types.binaryExpression('===', types.memberExpression(types.identifier('e'), types.identifier('key')), types.stringLiteral('Enter')), types.expressionStatement(types.callExpression(types.memberExpression(types.identifier('e'), types.identifier('preventDefault')), []))),
125
+ ])))));
126
+ }
127
+ input.node.openingElement.attributes = attributes;
128
+ }
129
+ //# sourceMappingURL=search-input.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"search-input.js","sourceRoot":"","sources":["../../src/search-input.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
1
  import * as types from '@babel/types';
2
- import { UIDLExpressionValue, UIDLStaticValue } from '@teleporthq/teleport-types';
2
+ import { UIDLExpressionValue, UIDLStateDefinition, UIDLStaticValue } from '@teleporthq/teleport-types';
3
3
  export interface DynamicSortAST {
4
4
  field: types.Expression;
5
5
  order: types.Expression;
@@ -16,5 +16,57 @@ export declare const readFixedSort: (sort: UIDLStaticValue | UIDLExpressionValue
16
16
  order: 'asc' | 'desc';
17
17
  } | undefined;
18
18
  export declare const extractDynamicSort: (sort: UIDLStaticValue | UIDLExpressionValue | undefined, sortDirection: UIDLStaticValue | UIDLExpressionValue | undefined) => DynamicSortAST | undefined;
19
+ /**
20
+ * A page state a state-bound sort reads, at the value the visitor starts with.
21
+ */
22
+ export interface SortStateDefault {
23
+ /** The state's binding in the component: the name the sort expressions read. */
24
+ binding: string;
25
+ value: string | number | boolean;
26
+ }
27
+ /**
28
+ * The states a state-bound sort reads, at their defaults: the sort a visitor
29
+ * starts with, which the build can fetch the first page by.
30
+ *
31
+ * Only when every name the column and the direction read is a state of this
32
+ * component starting at a fixed value. Anything else they read — a prop, the
33
+ * router, `window` — or a state the page seeds from its data leaves the build
34
+ * unable to know the starting sort: `undefined`, and the list fetches its first
35
+ * page in the browser. An empty list is a sort that reads nothing.
36
+ */
37
+ export declare const readSortStateDefaults: (dynamicSort: DynamicSortAST, stateDefinitions: Record<string, UIDLStateDefinition> | undefined) => SortStateDefault[] | undefined;
38
+ /**
39
+ * A list repeater's own sort, read the one way for every part of the plugin
40
+ * that fetches the list's rows — the build's fetch for a page and the
41
+ * browser's: a column the editor fixed (`fixed`), or one bound to state
42
+ * (`dynamic`) with, when the build can know them, the values a visitor starts
43
+ * with (`starting`, see `readSortStateDefaults`). Empty without a sort.
44
+ */
45
+ export interface RepeaterSort {
46
+ fixed?: {
47
+ field: string;
48
+ order: 'asc' | 'desc';
49
+ };
50
+ dynamic?: DynamicSortAST;
51
+ starting?: SortStateDefault[];
52
+ }
53
+ export declare const readRepeaterSort: (sort: UIDLStaticValue | UIDLExpressionValue | undefined, sortDirection: UIDLStaticValue | UIDLExpressionValue | undefined, stateDefinitions: Record<string, UIDLStateDefinition> | undefined) => RepeaterSort;
54
+ /**
55
+ * The `sorts` param of the build-time fetch: the browser's own expression,
56
+ * evaluated with every state it reads at its default —
57
+ *
58
+ * ((sortBy) => JSON.stringify([{ field: sortBy.split("-")?.[0] || '', order: … }]))("name-asc")
59
+ *
60
+ * — so it is the very string the browser sends while the sort is untouched, and
61
+ * the data source orders the first page exactly as it orders every later one
62
+ * (the same columns, empty values last, the row's id breaking ties).
63
+ */
64
+ export declare const buildStartingSortsValue: (dynamicSort: DynamicSortAST, defaults: SortStateDefault[]) => types.Expression;
65
+ /**
66
+ * `sortBy === "name-asc"`: the sort is still the one the visitor starts with,
67
+ * so the rows fetched at build time are its first page. `null` for a sort that
68
+ * reads nothing, which never moves.
69
+ */
70
+ export declare const buildSortAtStartGuard: (defaults: SortStateDefault[]) => types.Expression | null;
19
71
  export declare const appendSortsParam: (paramsProps: types.ObjectProperty[], legacySorts: any[] | undefined, dynamicSort: DynamicSortAST | undefined) => void;
20
72
  //# sourceMappingURL=sort-utils.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"sort-utils.d.ts","sourceRoot":"","sources":["../../src/sort-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC,OAAO,EAAE,mBAAmB,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAA;AAEjF,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC,UAAU,CAAA;IACvB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AAyDD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,eAAe,GAAG,mBAAmB,GAAG,SAAS,iBACxC,eAAe,GAAG,mBAAmB,GAAG,SAAS,KAC/D;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,GAAG,SAc7C,CAAA;AAED,eAAO,MAAM,kBAAkB,SACvB,eAAe,GAAG,mBAAmB,GAAG,SAAS,iBACxC,eAAe,GAAG,mBAAmB,GAAG,SAAS,KAC/D,cAAc,GAAG,SAkBnB,CAAA;AAiDD,eAAO,MAAM,gBAAgB,gBACd,MAAM,cAAc,EAAE,eAEtB,GAAG,EAAE,GAAG,SAAS,eACjB,cAAc,GAAG,SAAS,KACtC,IASF,CAAA"}
1
+ {"version":3,"file":"sort-utils.d.ts","sourceRoot":"","sources":["../../src/sort-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAGrC,OAAO,EACL,mBAAmB,EACnB,mBAAmB,EACnB,eAAe,EAChB,MAAM,4BAA4B,CAAA;AAEnC,MAAM,WAAW,cAAc;IAC7B,KAAK,EAAE,KAAK,CAAC,UAAU,CAAA;IACvB,KAAK,EAAE,KAAK,CAAC,UAAU,CAAA;IACvB,WAAW,EAAE,MAAM,EAAE,CAAA;CACtB;AA6DD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,SAClB,eAAe,GAAG,mBAAmB,GAAG,SAAS,iBACxC,eAAe,GAAG,mBAAmB,GAAG,SAAS,KAC/D;IAAE,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;CAAE,GAAG,SAc7C,CAAA;AAED,eAAO,MAAM,kBAAkB,SACvB,eAAe,GAAG,mBAAmB,GAAG,SAAS,iBACxC,eAAe,GAAG,mBAAmB,GAAG,SAAS,KAC/D,cAAc,GAAG,SAkBnB,CAAA;AAoBD;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,OAAO,EAAE,MAAM,CAAA;IACf,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CACjC;AAWD;;;;;;;;;GASG;AACH,eAAO,MAAM,qBAAqB,gBACnB,cAAc,oBACT,OAAO,MAAM,EAAE,mBAAmB,CAAC,GAAG,SAAS,KAChE,gBAAgB,EAAE,GAAG,SAyBvB,CAAA;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,KAAK,GAAG,MAAM,CAAA;KAAE,CAAA;IAChD,OAAO,CAAC,EAAE,cAAc,CAAA;IACxB,QAAQ,CAAC,EAAE,gBAAgB,EAAE,CAAA;CAC9B;AAED,eAAO,MAAM,gBAAgB,SACrB,eAAe,GAAG,mBAAmB,GAAG,SAAS,iBACxC,eAAe,GAAG,mBAAmB,GAAG,SAAS,oBAC9C,OAAO,MAAM,EAAE,mBAAmB,CAAC,GAAG,SAAS,KAChE,YAUF,CAAA;AAED;;;;;;;;;GASG;AACH,eAAO,MAAM,uBAAuB,gBACrB,cAAc,YACjB,gBAAgB,EAAE,KAC3B,MAAM,UAYR,CAAA;AAED;;;;GAIG;AACH,eAAO,MAAM,qBAAqB,aAAc,gBAAgB,EAAE,KAAG,MAAM,UAAU,GAAG,IAanF,CAAA;AA+BL,eAAO,MAAM,gBAAgB,gBACd,MAAM,cAAc,EAAE,eAEtB,GAAG,EAAE,GAAG,SAAS,eACjB,cAAc,GAAG,SAAS,KACtC,IASF,CAAA"}
@@ -9,6 +9,7 @@ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
9
9
  };
10
10
  import * as types from '@babel/types';
11
11
  import { ASTUtils } from '@teleporthq/teleport-plugin-common';
12
+ import { JSIdentifiers } from '@teleporthq/teleport-shared';
12
13
  var SKIP_IDENTIFIERS = new Set([
13
14
  'undefined',
14
15
  'NaN',
@@ -18,20 +19,21 @@ var SKIP_IDENTIFIERS = new Set([
18
19
  'document',
19
20
  'console',
20
21
  ]);
21
- var collectIdentifiers = function (node, acc) {
22
+ var collectIdentifiers = function (node, acc, skip) {
23
+ if (skip === void 0) { skip = SKIP_IDENTIFIERS; }
22
24
  if (!node || typeof node !== 'object') {
23
25
  return;
24
26
  }
25
27
  if (node.type === 'Identifier') {
26
- if (!SKIP_IDENTIFIERS.has(node.name)) {
28
+ if (!skip.has(node.name)) {
27
29
  acc.add(node.name);
28
30
  }
29
31
  return;
30
32
  }
31
33
  if (node.type === 'MemberExpression') {
32
- collectIdentifiers(node.object, acc);
34
+ collectIdentifiers(node.object, acc, skip);
33
35
  if (node.computed) {
34
- collectIdentifiers(node.property, acc);
36
+ collectIdentifiers(node.property, acc, skip);
35
37
  }
36
38
  return;
37
39
  }
@@ -41,10 +43,10 @@ var collectIdentifiers = function (node, acc) {
41
43
  // tslint:disable-next-line:no-any
42
44
  var child = node[key];
43
45
  if (Array.isArray(child)) {
44
- child.forEach(function (c) { return collectIdentifiers(c, acc); });
46
+ child.forEach(function (c) { return collectIdentifiers(c, acc, skip); });
45
47
  }
46
48
  else if (child && typeof child === 'object' && typeof child.type === 'string') {
47
- collectIdentifiers(child, acc);
49
+ collectIdentifiers(child, acc, skip);
48
50
  }
49
51
  }
50
52
  };
@@ -93,16 +95,102 @@ export var extractDynamicSort = function (sort, sortDirection) {
93
95
  depStateIds: Array.from(depSet),
94
96
  };
95
97
  };
96
- // Build the AST for `sorts: JSON.stringify([{ field: <fieldExpr>, order: <orderExpr> }])`
97
- var buildDynamicSortsProperty = function (dynamicSort) {
98
- return types.objectProperty(types.identifier('sorts'), types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
98
+ // `JSON.stringify([{ field: <fieldExpr>, order: <orderExpr> }])`
99
+ var buildDynamicSortsValue = function (dynamicSort) {
100
+ return types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [
99
101
  types.arrayExpression([
100
102
  types.objectExpression([
101
- types.objectProperty(types.identifier('field'), types.cloneNode(dynamicSort.field)),
102
- types.objectProperty(types.identifier('order'), types.cloneNode(dynamicSort.order)),
103
+ types.objectProperty(types.identifier('field'), types.cloneNode(dynamicSort.field, true)),
104
+ types.objectProperty(types.identifier('order'), types.cloneNode(dynamicSort.order, true)),
103
105
  ]),
104
106
  ]),
105
- ]));
107
+ ]);
108
+ };
109
+ // Build the AST for `sorts: JSON.stringify([{ field: <fieldExpr>, order: <orderExpr> }])`
110
+ var buildDynamicSortsProperty = function (dynamicSort) {
111
+ return types.objectProperty(types.identifier('sorts'), buildDynamicSortsValue(dynamicSort));
112
+ };
113
+ // Names a sort expression may read besides its states: they mean the same on
114
+ // the server and in the browser.
115
+ var CONSTANT_IDENTIFIERS = new Set(['undefined', 'NaN', 'Infinity']);
116
+ var isStartingValue = function (value) {
117
+ return typeof value === 'string' ||
118
+ typeof value === 'boolean' ||
119
+ (typeof value === 'number' && Number.isFinite(value));
120
+ };
121
+ /**
122
+ * The states a state-bound sort reads, at their defaults: the sort a visitor
123
+ * starts with, which the build can fetch the first page by.
124
+ *
125
+ * Only when every name the column and the direction read is a state of this
126
+ * component starting at a fixed value. Anything else they read — a prop, the
127
+ * router, `window` — or a state the page seeds from its data leaves the build
128
+ * unable to know the starting sort: `undefined`, and the list fetches its first
129
+ * page in the browser. An empty list is a sort that reads nothing.
130
+ */
131
+ export var readSortStateDefaults = function (dynamicSort, stateDefinitions) {
132
+ var read = new Set();
133
+ collectIdentifiers(dynamicSort.field, read, CONSTANT_IDENTIFIERS);
134
+ collectIdentifiers(dynamicSort.order, read, CONSTANT_IDENTIFIERS);
135
+ // A state's binding is its sanitised name, as the component declares it.
136
+ var stateByBinding = new Map();
137
+ Object.entries(stateDefinitions !== null && stateDefinitions !== void 0 ? stateDefinitions : {}).forEach(function (_a) {
138
+ var key = _a[0], definition = _a[1];
139
+ stateByBinding.set(JSIdentifiers.createSafeJSIdentifier(key), definition);
140
+ });
141
+ var defaults = [];
142
+ for (var _i = 0, _a = Array.from(read); _i < _a.length; _i++) {
143
+ var binding = _a[_i];
144
+ var definition = stateByBinding.get(binding);
145
+ if (!definition ||
146
+ definition.dataSourceBinding ||
147
+ definition.query ||
148
+ !isStartingValue(definition.defaultValue)) {
149
+ return undefined;
150
+ }
151
+ defaults.push({ binding: binding, value: definition.defaultValue });
152
+ }
153
+ return defaults;
154
+ };
155
+ export var readRepeaterSort = function (sort, sortDirection, stateDefinitions) {
156
+ if (!sort) {
157
+ return {};
158
+ }
159
+ var fixed = readFixedSort(sort, sortDirection);
160
+ if (fixed) {
161
+ return { fixed: fixed };
162
+ }
163
+ var dynamic = extractDynamicSort(sort, sortDirection);
164
+ return dynamic ? { dynamic: dynamic, starting: readSortStateDefaults(dynamic, stateDefinitions) } : {};
165
+ };
166
+ /**
167
+ * The `sorts` param of the build-time fetch: the browser's own expression,
168
+ * evaluated with every state it reads at its default —
169
+ *
170
+ * ((sortBy) => JSON.stringify([{ field: sortBy.split("-")?.[0] || '', order: … }]))("name-asc")
171
+ *
172
+ * — so it is the very string the browser sends while the sort is untouched, and
173
+ * the data source orders the first page exactly as it orders every later one
174
+ * (the same columns, empty values last, the row's id breaking ties).
175
+ */
176
+ export var buildStartingSortsValue = function (dynamicSort, defaults) {
177
+ var sorts = buildDynamicSortsValue(dynamicSort);
178
+ if (defaults.length === 0) {
179
+ return sorts;
180
+ }
181
+ return types.callExpression(types.arrowFunctionExpression(defaults.map(function (state) { return types.identifier(state.binding); }), sorts), defaults.map(function (state) { return types.valueToNode(state.value); }));
182
+ };
183
+ /**
184
+ * `sortBy === "name-asc"`: the sort is still the one the visitor starts with,
185
+ * so the rows fetched at build time are its first page. `null` for a sort that
186
+ * reads nothing, which never moves.
187
+ */
188
+ export var buildSortAtStartGuard = function (defaults) {
189
+ return defaults
190
+ .map(function (state) {
191
+ return types.binaryExpression('===', types.identifier(state.binding), types.valueToNode(state.value));
192
+ })
193
+ .reduce(function (all, guard) { return (all ? types.logicalExpression('&&', all, guard) : guard); }, null);
106
194
  };
107
195
  // Build the AST for the legacy static sorts array form.
108
196
  // tslint:disable-next-line:no-any