@teleporthq/teleport-plugin-next-data-source 0.43.74 → 0.44.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (231) hide show
  1. package/__tests__/_helpers/pagination-widget-fixture.ts +95 -5
  2. package/__tests__/blog-adjacent-arranged.test.ts +176 -0
  3. package/__tests__/blog-post-contents.test.ts +212 -0
  4. package/__tests__/blog-post-page-enrichment.test.ts +28 -5
  5. package/__tests__/blog-post-picture-stand-in.test.ts +48 -0
  6. package/__tests__/blog-post-reading-time.test.ts +55 -0
  7. package/__tests__/booking-item-transform.test.ts +120 -0
  8. package/__tests__/browser-row-policy.test.ts +13 -3
  9. package/__tests__/content-preset-wiring.test.ts +108 -0
  10. package/__tests__/fetchers.test.ts +1 -1
  11. package/__tests__/fixed-list-sort.test.ts +183 -0
  12. package/__tests__/infinite-scroll.test.ts +154 -5
  13. package/__tests__/list-sort-order.test.ts +61 -0
  14. package/__tests__/null-filter-where.test.ts +132 -0
  15. package/__tests__/pagination-filter-groups.test.ts +186 -0
  16. package/__tests__/pg-date-parser.test.ts +73 -0
  17. package/__tests__/plain-list-sort.test.ts +215 -0
  18. package/__tests__/product-price-sort.ts +58 -25
  19. package/__tests__/range-control.test.ts +159 -0
  20. package/__tests__/rest-api-key-header.test.ts +18 -0
  21. package/__tests__/search-input-marker.test.ts +86 -0
  22. package/__tests__/search-url-sync.test.ts +61 -16
  23. package/__tests__/shared-resource-prefetch.test.ts +65 -0
  24. package/__tests__/table-read-route-protected-tables.test.ts +33 -3
  25. package/dist/cjs/count-effect.d.ts +7 -1
  26. package/dist/cjs/count-effect.d.ts.map +1 -1
  27. package/dist/cjs/count-effect.js +15 -5
  28. package/dist/cjs/count-effect.js.map +1 -1
  29. package/dist/cjs/fetchers/pg-client-import.d.ts +12 -0
  30. package/dist/cjs/fetchers/pg-client-import.d.ts.map +1 -0
  31. package/dist/cjs/fetchers/pg-client-import.js +15 -0
  32. package/dist/cjs/fetchers/pg-client-import.js.map +1 -0
  33. package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
  34. package/dist/cjs/fetchers/postgresql.js +4 -1
  35. package/dist/cjs/fetchers/postgresql.js.map +1 -1
  36. package/dist/cjs/fetchers/raw-query.d.ts.map +1 -1
  37. package/dist/cjs/fetchers/raw-query.js +2 -1
  38. package/dist/cjs/fetchers/raw-query.js.map +1 -1
  39. package/dist/cjs/fetchers/rest-api.d.ts.map +1 -1
  40. package/dist/cjs/fetchers/rest-api.js +3 -1
  41. package/dist/cjs/fetchers/rest-api.js.map +1 -1
  42. package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
  43. package/dist/cjs/fetchers/teleport.js +5 -2
  44. package/dist/cjs/fetchers/teleport.js.map +1 -1
  45. package/dist/cjs/fetchers/utils/browser-row-policy.d.ts +7 -6
  46. package/dist/cjs/fetchers/utils/browser-row-policy.d.ts.map +1 -1
  47. package/dist/cjs/fetchers/utils/browser-row-policy.js +7 -33
  48. package/dist/cjs/fetchers/utils/browser-row-policy.js.map +1 -1
  49. package/dist/cjs/filter-utils.d.ts +19 -7
  50. package/dist/cjs/filter-utils.d.ts.map +1 -1
  51. package/dist/cjs/filter-utils.js +49 -13
  52. package/dist/cjs/filter-utils.js.map +1 -1
  53. package/dist/cjs/infinite-scroll.d.ts +25 -2
  54. package/dist/cjs/infinite-scroll.d.ts.map +1 -1
  55. package/dist/cjs/infinite-scroll.js +144 -33
  56. package/dist/cjs/infinite-scroll.js.map +1 -1
  57. package/dist/cjs/list-sort-order.d.ts +14 -0
  58. package/dist/cjs/list-sort-order.d.ts.map +1 -0
  59. package/dist/cjs/list-sort-order.js +36 -0
  60. package/dist/cjs/list-sort-order.js.map +1 -0
  61. package/dist/cjs/pagination-controls.d.ts +22 -3
  62. package/dist/cjs/pagination-controls.d.ts.map +1 -1
  63. package/dist/cjs/pagination-controls.js +29 -3
  64. package/dist/cjs/pagination-controls.js.map +1 -1
  65. package/dist/cjs/pagination-plugin.d.ts.map +1 -1
  66. package/dist/cjs/pagination-plugin.js +267 -212
  67. package/dist/cjs/pagination-plugin.js.map +1 -1
  68. package/dist/cjs/product-price-sort.d.ts +0 -9
  69. package/dist/cjs/product-price-sort.d.ts.map +1 -1
  70. package/dist/cjs/product-price-sort.js +1 -13
  71. package/dist/cjs/product-price-sort.js.map +1 -1
  72. package/dist/cjs/range-control.d.ts +45 -0
  73. package/dist/cjs/range-control.d.ts.map +1 -0
  74. package/dist/cjs/range-control.js +165 -0
  75. package/dist/cjs/range-control.js.map +1 -0
  76. package/dist/cjs/row-order.d.ts +20 -0
  77. package/dist/cjs/row-order.d.ts.map +1 -0
  78. package/dist/cjs/row-order.js +46 -0
  79. package/dist/cjs/row-order.js.map +1 -0
  80. package/dist/cjs/search-input.d.ts +42 -0
  81. package/dist/cjs/search-input.d.ts.map +1 -0
  82. package/dist/cjs/search-input.js +158 -0
  83. package/dist/cjs/search-input.js.map +1 -0
  84. package/dist/cjs/sort-utils.d.ts +10 -0
  85. package/dist/cjs/sort-utils.d.ts.map +1 -1
  86. package/dist/cjs/sort-utils.js +22 -1
  87. package/dist/cjs/sort-utils.js.map +1 -1
  88. package/dist/cjs/transformations/blog-adjacent-posts.d.ts +11 -1
  89. package/dist/cjs/transformations/blog-adjacent-posts.d.ts.map +1 -1
  90. package/dist/cjs/transformations/blog-adjacent-posts.js +14 -1
  91. package/dist/cjs/transformations/blog-adjacent-posts.js.map +1 -1
  92. package/dist/cjs/transformations/blog-comments.d.ts +1 -1
  93. package/dist/cjs/transformations/blog-comments.d.ts.map +1 -1
  94. package/dist/cjs/transformations/blog-comments.js +1 -1
  95. package/dist/cjs/transformations/blog-comments.js.map +1 -1
  96. package/dist/cjs/transformations/blog-post.d.ts +14 -0
  97. package/dist/cjs/transformations/blog-post.d.ts.map +1 -1
  98. package/dist/cjs/transformations/blog-post.js +4 -1
  99. package/dist/cjs/transformations/blog-post.js.map +1 -1
  100. package/dist/cjs/transformations/booking-item.d.ts +24 -0
  101. package/dist/cjs/transformations/booking-item.d.ts.map +1 -0
  102. package/dist/cjs/transformations/booking-item.js +27 -0
  103. package/dist/cjs/transformations/booking-item.js.map +1 -0
  104. package/dist/cjs/transformations/heading-anchors.d.ts +32 -8
  105. package/dist/cjs/transformations/heading-anchors.d.ts.map +1 -1
  106. package/dist/cjs/transformations/heading-anchors.js +34 -10
  107. package/dist/cjs/transformations/heading-anchors.js.map +1 -1
  108. package/dist/cjs/transformations/index.d.ts +27 -13
  109. package/dist/cjs/transformations/index.d.ts.map +1 -1
  110. package/dist/cjs/transformations/index.js +73 -16
  111. package/dist/cjs/transformations/index.js.map +1 -1
  112. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  113. package/dist/cjs/utils.d.ts.map +1 -1
  114. package/dist/cjs/utils.js +52 -3
  115. package/dist/cjs/utils.js.map +1 -1
  116. package/dist/esm/count-effect.d.ts +7 -1
  117. package/dist/esm/count-effect.d.ts.map +1 -1
  118. package/dist/esm/count-effect.js +15 -5
  119. package/dist/esm/count-effect.js.map +1 -1
  120. package/dist/esm/fetchers/pg-client-import.d.ts +12 -0
  121. package/dist/esm/fetchers/pg-client-import.d.ts.map +1 -0
  122. package/dist/esm/fetchers/pg-client-import.js +12 -0
  123. package/dist/esm/fetchers/pg-client-import.js.map +1 -0
  124. package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
  125. package/dist/esm/fetchers/postgresql.js +5 -2
  126. package/dist/esm/fetchers/postgresql.js.map +1 -1
  127. package/dist/esm/fetchers/raw-query.d.ts.map +1 -1
  128. package/dist/esm/fetchers/raw-query.js +2 -1
  129. package/dist/esm/fetchers/raw-query.js.map +1 -1
  130. package/dist/esm/fetchers/rest-api.d.ts.map +1 -1
  131. package/dist/esm/fetchers/rest-api.js +3 -1
  132. package/dist/esm/fetchers/rest-api.js.map +1 -1
  133. package/dist/esm/fetchers/teleport.d.ts.map +1 -1
  134. package/dist/esm/fetchers/teleport.js +6 -3
  135. package/dist/esm/fetchers/teleport.js.map +1 -1
  136. package/dist/esm/fetchers/utils/browser-row-policy.d.ts +7 -6
  137. package/dist/esm/fetchers/utils/browser-row-policy.d.ts.map +1 -1
  138. package/dist/esm/fetchers/utils/browser-row-policy.js +5 -31
  139. package/dist/esm/fetchers/utils/browser-row-policy.js.map +1 -1
  140. package/dist/esm/filter-utils.d.ts +19 -7
  141. package/dist/esm/filter-utils.d.ts.map +1 -1
  142. package/dist/esm/filter-utils.js +46 -12
  143. package/dist/esm/filter-utils.js.map +1 -1
  144. package/dist/esm/infinite-scroll.d.ts +25 -2
  145. package/dist/esm/infinite-scroll.d.ts.map +1 -1
  146. package/dist/esm/infinite-scroll.js +142 -32
  147. package/dist/esm/infinite-scroll.js.map +1 -1
  148. package/dist/esm/list-sort-order.d.ts +14 -0
  149. package/dist/esm/list-sort-order.d.ts.map +1 -0
  150. package/dist/esm/list-sort-order.js +32 -0
  151. package/dist/esm/list-sort-order.js.map +1 -0
  152. package/dist/esm/pagination-controls.d.ts +22 -3
  153. package/dist/esm/pagination-controls.d.ts.map +1 -1
  154. package/dist/esm/pagination-controls.js +28 -2
  155. package/dist/esm/pagination-controls.js.map +1 -1
  156. package/dist/esm/pagination-plugin.d.ts.map +1 -1
  157. package/dist/esm/pagination-plugin.js +271 -216
  158. package/dist/esm/pagination-plugin.js.map +1 -1
  159. package/dist/esm/product-price-sort.d.ts +0 -9
  160. package/dist/esm/product-price-sort.d.ts.map +1 -1
  161. package/dist/esm/product-price-sort.js +0 -11
  162. package/dist/esm/product-price-sort.js.map +1 -1
  163. package/dist/esm/range-control.d.ts +45 -0
  164. package/dist/esm/range-control.d.ts.map +1 -0
  165. package/dist/esm/range-control.js +137 -0
  166. package/dist/esm/range-control.js.map +1 -0
  167. package/dist/esm/row-order.d.ts +20 -0
  168. package/dist/esm/row-order.d.ts.map +1 -0
  169. package/dist/esm/row-order.js +41 -0
  170. package/dist/esm/row-order.js.map +1 -0
  171. package/dist/esm/search-input.d.ts +42 -0
  172. package/dist/esm/search-input.d.ts.map +1 -0
  173. package/dist/esm/search-input.js +129 -0
  174. package/dist/esm/search-input.js.map +1 -0
  175. package/dist/esm/sort-utils.d.ts +10 -0
  176. package/dist/esm/sort-utils.d.ts.map +1 -1
  177. package/dist/esm/sort-utils.js +20 -0
  178. package/dist/esm/sort-utils.js.map +1 -1
  179. package/dist/esm/transformations/blog-adjacent-posts.d.ts +11 -1
  180. package/dist/esm/transformations/blog-adjacent-posts.d.ts.map +1 -1
  181. package/dist/esm/transformations/blog-adjacent-posts.js +14 -1
  182. package/dist/esm/transformations/blog-adjacent-posts.js.map +1 -1
  183. package/dist/esm/transformations/blog-comments.d.ts +1 -1
  184. package/dist/esm/transformations/blog-comments.d.ts.map +1 -1
  185. package/dist/esm/transformations/blog-comments.js +1 -1
  186. package/dist/esm/transformations/blog-comments.js.map +1 -1
  187. package/dist/esm/transformations/blog-post.d.ts +14 -0
  188. package/dist/esm/transformations/blog-post.d.ts.map +1 -1
  189. package/dist/esm/transformations/blog-post.js +4 -1
  190. package/dist/esm/transformations/blog-post.js.map +1 -1
  191. package/dist/esm/transformations/booking-item.d.ts +24 -0
  192. package/dist/esm/transformations/booking-item.d.ts.map +1 -0
  193. package/dist/esm/transformations/booking-item.js +23 -0
  194. package/dist/esm/transformations/booking-item.js.map +1 -0
  195. package/dist/esm/transformations/heading-anchors.d.ts +32 -8
  196. package/dist/esm/transformations/heading-anchors.d.ts.map +1 -1
  197. package/dist/esm/transformations/heading-anchors.js +33 -9
  198. package/dist/esm/transformations/heading-anchors.js.map +1 -1
  199. package/dist/esm/transformations/index.d.ts +27 -13
  200. package/dist/esm/transformations/index.d.ts.map +1 -1
  201. package/dist/esm/transformations/index.js +72 -16
  202. package/dist/esm/transformations/index.js.map +1 -1
  203. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  204. package/dist/esm/utils.d.ts.map +1 -1
  205. package/dist/esm/utils.js +52 -3
  206. package/dist/esm/utils.js.map +1 -1
  207. package/package.json +5 -5
  208. package/src/count-effect.ts +31 -8
  209. package/src/fetchers/pg-client-import.ts +16 -0
  210. package/src/fetchers/postgresql.ts +25 -23
  211. package/src/fetchers/raw-query.ts +2 -1
  212. package/src/fetchers/rest-api.ts +3 -1
  213. package/src/fetchers/teleport.ts +22 -23
  214. package/src/fetchers/utils/browser-row-policy.ts +10 -20
  215. package/src/filter-utils.ts +102 -28
  216. package/src/infinite-scroll.ts +240 -79
  217. package/src/list-sort-order.ts +34 -0
  218. package/src/pagination-controls.ts +26 -3
  219. package/src/pagination-plugin.ts +370 -306
  220. package/src/product-price-sort.ts +0 -11
  221. package/src/range-control.ts +207 -0
  222. package/src/row-order.ts +55 -0
  223. package/src/search-input.ts +190 -0
  224. package/src/sort-utils.ts +25 -0
  225. package/src/transformations/blog-adjacent-posts.ts +89 -3
  226. package/src/transformations/blog-comments.ts +5 -5
  227. package/src/transformations/blog-post.ts +64 -13
  228. package/src/transformations/booking-item.ts +71 -0
  229. package/src/transformations/heading-anchors.ts +79 -16
  230. package/src/transformations/index.ts +104 -14
  231. package/src/utils.ts +74 -3
@@ -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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"}
@@ -0,0 +1,20 @@
1
+ /**
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 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,
6
+ * rather than a column that may not exist.
7
+ */
8
+ export declare const rowIdentityColumn: (config: Record<string, unknown>, tableName: string) => string | null;
9
+ /**
10
+ * The `rowOrderTiebreak(fields, direction)` helper a SQL fetcher embeds: what
11
+ * ends an ORDER BY so that it orders every row.
12
+ *
13
+ * Rows that share every requested key have no order of their own, and the
14
+ * database deals them out differently for each page — "sort by discount" ties
15
+ * every undiscounted product at zero, and an import dates hundreds of articles
16
+ * alike — so a paginated list repeated some rows and never showed others.
17
+ * The tie follows the last key's direction, as the editor's canvas does.
18
+ */
19
+ export declare const generateRowOrderTiebreakHelper: (identityColumn: string | null) => string;
20
+ //# sourceMappingURL=row-order.d.ts.map
@@ -0,0 +1 @@
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"}
@@ -0,0 +1,41 @@
1
+ import { isListingTableWithId } from './list-sort-order';
2
+ /**
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 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,
7
+ * rather than a column that may not exist.
8
+ */
9
+ export var rowIdentityColumn = function (config, tableName) {
10
+ var _a, _b, _c, _d;
11
+ var selectedTables = config
12
+ .selectedTables;
13
+ var saved = (_a = selectedTables === null || selectedTables === void 0 ? void 0 : selectedTables[tableName]) === null || _a === void 0 ? void 0 : _a.columns;
14
+ var columns = (Array.isArray(saved) ? saved : []).filter(function (column) { return typeof (column === null || column === void 0 ? void 0 : column.name) === 'string'; });
15
+ var key = (_c = (_b = columns.find(function (column) { return column.isPrimaryKey === true; })) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : (_d = columns.find(function (column) { return column.name === 'id'; })) === null || _d === void 0 ? void 0 : _d.name;
16
+ if (typeof key === 'string') {
17
+ return key;
18
+ }
19
+ return isListingTableWithId(tableName) ? 'id' : null;
20
+ };
21
+ /**
22
+ * The `rowOrderTiebreak(fields, direction)` helper a SQL fetcher embeds: what
23
+ * ends an ORDER BY so that it orders every row.
24
+ *
25
+ * Rows that share every requested key have no order of their own, and the
26
+ * database deals them out differently for each page — "sort by discount" ties
27
+ * every undiscounted product at zero, and an import dates hundreds of articles
28
+ * alike — so a paginated list repeated some rows and never showed others.
29
+ * The tie follows the last key's direction, as the editor's canvas does.
30
+ */
31
+ export var generateRowOrderTiebreakHelper = function (identityColumn) {
32
+ if (!identityColumn) {
33
+ return "const rowOrderTiebreak = () => ''";
34
+ }
35
+ var quoted = "\"".concat(identityColumn.replace(/"/g, '""'), "\"");
36
+ return [
37
+ 'const rowOrderTiebreak = (fields, direction) =>',
38
+ " fields.includes(".concat(JSON.stringify(identityColumn), ") ? '' : ").concat(JSON.stringify(", ".concat(quoted, " ")), " + direction"),
39
+ ].join('\n');
40
+ };
41
+ //# sourceMappingURL=row-order.js.map
@@ -0,0 +1 @@
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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"}
@@ -5,6 +5,16 @@ export interface DynamicSortAST {
5
5
  order: types.Expression;
6
6
  depStateIds: string[];
7
7
  }
8
+ /**
9
+ * The `{ field, order }` of a sort the UIDL FIXES — a static column and a
10
+ * static direction (or none: ascending) — or undefined for one bound to state.
11
+ * A fixed sort is a static sort: it rides on the server-side first-page fetch
12
+ * and the client keeps that page, which a dynamic sort cannot let it do.
13
+ */
14
+ export declare const readFixedSort: (sort: UIDLStaticValue | UIDLExpressionValue | undefined, sortDirection: UIDLStaticValue | UIDLExpressionValue | undefined) => {
15
+ field: string;
16
+ order: 'asc' | 'desc';
17
+ } | undefined;
8
18
  export declare const extractDynamicSort: (sort: UIDLStaticValue | UIDLExpressionValue | undefined, sortDirection: UIDLStaticValue | UIDLExpressionValue | undefined) => DynamicSortAST | undefined;
9
19
  export declare const appendSortsParam: (paramsProps: types.ObjectProperty[], legacySorts: any[] | undefined, dynamicSort: DynamicSortAST | undefined) => void;
10
20
  //# 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,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;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"}
@@ -58,6 +58,26 @@ var toExpressionAndDeps = function (value) {
58
58
  collectIdentifiers(parsed, deps);
59
59
  return { expr: parsed, deps: Array.from(deps) };
60
60
  };
61
+ /**
62
+ * The `{ field, order }` of a sort the UIDL FIXES — a static column and a
63
+ * static direction (or none: ascending) — or undefined for one bound to state.
64
+ * A fixed sort is a static sort: it rides on the server-side first-page fetch
65
+ * and the client keeps that page, which a dynamic sort cannot let it do.
66
+ */
67
+ export var readFixedSort = function (sort, sortDirection) {
68
+ var _a;
69
+ if ((sort === null || sort === void 0 ? void 0 : sort.type) !== 'static' || typeof sort.content !== 'string' || !sort.content.trim()) {
70
+ return undefined;
71
+ }
72
+ if (sortDirection &&
73
+ (sortDirection.type !== 'static' || typeof sortDirection.content !== 'string')) {
74
+ return undefined;
75
+ }
76
+ var direction = String((_a = sortDirection === null || sortDirection === void 0 ? void 0 : sortDirection.content) !== null && _a !== void 0 ? _a : '')
77
+ .trim()
78
+ .toLowerCase();
79
+ return { field: sort.content.trim(), order: direction.startsWith('desc') ? 'desc' : 'asc' };
80
+ };
61
81
  export var extractDynamicSort = function (sort, sortDirection) {
62
82
  if (!sort) {
63
83
  return undefined;
@@ -1 +1 @@
1
- {"version":3,"file":"sort-utils.js","sourceRoot":"","sources":["../../src/sort-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"sort-utils.js","sourceRoot":"","sources":["../../src/sort-utils.ts"],"names":[],"mappings":"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"}
@@ -11,6 +11,16 @@
11
11
  *
12
12
  * MUST mirror `findAdjacentBlogPosts` in teleport-gui
13
13
  * `packages/renderer/src/utils/blog-adjacent-posts.ts` (the canvas).
14
+ *
15
+ * In Manual Order (`arranged`) a post walks the published posts of its
16
+ * PRIMARY category (the first of `category_ids`) the way the author arranged
17
+ * them: the ones with a place (`sort_order`) by it, then the rest newest
18
+ * first, ties by id — "previous" the one above it, "next" the one below. The
19
+ * category is read off each row in code, since a list cell may be JSON or a
20
+ * comma-separated list (see `array-overlap-sql.ts`). A post without a
21
+ * category, or a table the query cannot read (a column it lacks), walks the
22
+ * newest-first order above. MUST mirror `findArrangedAdjacentPosts` in
23
+ * teleport-gui `apps/gui/app/project-page/features/blog/utils/arranged-order.ts`.
14
24
  */
15
- export declare const generateAdjacentPostsCode: () => string;
25
+ export declare const generateAdjacentPostsCode: (postsTable: string, arranged?: boolean) => string;
16
26
  //# sourceMappingURL=blog-adjacent-posts.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"blog-adjacent-posts.d.ts","sourceRoot":"","sources":["../../../src/transformations/blog-adjacent-posts.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,yBAAyB,QAAO,MAqD5C,CAAA"}
1
+ {"version":3,"file":"blog-adjacent-posts.d.ts","sourceRoot":"","sources":["../../../src/transformations/blog-adjacent-posts.ts"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,yBAAyB,eAAgB,MAAM,yBAAqB,MAiIhF,CAAA"}
@@ -16,6 +16,19 @@ var ADJACENT_POST_CANDIDATES = 5;
16
16
  *
17
17
  * MUST mirror `findAdjacentBlogPosts` in teleport-gui
18
18
  * `packages/renderer/src/utils/blog-adjacent-posts.ts` (the canvas).
19
+ *
20
+ * In Manual Order (`arranged`) a post walks the published posts of its
21
+ * PRIMARY category (the first of `category_ids`) the way the author arranged
22
+ * them: the ones with a place (`sort_order`) by it, then the rest newest
23
+ * first, ties by id — "previous" the one above it, "next" the one below. The
24
+ * category is read off each row in code, since a list cell may be JSON or a
25
+ * comma-separated list (see `array-overlap-sql.ts`). A post without a
26
+ * category, or a table the query cannot read (a column it lacks), walks the
27
+ * newest-first order above. MUST mirror `findArrangedAdjacentPosts` in
28
+ * teleport-gui `apps/gui/app/project-page/features/blog/utils/arranged-order.ts`.
19
29
  */
20
- export var generateAdjacentPostsCode = function () { return "\nvar BLOG_ADJACENT_CANDIDATES = ".concat(ADJACENT_POST_CANDIDATES, "\n\nfunction blogAdjacentPostsSql(comparison, direction) {\n return (\n 'SELECT p.* FROM teleport_blog_posts p,' +\n ' (SELECT created_at, id FROM teleport_blog_posts WHERE id = $1) cur' +\n \" WHERE p.status = 'published' AND (p.created_at, p.id) \" + comparison + ' (cur.created_at, cur.id)' +\n ' ORDER BY p.created_at ' + direction + ', p.id ' + direction +\n ' LIMIT ' + BLOG_ADJACENT_CANDIDATES\n )\n}\n\nfunction firstLinkableBlogPost(result) {\n var rows = result && Array.isArray(result.rows) ? result.rows : []\n for (var i = 0; i < rows.length; i++) {\n var row = rows[i]\n if (!row) continue\n var redirect = pickFirst(row.redirect_url, row.redirectUrl)\n if (typeof redirect === 'string' && redirect.trim() !== '') continue\n // Through JSON, like the rows the fetcher itself hands the transform.\n return JSON.parse(JSON.stringify(row))\n }\n return null\n}\n\n// { [postId]: { previous, next } } \u2014 raw rows or null \u2014 for a single-record\n// fetch; {} otherwise and on any failure (the navigation then hides).\nasync function getAdjacentPostsMap(getClientFn, records) {\n var map = {}\n if (!Array.isArray(records) || records.length !== 1) return map\n var postId = records[0] && records[0].id\n if (postId === null || postId === undefined) return map\n\n var client\n try {\n client = getClientFn()\n await client.connect()\n var older = await client.query(blogAdjacentPostsSql('<', 'DESC'), [String(postId)])\n var newer = await client.query(blogAdjacentPostsSql('>', 'ASC'), [String(postId)])\n map[String(postId)] = {\n previous: firstLinkableBlogPost(older),\n next: firstLinkableBlogPost(newer),\n }\n } catch (e) {\n // Leaves the navigation hidden.\n } finally {\n if (client) {\n try { await client.end() } catch (e) { /* ignore */ }\n }\n }\n return map\n}\n"); };
30
+ export var generateAdjacentPostsCode = function (postsTable, arranged) {
31
+ if (arranged === void 0) { arranged = false; }
32
+ return "\nvar BLOG_ADJACENT_CANDIDATES = ".concat(ADJACENT_POST_CANDIDATES, "\nvar BLOG_ARRANGED_ORDER = ").concat(arranged, "\n\nfunction blogAdjacentPostsSql(comparison, direction) {\n return (\n 'SELECT p.* FROM ").concat(postsTable, " p,' +\n ' (SELECT created_at, id FROM ").concat(postsTable, " WHERE id = $1) cur' +\n \" WHERE p.status = 'published' AND (p.created_at, p.id) \" + comparison + ' (cur.created_at, cur.id)' +\n ' ORDER BY p.created_at ' + direction + ', p.id ' + direction +\n ' LIMIT ' + BLOG_ADJACENT_CANDIDATES\n )\n}\n\nfunction firstLinkableBlogPost(result) {\n var rows = result && Array.isArray(result.rows) ? result.rows : []\n for (var i = 0; i < rows.length; i++) {\n var row = rows[i]\n if (!row) continue\n var redirect = pickFirst(row.redirect_url, row.redirectUrl)\n if (typeof redirect === 'string' && redirect.trim() !== '') continue\n // Through JSON, like the rows the fetcher itself hands the transform.\n return JSON.parse(JSON.stringify(row))\n }\n return null\n}\n\nfunction blogPlaceOf(row) {\n var raw = pickFirst(row.sort_order, row.sortOrder)\n if (raw === null || raw === undefined || raw === '') return null\n var value = Number(raw)\n return isFinite(value) ? value : null\n}\n\n// The arranged posts by their place, then the rest newest first, ties by id descending.\nfunction compareBlogPlaces(a, b) {\n var placeA = blogPlaceOf(a)\n var placeB = blogPlaceOf(b)\n if (placeA !== placeB) {\n if (placeA === null) return 1\n if (placeB === null) return -1\n return placeA - placeB\n }\n var byDate =\n normalizeTimestamp(pickFirst(b.created_at, b.createdAt)) -\n normalizeTimestamp(pickFirst(a.created_at, a.createdAt))\n if (byDate !== 0) return byDate\n var idA = String(a.id)\n var idB = String(b.id)\n return idA < idB ? 1 : idA > idB ? -1 : 0\n}\n\n// { previous, next } along the post's primary category in Manual Order, or\n// null when the post has none (the caller then walks the newest-first order).\nasync function getArrangedAdjacentPosts(client, record) {\n var primary = parseJsonArray(record.category_ids)[0]\n if (!primary) return null\n var postId = String(record.id)\n var listed = await client.query(\n \"SELECT id, category_ids, sort_order, created_at FROM ").concat(postsTable, " WHERE status = 'published' OR id = $1\",\n [postId]\n )\n var chain = (listed && Array.isArray(listed.rows) ? listed.rows : [])\n .filter(function (row) {\n return String(row.id) === postId || parseJsonArray(row.category_ids)[0] === primary\n })\n .sort(compareBlogPlaces)\n var at = -1\n for (var i = 0; i < chain.length; i++) {\n if (String(chain[i].id) === postId) at = i\n }\n if (at < 0) return null\n var above = chain.slice(Math.max(0, at - BLOG_ADJACENT_CANDIDATES), at).reverse()\n var below = chain.slice(at + 1, at + 1 + BLOG_ADJACENT_CANDIDATES)\n var ids = above.concat(below).map(function (row) { return String(row.id) })\n if (ids.length === 0) return { previous: null, next: null }\n var full = await client.query(\n 'SELECT p.* FROM ").concat(postsTable, " p WHERE p.id::text = ANY($1::text[])',\n [ids]\n )\n var byId = {}\n ;(full && Array.isArray(full.rows) ? full.rows : []).forEach(function (row) {\n byId[String(row.id)] = row\n })\n var rowsOf = function (entries) {\n return { rows: entries.map(function (row) { return byId[String(row.id)] }) }\n }\n return { previous: firstLinkableBlogPost(rowsOf(above)), next: firstLinkableBlogPost(rowsOf(below)) }\n}\n\n// { [postId]: { previous, next } } \u2014 raw rows or null \u2014 for a single-record\n// fetch; {} otherwise and on any failure (the navigation then hides).\nasync function getAdjacentPostsMap(getClientFn, records) {\n var map = {}\n if (!Array.isArray(records) || records.length !== 1) return map\n var postId = records[0] && records[0].id\n if (postId === null || postId === undefined) return map\n\n var client\n try {\n client = getClientFn()\n await client.connect()\n var arranged = null\n if (BLOG_ARRANGED_ORDER) {\n try {\n arranged = await getArrangedAdjacentPosts(client, records[0])\n } catch (e) {\n // A table without the columns: the newest-first order below.\n }\n }\n if (arranged) {\n map[String(postId)] = arranged\n return map\n }\n var older = await client.query(blogAdjacentPostsSql('<', 'DESC'), [String(postId)])\n var newer = await client.query(blogAdjacentPostsSql('>', 'ASC'), [String(postId)])\n map[String(postId)] = {\n previous: firstLinkableBlogPost(older),\n next: firstLinkableBlogPost(newer),\n }\n } catch (e) {\n // Leaves the navigation hidden.\n } finally {\n if (client) {\n try { await client.end() } catch (e) { /* ignore */ }\n }\n }\n return map\n}\n");
33
+ };
21
34
  //# sourceMappingURL=blog-adjacent-posts.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blog-adjacent-posts.js","sourceRoot":"","sources":["../../../src/transformations/blog-adjacent-posts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,IAAM,wBAAwB,GAAG,CAAC,CAAA;AAElC;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,IAAM,yBAAyB,GAAG,cAAc,OAAA,2CACtB,wBAAwB,g2DAoDxD,EArDsD,CAqDtD,CAAA"}
1
+ {"version":3,"file":"blog-adjacent-posts.js","sourceRoot":"","sources":["../../../src/transformations/blog-adjacent-posts.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,IAAM,wBAAwB,GAAG,CAAC,CAAA;AAElC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,CAAC,IAAM,yBAAyB,GAAG,UAAC,UAAkB,EAAE,QAAgB;IAAhB,yBAAA,EAAA,gBAAgB;IAAa,OAAA,2CAC1D,wBAAwB,yCAC7B,QAAQ,0GAIb,UAAU,uDACG,UAAU,u9DAoDc,UAAU,8xBAkB/C,UAAU,ssDAoDhC;AAjI0F,CAiI1F,CAAA"}
@@ -26,5 +26,5 @@ export declare const BLOG_COMMENTS_RENDER_LIMIT = 200;
26
26
  * MUST mirror `buildBlogComments` in teleport-gui
27
27
  * `packages/renderer/src/utils/blog-comments.ts` (the canvas).
28
28
  */
29
- export declare const generateBlogCommentsCode: () => string;
29
+ export declare const generateBlogCommentsCode: (commentsTable: string) => string;
30
30
  //# sourceMappingURL=blog-comments.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"blog-comments.d.ts","sourceRoot":"","sources":["../../../src/transformations/blog-comments.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAA;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,QAAO,MAsG3C,CAAA"}
1
+ {"version":3,"file":"blog-comments.d.ts","sourceRoot":"","sources":["../../../src/transformations/blog-comments.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,eAAO,MAAM,0BAA0B,MAAM,CAAA;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,eAAO,MAAM,wBAAwB,kBAAmB,MAAM,KAAG,MAsGhE,CAAA"}
@@ -26,5 +26,5 @@ export var BLOG_COMMENTS_RENDER_LIMIT = 200;
26
26
  * MUST mirror `buildBlogComments` in teleport-gui
27
27
  * `packages/renderer/src/utils/blog-comments.ts` (the canvas).
28
28
  */
29
- export var generateBlogCommentsCode = function () { return "\nvar BLOG_COMMENTS_RENDER_LIMIT = ".concat(BLOG_COMMENTS_RENDER_LIMIT, "\n\nvar BLOG_COMMENTS_SQL =\n 'WITH top AS (' +\n ' SELECT id FROM teleport_blog_comments' +\n \" WHERE post_id = $1 AND parent_id IS NULL AND status = 'approved'\" +\n ' ORDER BY created_at DESC, id DESC LIMIT ' + BLOG_COMMENTS_RENDER_LIMIT +\n ')' +\n ' SELECT c.id, c.parent_id, c.author_name, c.content, c.is_author_reply, c.created_at' +\n ' FROM teleport_blog_comments c' +\n \" WHERE c.post_id = $1 AND c.status = 'approved'\" +\n ' AND (c.id IN (SELECT id FROM top) OR c.parent_id IN (SELECT id FROM top))' +\n ' ORDER BY c.created_at ASC, c.id ASC'\n\n// Every approved comment the page could show \u2014 a reply counts only while the\n// comment it answers is approved too.\nvar BLOG_COMMENTS_COUNT_SQL =\n 'SELECT COUNT(*) AS n FROM teleport_blog_comments c' +\n \" WHERE c.post_id = $1 AND c.status = 'approved'\" +\n ' AND (c.parent_id IS NULL OR EXISTS (' +\n ' SELECT 1 FROM teleport_blog_comments p' +\n \" WHERE p.id = c.parent_id AND p.status = 'approved'))\"\n\nfunction blogAuthorInitials(name) {\n if (typeof name !== 'string') return ''\n var words = name.trim().split(' ').filter(function(word) { return word !== '' })\n if (words.length === 0) return ''\n // Code points, not UTF-16 units: an initial may be an emoji or a letter\n // outside the BMP, and half of a surrogate pair renders as a box.\n var first = Array.from(words[0])[0] || ''\n var last = words.length > 1 ? Array.from(words[words.length - 1])[0] || '' : ''\n return (first + last).toUpperCase()\n}\n\nfunction buildBlogComment(row) {\n var name = typeof row.author_name === 'string' ? row.author_name.trim() : ''\n var authorName = name || 'Reader'\n return {\n id: String(row.id),\n authorName: authorName,\n authorInitials: blogAuthorInitials(authorName),\n content: typeof row.content === 'string' ? row.content : '',\n createdAt: normalizeTimestamp(row.created_at),\n isAuthorReply: coerceBoolean(row.is_author_reply, false),\n }\n}\n\nfunction isTopLevelComment(row) {\n return row.parent_id === null || row.parent_id === undefined || row.parent_id === ''\n}\n\nfunction buildBlogComments(rows) {\n var comments = []\n if (!Array.isArray(rows)) return comments\n var byId = {}\n for (var i = 0; i < rows.length; i++) {\n var row = rows[i]\n if (!row || row.id == null || !isTopLevelComment(row)) continue\n var comment = buildBlogComment(row)\n comment.replies = []\n byId[comment.id] = comment\n comments.push(comment)\n }\n for (var j = 0; j < rows.length; j++) {\n var reply = rows[j]\n if (!reply || reply.id == null || isTopLevelComment(reply)) continue\n var parent = byId[String(reply.parent_id)]\n if (parent) parent.replies.push(buildBlogComment(reply))\n }\n return comments\n}\n\n// { [postId]: { rows, count } } for a single-record (details) fetch; {} for\n// anything else, and on any failure \u2014 a blog whose comments table does not\n// exist yet renders its posts without comments rather than failing the page.\nasync function getBlogCommentsMap(getClientFn, records) {\n var map = {}\n if (!Array.isArray(records) || records.length !== 1) return map\n var postId = records[0] && records[0].id\n if (postId === null || postId === undefined) return map\n\n var client\n try {\n client = getClientFn()\n await client.connect()\n var listed = await client.query(BLOG_COMMENTS_SQL, [String(postId)])\n var counted = await client.query(BLOG_COMMENTS_COUNT_SQL, [String(postId)])\n // Through JSON, like every other row the fetcher hands the transform: the\n // driver returns timestamps as Date objects.\n var rows = listed && Array.isArray(listed.rows) ? JSON.parse(JSON.stringify(listed.rows)) : []\n var count = counted && counted.rows && counted.rows[0] ? Number(counted.rows[0].n) : NaN\n map[String(postId)] = { rows: rows, count: isNaN(count) ? rows.length : count }\n } catch (e) {\n // Leaves the post without comments.\n } finally {\n if (client) {\n try { await client.end() } catch (e) { /* ignore */ }\n }\n }\n return map\n}\n"); };
29
+ export var generateBlogCommentsCode = function (commentsTable) { return "\nvar BLOG_COMMENTS_RENDER_LIMIT = ".concat(BLOG_COMMENTS_RENDER_LIMIT, "\n\nvar BLOG_COMMENTS_SQL =\n 'WITH top AS (' +\n ' SELECT id FROM ").concat(commentsTable, "' +\n \" WHERE post_id = $1 AND parent_id IS NULL AND status = 'approved'\" +\n ' ORDER BY created_at DESC, id DESC LIMIT ' + BLOG_COMMENTS_RENDER_LIMIT +\n ')' +\n ' SELECT c.id, c.parent_id, c.author_name, c.content, c.is_author_reply, c.created_at' +\n ' FROM ").concat(commentsTable, " c' +\n \" WHERE c.post_id = $1 AND c.status = 'approved'\" +\n ' AND (c.id IN (SELECT id FROM top) OR c.parent_id IN (SELECT id FROM top))' +\n ' ORDER BY c.created_at ASC, c.id ASC'\n\n// Every approved comment the page could show \u2014 a reply counts only while the\n// comment it answers is approved too.\nvar BLOG_COMMENTS_COUNT_SQL =\n 'SELECT COUNT(*) AS n FROM ").concat(commentsTable, " c' +\n \" WHERE c.post_id = $1 AND c.status = 'approved'\" +\n ' AND (c.parent_id IS NULL OR EXISTS (' +\n ' SELECT 1 FROM ").concat(commentsTable, " p' +\n \" WHERE p.id = c.parent_id AND p.status = 'approved'))\"\n\nfunction blogAuthorInitials(name) {\n if (typeof name !== 'string') return ''\n var words = name.trim().split(' ').filter(function(word) { return word !== '' })\n if (words.length === 0) return ''\n // Code points, not UTF-16 units: an initial may be an emoji or a letter\n // outside the BMP, and half of a surrogate pair renders as a box.\n var first = Array.from(words[0])[0] || ''\n var last = words.length > 1 ? Array.from(words[words.length - 1])[0] || '' : ''\n return (first + last).toUpperCase()\n}\n\nfunction buildBlogComment(row) {\n var name = typeof row.author_name === 'string' ? row.author_name.trim() : ''\n var authorName = name || 'Reader'\n return {\n id: String(row.id),\n authorName: authorName,\n authorInitials: blogAuthorInitials(authorName),\n content: typeof row.content === 'string' ? row.content : '',\n createdAt: normalizeTimestamp(row.created_at),\n isAuthorReply: coerceBoolean(row.is_author_reply, false),\n }\n}\n\nfunction isTopLevelComment(row) {\n return row.parent_id === null || row.parent_id === undefined || row.parent_id === ''\n}\n\nfunction buildBlogComments(rows) {\n var comments = []\n if (!Array.isArray(rows)) return comments\n var byId = {}\n for (var i = 0; i < rows.length; i++) {\n var row = rows[i]\n if (!row || row.id == null || !isTopLevelComment(row)) continue\n var comment = buildBlogComment(row)\n comment.replies = []\n byId[comment.id] = comment\n comments.push(comment)\n }\n for (var j = 0; j < rows.length; j++) {\n var reply = rows[j]\n if (!reply || reply.id == null || isTopLevelComment(reply)) continue\n var parent = byId[String(reply.parent_id)]\n if (parent) parent.replies.push(buildBlogComment(reply))\n }\n return comments\n}\n\n// { [postId]: { rows, count } } for a single-record (details) fetch; {} for\n// anything else, and on any failure \u2014 a blog whose comments table does not\n// exist yet renders its posts without comments rather than failing the page.\nasync function getBlogCommentsMap(getClientFn, records) {\n var map = {}\n if (!Array.isArray(records) || records.length !== 1) return map\n var postId = records[0] && records[0].id\n if (postId === null || postId === undefined) return map\n\n var client\n try {\n client = getClientFn()\n await client.connect()\n var listed = await client.query(BLOG_COMMENTS_SQL, [String(postId)])\n var counted = await client.query(BLOG_COMMENTS_COUNT_SQL, [String(postId)])\n // Through JSON, like every other row the fetcher hands the transform: the\n // driver returns timestamps as Date objects.\n var rows = listed && Array.isArray(listed.rows) ? JSON.parse(JSON.stringify(listed.rows)) : []\n var count = counted && counted.rows && counted.rows[0] ? Number(counted.rows[0].n) : NaN\n map[String(postId)] = { rows: rows, count: isNaN(count) ? rows.length : count }\n } catch (e) {\n // Leaves the post without comments.\n } finally {\n if (client) {\n try { await client.end() } catch (e) { /* ignore */ }\n }\n }\n return map\n}\n"); };
30
30
  //# sourceMappingURL=blog-comments.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"blog-comments.js","sourceRoot":"","sources":["../../../src/transformations/blog-comments.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,IAAM,0BAA0B,GAAG,GAAG,CAAA;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,IAAM,wBAAwB,GAAG,cAAc,OAAA,6CACnB,0BAA0B,y/HAqG5D,EAtGqD,CAsGrD,CAAA"}
1
+ {"version":3,"file":"blog-comments.js","sourceRoot":"","sources":["../../../src/transformations/blog-comments.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,MAAM,CAAC,IAAM,0BAA0B,GAAG,GAAG,CAAA;AAE7C;;;;;;;;;;;;;;;;;;GAkBG;AACH,MAAM,CAAC,IAAM,wBAAwB,GAAG,UAAC,aAAqB,IAAa,OAAA,6CACxC,0BAA0B,kFAIxC,aAAa,yRAKvB,aAAa,mYAQO,aAAa,4IAGxB,aAAa,2lGAiFhC,EAtG0E,CAsG1E,CAAA"}
@@ -1,10 +1,24 @@
1
1
  import type { UIDLEcommerceCategory } from '@teleporthq/teleport-types';
2
+ import { ContentTables } from '@teleporthq/teleport-shared';
2
3
  /** What the blog-post transform bakes in at export time beyond the row itself. */
3
4
  export interface BlogPostTransformOptions {
5
+ /**
6
+ * The preset's tables (the Blog's by default): the posts table the related
7
+ * and adjacent posts are read from, the comments table a post page counts.
8
+ */
9
+ tables?: ContentTables.ContentTables;
4
10
  /** Category taxonomy — lives only in the UIDL, there is no DB table for it. */
5
11
  categories?: UIDLEcommerceCategory[];
6
12
  /** Content headings get ids and `#` links — see `heading-anchors.ts`. */
7
13
  headingAnchors?: boolean;
14
+ /**
15
+ * The post pages carry a Contents list: the content's headings get their ids
16
+ * (the `#` links only with `headingAnchors`) and a post page's post its
17
+ * `sections` — see `blogContentsSectionsOf`.
18
+ */
19
+ contents?: boolean;
20
+ /** Manual Order: Previous / Next walk the post's category as arranged — see `blog-adjacent-posts.ts`. */
21
+ arranged?: boolean;
8
22
  }
9
23
  /**
10
24
  * Generates JavaScript code for blog post data transformation.