@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.
- package/__tests__/_helpers/pagination-widget-fixture.ts +95 -5
- package/__tests__/blog-adjacent-arranged.test.ts +176 -0
- package/__tests__/blog-post-contents.test.ts +212 -0
- package/__tests__/blog-post-page-enrichment.test.ts +28 -5
- package/__tests__/blog-post-picture-stand-in.test.ts +48 -0
- package/__tests__/blog-post-reading-time.test.ts +55 -0
- package/__tests__/booking-item-transform.test.ts +120 -0
- package/__tests__/browser-row-policy.test.ts +13 -3
- package/__tests__/content-preset-wiring.test.ts +108 -0
- package/__tests__/fetchers.test.ts +1 -1
- package/__tests__/fixed-list-sort.test.ts +183 -0
- package/__tests__/infinite-scroll.test.ts +154 -5
- package/__tests__/list-sort-order.test.ts +61 -0
- package/__tests__/null-filter-where.test.ts +132 -0
- package/__tests__/pagination-filter-groups.test.ts +186 -0
- package/__tests__/pg-date-parser.test.ts +73 -0
- package/__tests__/plain-list-sort.test.ts +215 -0
- package/__tests__/product-price-sort.ts +58 -25
- package/__tests__/range-control.test.ts +159 -0
- package/__tests__/rest-api-key-header.test.ts +18 -0
- package/__tests__/search-input-marker.test.ts +86 -0
- package/__tests__/search-url-sync.test.ts +61 -16
- package/__tests__/shared-resource-prefetch.test.ts +65 -0
- package/__tests__/table-read-route-protected-tables.test.ts +33 -3
- package/dist/cjs/count-effect.d.ts +7 -1
- package/dist/cjs/count-effect.d.ts.map +1 -1
- package/dist/cjs/count-effect.js +15 -5
- package/dist/cjs/count-effect.js.map +1 -1
- package/dist/cjs/fetchers/pg-client-import.d.ts +12 -0
- package/dist/cjs/fetchers/pg-client-import.d.ts.map +1 -0
- package/dist/cjs/fetchers/pg-client-import.js +15 -0
- package/dist/cjs/fetchers/pg-client-import.js.map +1 -0
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +4 -1
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/raw-query.d.ts.map +1 -1
- package/dist/cjs/fetchers/raw-query.js +2 -1
- package/dist/cjs/fetchers/raw-query.js.map +1 -1
- package/dist/cjs/fetchers/rest-api.d.ts.map +1 -1
- package/dist/cjs/fetchers/rest-api.js +3 -1
- package/dist/cjs/fetchers/rest-api.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
- package/dist/cjs/fetchers/teleport.js +5 -2
- package/dist/cjs/fetchers/teleport.js.map +1 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.d.ts +7 -6
- package/dist/cjs/fetchers/utils/browser-row-policy.d.ts.map +1 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.js +7 -33
- package/dist/cjs/fetchers/utils/browser-row-policy.js.map +1 -1
- package/dist/cjs/filter-utils.d.ts +19 -7
- package/dist/cjs/filter-utils.d.ts.map +1 -1
- package/dist/cjs/filter-utils.js +49 -13
- package/dist/cjs/filter-utils.js.map +1 -1
- package/dist/cjs/infinite-scroll.d.ts +25 -2
- package/dist/cjs/infinite-scroll.d.ts.map +1 -1
- package/dist/cjs/infinite-scroll.js +144 -33
- package/dist/cjs/infinite-scroll.js.map +1 -1
- package/dist/cjs/list-sort-order.d.ts +14 -0
- package/dist/cjs/list-sort-order.d.ts.map +1 -0
- package/dist/cjs/list-sort-order.js +36 -0
- package/dist/cjs/list-sort-order.js.map +1 -0
- package/dist/cjs/pagination-controls.d.ts +22 -3
- package/dist/cjs/pagination-controls.d.ts.map +1 -1
- package/dist/cjs/pagination-controls.js +29 -3
- package/dist/cjs/pagination-controls.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +267 -212
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/product-price-sort.d.ts +0 -9
- package/dist/cjs/product-price-sort.d.ts.map +1 -1
- package/dist/cjs/product-price-sort.js +1 -13
- package/dist/cjs/product-price-sort.js.map +1 -1
- package/dist/cjs/range-control.d.ts +45 -0
- package/dist/cjs/range-control.d.ts.map +1 -0
- package/dist/cjs/range-control.js +165 -0
- package/dist/cjs/range-control.js.map +1 -0
- package/dist/cjs/row-order.d.ts +20 -0
- package/dist/cjs/row-order.d.ts.map +1 -0
- package/dist/cjs/row-order.js +46 -0
- package/dist/cjs/row-order.js.map +1 -0
- package/dist/cjs/search-input.d.ts +42 -0
- package/dist/cjs/search-input.d.ts.map +1 -0
- package/dist/cjs/search-input.js +158 -0
- package/dist/cjs/search-input.js.map +1 -0
- package/dist/cjs/sort-utils.d.ts +10 -0
- package/dist/cjs/sort-utils.d.ts.map +1 -1
- package/dist/cjs/sort-utils.js +22 -1
- package/dist/cjs/sort-utils.js.map +1 -1
- package/dist/cjs/transformations/blog-adjacent-posts.d.ts +11 -1
- package/dist/cjs/transformations/blog-adjacent-posts.d.ts.map +1 -1
- package/dist/cjs/transformations/blog-adjacent-posts.js +14 -1
- package/dist/cjs/transformations/blog-adjacent-posts.js.map +1 -1
- package/dist/cjs/transformations/blog-comments.d.ts +1 -1
- package/dist/cjs/transformations/blog-comments.d.ts.map +1 -1
- package/dist/cjs/transformations/blog-comments.js +1 -1
- package/dist/cjs/transformations/blog-comments.js.map +1 -1
- package/dist/cjs/transformations/blog-post.d.ts +14 -0
- package/dist/cjs/transformations/blog-post.d.ts.map +1 -1
- package/dist/cjs/transformations/blog-post.js +4 -1
- package/dist/cjs/transformations/blog-post.js.map +1 -1
- package/dist/cjs/transformations/booking-item.d.ts +24 -0
- package/dist/cjs/transformations/booking-item.d.ts.map +1 -0
- package/dist/cjs/transformations/booking-item.js +27 -0
- package/dist/cjs/transformations/booking-item.js.map +1 -0
- package/dist/cjs/transformations/heading-anchors.d.ts +32 -8
- package/dist/cjs/transformations/heading-anchors.d.ts.map +1 -1
- package/dist/cjs/transformations/heading-anchors.js +34 -10
- package/dist/cjs/transformations/heading-anchors.js.map +1 -1
- package/dist/cjs/transformations/index.d.ts +27 -13
- package/dist/cjs/transformations/index.d.ts.map +1 -1
- package/dist/cjs/transformations/index.js +73 -16
- package/dist/cjs/transformations/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +52 -3
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/count-effect.d.ts +7 -1
- package/dist/esm/count-effect.d.ts.map +1 -1
- package/dist/esm/count-effect.js +15 -5
- package/dist/esm/count-effect.js.map +1 -1
- package/dist/esm/fetchers/pg-client-import.d.ts +12 -0
- package/dist/esm/fetchers/pg-client-import.d.ts.map +1 -0
- package/dist/esm/fetchers/pg-client-import.js +12 -0
- package/dist/esm/fetchers/pg-client-import.js.map +1 -0
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +5 -2
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/raw-query.d.ts.map +1 -1
- package/dist/esm/fetchers/raw-query.js +2 -1
- package/dist/esm/fetchers/raw-query.js.map +1 -1
- package/dist/esm/fetchers/rest-api.d.ts.map +1 -1
- package/dist/esm/fetchers/rest-api.js +3 -1
- package/dist/esm/fetchers/rest-api.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts.map +1 -1
- package/dist/esm/fetchers/teleport.js +6 -3
- package/dist/esm/fetchers/teleport.js.map +1 -1
- package/dist/esm/fetchers/utils/browser-row-policy.d.ts +7 -6
- package/dist/esm/fetchers/utils/browser-row-policy.d.ts.map +1 -1
- package/dist/esm/fetchers/utils/browser-row-policy.js +5 -31
- package/dist/esm/fetchers/utils/browser-row-policy.js.map +1 -1
- package/dist/esm/filter-utils.d.ts +19 -7
- package/dist/esm/filter-utils.d.ts.map +1 -1
- package/dist/esm/filter-utils.js +46 -12
- package/dist/esm/filter-utils.js.map +1 -1
- package/dist/esm/infinite-scroll.d.ts +25 -2
- package/dist/esm/infinite-scroll.d.ts.map +1 -1
- package/dist/esm/infinite-scroll.js +142 -32
- package/dist/esm/infinite-scroll.js.map +1 -1
- package/dist/esm/list-sort-order.d.ts +14 -0
- package/dist/esm/list-sort-order.d.ts.map +1 -0
- package/dist/esm/list-sort-order.js +32 -0
- package/dist/esm/list-sort-order.js.map +1 -0
- package/dist/esm/pagination-controls.d.ts +22 -3
- package/dist/esm/pagination-controls.d.ts.map +1 -1
- package/dist/esm/pagination-controls.js +28 -2
- package/dist/esm/pagination-controls.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +271 -216
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/product-price-sort.d.ts +0 -9
- package/dist/esm/product-price-sort.d.ts.map +1 -1
- package/dist/esm/product-price-sort.js +0 -11
- package/dist/esm/product-price-sort.js.map +1 -1
- package/dist/esm/range-control.d.ts +45 -0
- package/dist/esm/range-control.d.ts.map +1 -0
- package/dist/esm/range-control.js +137 -0
- package/dist/esm/range-control.js.map +1 -0
- package/dist/esm/row-order.d.ts +20 -0
- package/dist/esm/row-order.d.ts.map +1 -0
- package/dist/esm/row-order.js +41 -0
- package/dist/esm/row-order.js.map +1 -0
- package/dist/esm/search-input.d.ts +42 -0
- package/dist/esm/search-input.d.ts.map +1 -0
- package/dist/esm/search-input.js +129 -0
- package/dist/esm/search-input.js.map +1 -0
- package/dist/esm/sort-utils.d.ts +10 -0
- package/dist/esm/sort-utils.d.ts.map +1 -1
- package/dist/esm/sort-utils.js +20 -0
- package/dist/esm/sort-utils.js.map +1 -1
- package/dist/esm/transformations/blog-adjacent-posts.d.ts +11 -1
- package/dist/esm/transformations/blog-adjacent-posts.d.ts.map +1 -1
- package/dist/esm/transformations/blog-adjacent-posts.js +14 -1
- package/dist/esm/transformations/blog-adjacent-posts.js.map +1 -1
- package/dist/esm/transformations/blog-comments.d.ts +1 -1
- package/dist/esm/transformations/blog-comments.d.ts.map +1 -1
- package/dist/esm/transformations/blog-comments.js +1 -1
- package/dist/esm/transformations/blog-comments.js.map +1 -1
- package/dist/esm/transformations/blog-post.d.ts +14 -0
- package/dist/esm/transformations/blog-post.d.ts.map +1 -1
- package/dist/esm/transformations/blog-post.js +4 -1
- package/dist/esm/transformations/blog-post.js.map +1 -1
- package/dist/esm/transformations/booking-item.d.ts +24 -0
- package/dist/esm/transformations/booking-item.d.ts.map +1 -0
- package/dist/esm/transformations/booking-item.js +23 -0
- package/dist/esm/transformations/booking-item.js.map +1 -0
- package/dist/esm/transformations/heading-anchors.d.ts +32 -8
- package/dist/esm/transformations/heading-anchors.d.ts.map +1 -1
- package/dist/esm/transformations/heading-anchors.js +33 -9
- package/dist/esm/transformations/heading-anchors.js.map +1 -1
- package/dist/esm/transformations/index.d.ts +27 -13
- package/dist/esm/transformations/index.d.ts.map +1 -1
- package/dist/esm/transformations/index.js +72 -16
- package/dist/esm/transformations/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +52 -3
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/count-effect.ts +31 -8
- package/src/fetchers/pg-client-import.ts +16 -0
- package/src/fetchers/postgresql.ts +25 -23
- package/src/fetchers/raw-query.ts +2 -1
- package/src/fetchers/rest-api.ts +3 -1
- package/src/fetchers/teleport.ts +22 -23
- package/src/fetchers/utils/browser-row-policy.ts +10 -20
- package/src/filter-utils.ts +102 -28
- package/src/infinite-scroll.ts +240 -79
- package/src/list-sort-order.ts +34 -0
- package/src/pagination-controls.ts +26 -3
- package/src/pagination-plugin.ts +370 -306
- package/src/product-price-sort.ts +0 -11
- package/src/range-control.ts +207 -0
- package/src/row-order.ts +55 -0
- package/src/search-input.ts +190 -0
- package/src/sort-utils.ts +25 -0
- package/src/transformations/blog-adjacent-posts.ts +89 -3
- package/src/transformations/blog-comments.ts +5 -5
- package/src/transformations/blog-post.ts +64 -13
- package/src/transformations/booking-item.ts +71 -0
- package/src/transformations/heading-anchors.ts +79 -16
- package/src/transformations/index.ts +104 -14
- package/src/utils.ts +74 -3
|
@@ -4,12 +4,15 @@ exports.generateTeleportCountFetcher = exports.generateTeleportFetcher = exports
|
|
|
4
4
|
var utils_1 = require("../utils");
|
|
5
5
|
var transformations_1 = require("../transformations");
|
|
6
6
|
var product_price_sort_1 = require("../product-price-sort");
|
|
7
|
+
var list_sort_order_1 = require("../list-sort-order");
|
|
8
|
+
var row_order_1 = require("../row-order");
|
|
7
9
|
var product_filter_fields_1 = require("../product-filter-fields");
|
|
8
10
|
var localized_columns_1 = require("../localized-columns");
|
|
9
11
|
var request_locale_1 = require("../request-locale");
|
|
10
12
|
var table_access_guard_1 = require("./utils/table-access-guard");
|
|
11
13
|
var request_sql_guards_1 = require("./utils/request-sql-guards");
|
|
12
14
|
var array_overlap_sql_1 = require("../array-overlap-sql");
|
|
15
|
+
var pg_client_import_1 = require("./pg-client-import");
|
|
13
16
|
var DEFAULT_ENV_KEYS = {
|
|
14
17
|
host: 'TELEPORT_DB_HOST',
|
|
15
18
|
port: 'TELEPORT_DB_PORT',
|
|
@@ -56,9 +59,9 @@ var generateTeleportFetcher = function (config, tableName, transformOptions) {
|
|
|
56
59
|
? "key: ".concat(resolveEnvReference(dbConfig.sslConfig.key, 'TELEPORT_DB_SSL_KEY'), ",")
|
|
57
60
|
: '', "\n rejectUnauthorized: false\n }")
|
|
58
61
|
: "(process.env.".concat(DEFAULT_ENV_KEYS.ssl, " === 'false' ? false : process.env.").concat(DEFAULT_ENV_KEYS.ssl, " === 'true' ? { rejectUnauthorized: false } : undefined)");
|
|
59
|
-
return "import { Client } from 'pg'\n\n".concat((0, table_access_guard_1.generateTableAccessPreamble)(transformOptions.trustedReaderRoles || []), "\nfunction normalizePostgresConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n if (/^postgresql:\\/(?!\\/)/i.test(connectionString)) {\n return connectionString.replace(/^postgresql:\\//i, 'postgresql://');\n }\n return connectionString;\n}\n\nfunction stripSslQueryParamsFromConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n try {\n var u = new URL(connectionString.replace(/^postgresql:/i, 'postgres:'));\n u.searchParams.delete('sslmode');\n u.searchParams.delete('ssl');\n u.searchParams.delete('sslrootcert');\n u.searchParams.delete('sslcert');\n u.searchParams.delete('sslkey');\n return u.toString().replace(/^postgres:/i, 'postgresql:');\n } catch (e) {\n return connectionString;\n }\n}\n\nconst getClient = () => {\n var ssl = ").concat(sslCode, ";\n var connStr = process.env.TELEPORT_DB_CONNECTION_STRING;\n if (connStr) {\n connStr = normalizePostgresConnectionString(connStr);\n }\n if (ssl === false && connStr) {\n connStr = stripSslQueryParamsFromConnectionString(connStr);\n }\n if (connStr) {\n return new Client(Object.assign(\n { connectionString: connStr },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n }\n return new Client(Object.assign(\n {\n host: ").concat(hostRef, ",\n port: parseInt(").concat(portRef, " || '5432', 10),\n user: ").concat(userRef, ",\n password: ").concat(passwordRef, ",\n database: ").concat(databaseRef, ",\n },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n}\n\n").concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\n").concat((0, utils_1.generateSearchEscapeHelpersCode)(), "\n").concat((0, array_overlap_sql_1.generateArrayOverlapSqlCode)(), "\n").concat((0, transformations_1.getTransformationCode)(tableName, transformOptions), "\n").concat((0, transformations_1.getTransformWrapperCode)(tableName, transformOptions), "\n").concat((0, request_sql_guards_1.generateRequestSqlGuardsCode)(), "\nconst processFilters = (filters, conditions, queryParams, paramIndex) => {\n if (!filters) return paramIndex\n \n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n if (!filterTree) return paramIndex\n \n const buildCondition = (condition) => {\n const field = condition.source\n const normalizedCondition = normalizeInOperand(condition.operand, condition.destination)\n if (normalizedCondition === null) return null\n const value = normalizedCondition.value\n const operand = normalizedCondition.operand\n \n // The products table's virtual fields (effective price, rating bucket,\n // on-sale flag, variant axes) are whole clauses, not columns - so they are\n // answered before any branch below can interpolate the field name raw.\n const productClause = productFilterClause(field, operand, value, (param) => {\n queryParams.push(param)\n return '$' + paramIndex++\n })\n if (productClause !== null) return productClause\n\n // A translatable column is compared against the value in every language,\n // so a localized slug resolves under any locale - see localized-columns.ts.\n const localizedClause = localizedEqualityClause(field, operand, value, (param) => {\n queryParams.push(param)\n return '$' + paramIndex++\n })\n if (localizedClause !== null) return localizedClause\n assertRequestColumn(field, 'filter field')\n \n if (Array.isArray(value)) {\n if (value.length === 0) return null\n if (operand === 'array_overlap') {\n // The row's list (see array-overlap-sql.ts) shares any value with the set.\n const clause = arrayOverlapSql((localizedColumnList(field) || [field]), '$' + paramIndex)\n queryParams.push(value.map((entry) => String(entry)))\n paramIndex++\n return clause\n }\n const placeholders = value.map(() => `$${paramIndex++}`)\n queryParams.push(...value)\n return operand === '!='\n ? `${field} NOT IN (${placeholders.join(', ')})`\n : `${field} IN (${placeholders.join(', ')})`\n }\n \n if (operand === 'array_overlap') {\n if (value === '' || value === null || value === undefined) return null\n // A single comma-joined string (the multi-select Category Filter's\n // ?categoryFilter=a,b,c) expands to multiple ids; one id stays one.\n const overlapValues = String(value).split(',').map((entry) => entry.trim()).filter(Boolean)\n if (overlapValues.length === 0) return null\n const clause = arrayOverlapSql((localizedColumnList(field) || [field]), '$' + paramIndex)\n queryParams.push(overlapValues)\n paramIndex++\n return clause\n }\n \n if (value === null) {\n if (operand === '=') return `${field} IS NULL`\n if (operand === '!=') return `${field} IS NOT NULL`\n return null\n }\n \n const validOps = ['=', '!=', '>', '<', '>=', '<=']\n const sqlOperator = validOps.includes(operand) ? operand : '='\n const clause = `${field} ${sqlOperator} $${paramIndex}`\n queryParams.push(value)\n paramIndex++\n return clause\n }\n \n const clause = buildFilterTreeClause(filterTree, buildCondition)\n if (clause) conditions.push(clause)\n \n return paramIndex\n}\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, product_price_sort_1.generateSortFieldSqlHelper)(tableName), "\n\n").concat((0, product_price_sort_1.generateSortFallbackFieldHelper)(tableName), "\n\n").concat((0, product_filter_fields_1.generateProductFilterClauseHelper)(tableName), "\n\n").concat((0, localized_columns_1.generateLocalizedColumnsHelper)(localizedColumns), "\n\n// Matches DDL / dangerous statements the raw-query branch should refuse.\n// Keep this list conservative \u2014 anything destructive or schema-changing is\n// out of scope for a client-triggered fetch. SELECT and CTEs (WITH ...) are\n// the only shapes consumers legitimately need.\nconst BLOCKED_RAW_QUERY_PATTERNS = [\n /\\bcreate\\s+(?:temporary\\s+|temp\\s+|unlogged\\s+|global\\s+|local\\s+)?table\\b/i,\n /\\bcreate\\s+(?:unique\\s+)?index\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:materialized\\s+)?view\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?trigger\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:aggregate\\s+)?function\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?procedure\\b/i,\n /\\bcreate\\s+(?:database|schema|sequence|extension|type|role|user)\\b/i,\n /\\bdrop\\s+(?:table|view|index|schema|database|sequence|trigger|function|procedure|role|user|extension|type|materialized)\\b/i,\n /\\balter\\s+(?:table|view|index|schema|database|sequence|role|user|system)\\b/i,\n /\\btruncate\\b/i,\n /\\bgrant\\b/i,\n /\\brevoke\\b/i,\n /\\binsert\\b/i,\n /\\bupdate\\b/i,\n /\\bdelete\\b/i,\n /\\bcopy\\b/i,\n /\\bvacuum\\b/i,\n /\\breindex\\b/i,\n /\\bcluster\\b/i,\n]\n\nfunction assertRawQuerySafe(rawQuery) {\n if (typeof rawQuery !== 'string' || rawQuery.length === 0) {\n throw new Error('rawQuery must be a non-empty string')\n }\n // Reject multi-statement payloads \u2014 only single SELECT / WITH statements.\n // A trailing semicolon is tolerated but any content after it fails.\n var trimmed = rawQuery.trim().replace(/;\\s*$/, '')\n if (trimmed.indexOf(';') !== -1) {\n throw new Error('rawQuery must contain exactly one statement')\n }\n for (var i = 0; i < BLOCKED_RAW_QUERY_PATTERNS.length; i++) {\n if (BLOCKED_RAW_QUERY_PATTERNS[i].test(trimmed)) {\n throw new Error('rawQuery contains a blocked statement')\n }\n }\n}\n\nexport default async function handler(req, res) {\n").concat((0, table_access_guard_1.generateReadGuardCall)(tableName, 'req.query && req.query.rawQuery'), "\n const client = getClient()\n\n try {\n await client.connect()\n ").concat(schema ? "await client.query('SET search_path TO ".concat(schema, "')") : '', "\n\n // If the caller supplied a rawQuery, run it verbatim (after a safety\n // guard). The schema-driven branch below builds `SELECT * FROM ").concat(tableName, "`\n // with optional filters \u2014 it's the default read path and ignores\n // rawQuery. Page-load workflows and other consumers that need a JOIN\n // or a user-scoped filter pass their fully-rendered SQL here via\n // `fetchData({ rawQuery })` and expect it to execute verbatim.\n if (req.query && typeof req.query.rawQuery === 'string' && req.query.rawQuery.length > 0) {\n assertRawQuerySafe(req.query.rawQuery)\n const rawResult = await client.query(req.query.rawQuery)\n const rawRows = Array.isArray(rawResult?.rows) ? rawResult.rows : []\n const rawPlain = rawRows.map((row) =>\n row && typeof row.toJSON === 'function' ? row.toJSON() : row\n )\n const rawSafe = JSON.parse(JSON.stringify(rawPlain, dateReplacer))\n return res.status(200).json({\n success: true,\n // Every row here ends up in a browser (a page's props or a client\n // refetch), so no credential column survives, whatever joined it.\n data: __taWithoutCredentials(rawSafe, null),\n timestamp: Date.now()\n })\n }\n\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n // A visitor never filters, sorts or searches by a column it is not served.\n if (__rowPolicy) __brpAssertVisibleFields(__rowPolicy, req.query)\n // The language the page is in - what a translatable sort orders by.\n const requestLocale = typeof req.query.").concat(request_locale_1.REQUEST_LOCALE_PARAM, " === 'string' ? req.query.").concat(request_locale_1.REQUEST_LOCALE_PARAM, " : null\n \n const conditions = []\n const queryParams = []\n let paramIndex = 1\n \n if (query) {\n let columns = []\n \n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n columns = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : [])\n } else {\n try {\n const schemaQuery = `\n SELECT column_name \n FROM information_schema.columns \n WHERE table_name = $1\n ").concat(schema ? "AND table_schema = $2" : '', "\n ORDER BY ordinal_position\n `\n const schemaParams = ").concat(schema
|
|
62
|
+
return "".concat(pg_client_import_1.PG_CLIENT_IMPORT, "\n\n").concat((0, table_access_guard_1.generateTableAccessPreamble)(transformOptions.trustedReaderRoles || []), "\nfunction normalizePostgresConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n if (/^postgresql:\\/(?!\\/)/i.test(connectionString)) {\n return connectionString.replace(/^postgresql:\\//i, 'postgresql://');\n }\n return connectionString;\n}\n\nfunction stripSslQueryParamsFromConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n try {\n var u = new URL(connectionString.replace(/^postgresql:/i, 'postgres:'));\n u.searchParams.delete('sslmode');\n u.searchParams.delete('ssl');\n u.searchParams.delete('sslrootcert');\n u.searchParams.delete('sslcert');\n u.searchParams.delete('sslkey');\n return u.toString().replace(/^postgres:/i, 'postgresql:');\n } catch (e) {\n return connectionString;\n }\n}\n\nconst getClient = () => {\n var ssl = ").concat(sslCode, ";\n var connStr = process.env.TELEPORT_DB_CONNECTION_STRING;\n if (connStr) {\n connStr = normalizePostgresConnectionString(connStr);\n }\n if (ssl === false && connStr) {\n connStr = stripSslQueryParamsFromConnectionString(connStr);\n }\n if (connStr) {\n return new Client(Object.assign(\n { connectionString: connStr },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n }\n return new Client(Object.assign(\n {\n host: ").concat(hostRef, ",\n port: parseInt(").concat(portRef, " || '5432', 10),\n user: ").concat(userRef, ",\n password: ").concat(passwordRef, ",\n database: ").concat(databaseRef, ",\n },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n}\n\n").concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\n").concat((0, utils_1.generateSearchEscapeHelpersCode)(), "\n").concat((0, array_overlap_sql_1.generateArrayOverlapSqlCode)(), "\n").concat((0, transformations_1.getTransformationCode)(tableName, transformOptions), "\n").concat((0, transformations_1.getTransformWrapperCode)(tableName, transformOptions), "\n").concat((0, request_sql_guards_1.generateRequestSqlGuardsCode)(), "\nconst processFilters = (filters, conditions, queryParams, paramIndex) => {\n if (!filters) return paramIndex\n \n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n if (!filterTree) return paramIndex\n \n const buildCondition = (condition) => {\n const field = condition.source\n const normalizedCondition = normalizeInOperand(condition.operand, condition.destination)\n if (normalizedCondition === null) return null\n const value = normalizedCondition.value\n const operand = normalizedCondition.operand\n \n // The products table's virtual fields (effective price, rating bucket,\n // on-sale flag, variant axes) are whole clauses, not columns - so they are\n // answered before any branch below can interpolate the field name raw.\n const productClause = productFilterClause(field, operand, value, (param) => {\n queryParams.push(param)\n return '$' + paramIndex++\n })\n if (productClause !== null) return productClause\n\n // A translatable column is compared against the value in every language,\n // so a localized slug resolves under any locale - see localized-columns.ts.\n const localizedClause = localizedEqualityClause(field, operand, value, (param) => {\n queryParams.push(param)\n return '$' + paramIndex++\n })\n if (localizedClause !== null) return localizedClause\n assertRequestColumn(field, 'filter field')\n \n if (Array.isArray(value)) {\n if (value.length === 0) return null\n if (operand === 'array_overlap') {\n // The row's list (see array-overlap-sql.ts) shares any value with the set.\n const clause = arrayOverlapSql((localizedColumnList(field) || [field]), '$' + paramIndex)\n queryParams.push(value.map((entry) => String(entry)))\n paramIndex++\n return clause\n }\n const placeholders = value.map(() => `$${paramIndex++}`)\n queryParams.push(...value)\n return operand === '!='\n ? `${field} NOT IN (${placeholders.join(', ')})`\n : `${field} IN (${placeholders.join(', ')})`\n }\n \n if (operand === 'array_overlap') {\n if (value === '' || value === null || value === undefined) return null\n // A single comma-joined string (the multi-select Category Filter's\n // ?categoryFilter=a,b,c) expands to multiple ids; one id stays one.\n const overlapValues = String(value).split(',').map((entry) => entry.trim()).filter(Boolean)\n if (overlapValues.length === 0) return null\n const clause = arrayOverlapSql((localizedColumnList(field) || [field]), '$' + paramIndex)\n queryParams.push(overlapValues)\n paramIndex++\n return clause\n }\n \n if (value === null) {\n if (operand === '=') return `${field} IS NULL`\n if (operand === '!=') return `${field} IS NOT NULL`\n return null\n }\n \n const validOps = ['=', '!=', '>', '<', '>=', '<=']\n const sqlOperator = validOps.includes(operand) ? operand : '='\n const clause = `${field} ${sqlOperator} $${paramIndex}`\n queryParams.push(value)\n paramIndex++\n return clause\n }\n \n const clause = buildFilterTreeClause(filterTree, buildCondition)\n if (clause) conditions.push(clause)\n \n return paramIndex\n}\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, product_price_sort_1.generateSortFieldSqlHelper)(tableName), "\n\n").concat((0, product_price_sort_1.generateSortFallbackFieldHelper)(tableName), "\n\n").concat((0, row_order_1.generateRowOrderTiebreakHelper)((0, row_order_1.rowIdentityColumn)(config, tableName)), "\n\n").concat((0, product_filter_fields_1.generateProductFilterClauseHelper)(tableName), "\n\n").concat((0, localized_columns_1.generateLocalizedColumnsHelper)(localizedColumns), "\n\n// Matches DDL / dangerous statements the raw-query branch should refuse.\n// Keep this list conservative \u2014 anything destructive or schema-changing is\n// out of scope for a client-triggered fetch. SELECT and CTEs (WITH ...) are\n// the only shapes consumers legitimately need.\nconst BLOCKED_RAW_QUERY_PATTERNS = [\n /\\bcreate\\s+(?:temporary\\s+|temp\\s+|unlogged\\s+|global\\s+|local\\s+)?table\\b/i,\n /\\bcreate\\s+(?:unique\\s+)?index\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:materialized\\s+)?view\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?trigger\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:aggregate\\s+)?function\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?procedure\\b/i,\n /\\bcreate\\s+(?:database|schema|sequence|extension|type|role|user)\\b/i,\n /\\bdrop\\s+(?:table|view|index|schema|database|sequence|trigger|function|procedure|role|user|extension|type|materialized)\\b/i,\n /\\balter\\s+(?:table|view|index|schema|database|sequence|role|user|system)\\b/i,\n /\\btruncate\\b/i,\n /\\bgrant\\b/i,\n /\\brevoke\\b/i,\n /\\binsert\\b/i,\n /\\bupdate\\b/i,\n /\\bdelete\\b/i,\n /\\bcopy\\b/i,\n /\\bvacuum\\b/i,\n /\\breindex\\b/i,\n /\\bcluster\\b/i,\n]\n\nfunction assertRawQuerySafe(rawQuery) {\n if (typeof rawQuery !== 'string' || rawQuery.length === 0) {\n throw new Error('rawQuery must be a non-empty string')\n }\n // Reject multi-statement payloads \u2014 only single SELECT / WITH statements.\n // A trailing semicolon is tolerated but any content after it fails.\n var trimmed = rawQuery.trim().replace(/;\\s*$/, '')\n if (trimmed.indexOf(';') !== -1) {\n throw new Error('rawQuery must contain exactly one statement')\n }\n for (var i = 0; i < BLOCKED_RAW_QUERY_PATTERNS.length; i++) {\n if (BLOCKED_RAW_QUERY_PATTERNS[i].test(trimmed)) {\n throw new Error('rawQuery contains a blocked statement')\n }\n }\n}\n\nexport default async function handler(req, res) {\n").concat((0, table_access_guard_1.generateReadGuardCall)(tableName, 'req.query && req.query.rawQuery'), "\n const client = getClient()\n\n try {\n await client.connect()\n ").concat(schema ? "await client.query('SET search_path TO ".concat(schema, "')") : '', "\n\n // If the caller supplied a rawQuery, run it verbatim (after a safety\n // guard). The schema-driven branch below builds `SELECT * FROM ").concat(tableName, "`\n // with optional filters \u2014 it's the default read path and ignores\n // rawQuery. Page-load workflows and other consumers that need a JOIN\n // or a user-scoped filter pass their fully-rendered SQL here via\n // `fetchData({ rawQuery })` and expect it to execute verbatim.\n if (req.query && typeof req.query.rawQuery === 'string' && req.query.rawQuery.length > 0) {\n assertRawQuerySafe(req.query.rawQuery)\n const rawResult = await client.query(req.query.rawQuery)\n const rawRows = Array.isArray(rawResult?.rows) ? rawResult.rows : []\n const rawPlain = rawRows.map((row) =>\n row && typeof row.toJSON === 'function' ? row.toJSON() : row\n )\n const rawSafe = JSON.parse(JSON.stringify(rawPlain, dateReplacer))\n return res.status(200).json({\n success: true,\n // Every row here ends up in a browser (a page's props or a client\n // refetch), so no credential column survives, whatever joined it.\n data: __taWithoutCredentials(rawSafe, null),\n timestamp: Date.now()\n })\n }\n\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n // A visitor never filters, sorts or searches by a column it is not served.\n if (__rowPolicy) __brpAssertVisibleFields(__rowPolicy, req.query)\n // The language the page is in - what a translatable sort orders by.\n const requestLocale = typeof req.query.").concat(request_locale_1.REQUEST_LOCALE_PARAM, " === 'string' ? req.query.").concat(request_locale_1.REQUEST_LOCALE_PARAM, " : null\n \n const conditions = []\n const queryParams = []\n let paramIndex = 1\n \n if (query) {\n let columns = []\n \n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n columns = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : [])\n } else {\n try {\n const schemaQuery = `\n SELECT column_name \n FROM information_schema.columns \n WHERE table_name = $1\n ").concat(schema ? "AND table_schema = $2" : '', "\n ORDER BY ordinal_position\n `\n const schemaParams = ").concat(schema
|
|
60
63
|
? "[".concat(JSON.stringify(tableName), ", ").concat(JSON.stringify(schema), "]")
|
|
61
|
-
: "[".concat(JSON.stringify(tableName), "]"), "\n \n const schemaResult = await client.query(schemaQuery, schemaParams)\n columns = schemaResult.rows.map(row => row.column_name)\n } catch (schemaError) {\n console.warn('Failed to fetch column names from information_schema:', schemaError.message)\n }\n }\n if (__rowPolicy) columns = __brpVisibleColumns(__rowPolicy, columns)\n \n if (columns.length > 0) {\n const pattern = '%' + escapeLikePattern(query) + '%'\n const placeholder = '$' + paramIndex\n paramIndex++\n queryParams.push(pattern)\n const searchConditions = columns.map(\n (col) => '\"' + sanitizeSearchIdentifier(col) + '\"::text ILIKE ' + placeholder + \" ESCAPE '|'\"\n )\n conditions.push('(' + searchConditions.join(' OR ') + ')')\n }\n }\n \n paramIndex = processFilters(filters, conditions, queryParams, paramIndex)\n if (__rowPolicy) conditions.push('(' + __rowPolicy.predicate + ')')\n \n let sql = `SELECT * FROM ").concat(tableName, "`\n \n if (conditions.length > 0) {\n sql += ` WHERE ${conditions.join(' AND ')}`\n }\n \n // Handle sorts - new array format. Two ORDER BY clauses are built: the one\n // actually used (a translatable column in the request's language, the\n // products table's price rewrites), and a plain-column twin kept only as
|
|
64
|
+
: "[".concat(JSON.stringify(tableName), "]"), "\n \n const schemaResult = await client.query(schemaQuery, schemaParams)\n columns = schemaResult.rows.map(row => row.column_name)\n } catch (schemaError) {\n console.warn('Failed to fetch column names from information_schema:', schemaError.message)\n }\n }\n if (__rowPolicy) columns = __brpVisibleColumns(__rowPolicy, columns)\n \n if (columns.length > 0) {\n const pattern = '%' + escapeLikePattern(query) + '%'\n const placeholder = '$' + paramIndex\n paramIndex++\n queryParams.push(pattern)\n const searchConditions = columns.map(\n (col) => '\"' + sanitizeSearchIdentifier(col) + '\"::text ILIKE ' + placeholder + \" ESCAPE '|'\"\n )\n conditions.push('(' + searchConditions.join(' OR ') + ')')\n }\n }\n \n paramIndex = processFilters(filters, conditions, queryParams, paramIndex)\n if (__rowPolicy) conditions.push('(' + __rowPolicy.predicate + ')')\n \n let sql = `SELECT * FROM ").concat(tableName, "`\n \n if (conditions.length > 0) {\n sql += ` WHERE ${conditions.join(' AND ')}`\n }\n \n // Handle sorts - new array format. Two ORDER BY clauses are built: the one\n // actually used (a translatable column in the request's language, the\n // products table's price rewrites, rows without a value last), and a\n // plain-column twin kept only as the fallback below.\n let orderBySql = ''\n let plainOrderBySql = ''\n if (sorts) {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n const valid = parsedSorts.filter((sort) => sort && sort.field)\n valid.forEach((sort) => assertRequestColumn(sort.field, 'sort field'))\n const orderOf = (sort) => (sort.order || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'\n const orderClauses = valid.map((sort) => `${localizedSortFieldSql(sort.field, requestLocale) || sortFieldSql(sort.field)} ${orderOf(sort)}").concat(list_sort_order_1.SORT_NULLS_LAST_SQL, "`)\n const plainClauses = valid.map((sort) => `${sortFallbackField(sort.field)} ${orderOf(sort)}`)\n\n if (orderClauses.length > 0) {\n // The row's own key last, so equal rows can't repeat across pages\n // or vanish between them.\n const tiebreak = rowOrderTiebreak(valid.map((sort) => sort.field), orderOf(valid[valid.length - 1]))\n orderBySql = ` ORDER BY ${orderClauses.join(', ')}${tiebreak}`\n plainOrderBySql = ` ORDER BY ${plainClauses.join(', ')}${tiebreak}`\n }\n }\n } else if (sortBy) {\n assertRequestColumn(sortBy, 'sort field')\n const sortByDirection = (sortOrder || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'\n const tiebreak = rowOrderTiebreak([sortBy], sortByDirection)\n orderBySql = ` ORDER BY ${localizedSortFieldSql(sortBy, requestLocale) || sortBy} ${sortByDirection}").concat(list_sort_order_1.SORT_NULLS_LAST_SQL, "${tiebreak}`\n plainOrderBySql = ` ORDER BY ${sortBy} ${sortByDirection}${tiebreak}`\n }\n const usedRewrittenSort = orderBySql !== plainOrderBySql\n\n const limitValue = requestRowCount(limit || perPage)\n const offsetValue = offset !== undefined ? parseInt(offset) : (page && perPage ? (parseInt(page) - 1) * parseInt(perPage) : undefined)\n\n let sqlTail = ''\n if (limitValue !== undefined) {\n sqlTail += ` LIMIT ${limitValue}`\n }\n \n if (offsetValue !== undefined) {\n sqlTail += ` OFFSET ${offsetValue}`\n }\n\n const baseSql = sql\n sql = baseSql + orderBySql + sqlTail\n\n // The discount-aware price ordering is an inline sub-select over a JSON\n // column. It is written to be unraisable, but it runs inside ORDER BY for\n // the whole table - so if a database ever rejects it, fall back to ordering\n // by the stored list price rather than serving an empty products page. The\n // translatable-column ordering takes the same exit: a per-language column\n // the schema had at generation time may have been dropped since. So does\n // the empty-values-last ordering.\n let result\n try {\n result = await client.query(sql, queryParams)\n } catch (sortError) {\n if (!usedRewrittenSort) throw sortError\n console.warn(\n 'Rewritten sort failed; falling back to the plain column:',\n sortError && sortError.message\n )\n result = await client.query(baseSql + plainOrderBySql + sqlTail, queryParams)\n }\n const rows = Array.isArray(result?.rows) ? result.rows : []\n const plainRows = rows.map((row) =>\n row && typeof row.toJSON === 'function' ? row.toJSON() : row\n )\n const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))\n ").concat((0, transformations_1.getTransformExpression)(tableName)
|
|
62
65
|
? "const transformedData = ".concat((0, transformations_1.getTransformExpression)(tableName))
|
|
63
66
|
: '', "\n\n // Stamp each row with a globally-correct 1-based `__rowNumber` (the page\n // offset is applied server-side above), so list index columns keep counting\n // across pages instead of restarting at 1. Renderer-internal field \u2014 it is\n // filtered from ordinary field bindings and only read by the index column.\n const __finalData = ").concat((0, transformations_1.getTransformExpression)(tableName) ? 'transformedData' : 'safeData', "\n const __rowNumberStart = (typeof offsetValue === 'number' && !isNaN(offsetValue)) ? offsetValue : 0\n const __numberedData = Array.isArray(__finalData)\n ? __finalData.map((__row, __i) =>\n __row && typeof __row === 'object' && !Array.isArray(__row)\n ? Object.assign({}, __row, { __rowNumber: __rowNumberStart + __i + 1 })\n : __row)\n : __finalData\n\n return res.status(200).json({\n success: true,\n data: __taWithoutCredentials(\n __rowPolicy ? __brpStripHidden(__rowPolicy, __numberedData) : __numberedData,\n ").concat(JSON.stringify(tableName), "\n ),\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Teleport DB fetch error:', error)\n // A database error names tables, columns and values: it stays in the server\n // log. Only an error this route raised for the caller (it carries a status)\n // is repeated to it.\n return res.status(error.status || 500).json({\n success: false,\n error: error.status ? error.message : 'Failed to fetch data',\n timestamp: Date.now()\n })\n } finally {\n if (client) {\n try {\n await client.end()\n } catch (error) {\n console.error('Error closing database client:', error)\n }\n }\n }\n}\n");
|
|
64
67
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"teleport.js","sourceRoot":"","sources":["../../../src/fetchers/teleport.ts"],"names":[],"mappings":";;;AAAA,kCAMiB;AACjB,sDAK2B;AAC3B,
|
|
1
|
+
{"version":3,"file":"teleport.js","sourceRoot":"","sources":["../../../src/fetchers/teleport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ContentTables } from '@teleporthq/teleport-shared';
|
|
1
2
|
/**
|
|
2
3
|
* What a per-table read route (`/api/teleport-<table>-<source>` and its count
|
|
3
4
|
* twin) serves a BROWSER of the tables whose unpublished rows sit beside the
|
|
@@ -17,12 +18,12 @@
|
|
|
17
18
|
* bindings name every text column of the table — the blog list asks to search
|
|
18
19
|
* `author_email` — and refusing them emptied the blog for every visitor.
|
|
19
20
|
*/
|
|
20
|
-
export
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
21
|
+
export type BrowserRowPolicy = ContentTables.VisitorRowPolicy;
|
|
22
|
+
/**
|
|
23
|
+
* One map for both route families: the content presets' posts tables (ONLY
|
|
24
|
+
* `published` rows, never the author's email — see
|
|
25
|
+
* `CONTENT_POSTS_VISITOR_ROW_POLICY`) and the catalogue's products.
|
|
26
|
+
*/
|
|
26
27
|
export declare const BROWSER_ROW_POLICIES: Readonly<Record<string, BrowserRowPolicy>>;
|
|
27
28
|
/**
|
|
28
29
|
* ES5 source inlined after the table-access preamble (it uses `__ta*` and
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-row-policy.d.ts","sourceRoot":"","sources":["../../../../src/fetchers/utils/browser-row-policy.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"browser-row-policy.d.ts","sourceRoot":"","sources":["../../../../src/fetchers/utils/browser-row-policy.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAE3D;;;;;;;;;;;;;;;;;;GAkBG;AAEH,MAAM,MAAM,gBAAgB,GAAG,aAAa,CAAC,gBAAgB,CAAA;AAE7D;;;;GAIG;AACH,eAAO,MAAM,oBAAoB,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CACxC,CAAA;AAEpC;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,QACnC,MA+HL,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,cACpB,MAAM,mBACA,cAAc,MAAM,CAAC,KACrC,OAUF,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,4BAA4B,cAC5B,MAAM,gBACH,MAAM,GAAG,IAAI,KAC1B,MASF,CAAA"}
|
|
@@ -1,39 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* What a per-table read route (`/api/teleport-<table>-<source>` and its count
|
|
4
|
-
* twin) serves a BROWSER of the tables whose unpublished rows sit beside the
|
|
5
|
-
* public ones. (The tables it serves a browser not at all — the AI assistant's
|
|
6
|
-
* among them — are `TableAccess.PROTECTED_TABLES`, guarded by `__taGuardRead`.)
|
|
7
|
-
*
|
|
8
|
-
* The route answers whoever asks, with the whole table. For the blog that was
|
|
9
|
-
* every draft, scheduled and archived post — and each author's email address;
|
|
10
|
-
* for the catalogue, every draft and inactive product. The storefront's own
|
|
11
|
-
* bindings ask for the public rows, but the route is a URL anyone can call
|
|
12
|
-
* without them. So a caller that is not the store itself (its server code, or a
|
|
13
|
-
* signed-in administrator — the generated admin edits drafts through these
|
|
14
|
-
* routes) is served only the rows the storefront publishes, never a hidden
|
|
15
|
-
* column, and may neither filter nor sort by a hidden column: a filter is an
|
|
16
|
-
* oracle for a column it never returns. A hidden SEARCH column is dropped from
|
|
17
|
-
* the search instead (`__brpVisibleColumns`), because the storefront's own list
|
|
18
|
-
* bindings name every text column of the table — the blog list asks to search
|
|
19
|
-
* `author_email` — and refusing them emptied the blog for every visitor.
|
|
20
|
-
*/
|
|
21
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
22
3
|
exports.generateBrowserRowAccessCall = exports.isViewDependentTable = exports.generateBrowserRowPolicyCode = exports.BROWSER_ROW_POLICIES = void 0;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
// The storefront sells `active` products; a draft or inactive one is the
|
|
31
|
-
// merchant's, spelled in any case the admin form stored it in.
|
|
32
|
-
teleport_products: {
|
|
33
|
-
predicate: "LOWER(TRIM(status)) = 'active'",
|
|
34
|
-
hiddenColumns: [],
|
|
35
|
-
},
|
|
36
|
-
};
|
|
4
|
+
var teleport_shared_1 = require("@teleporthq/teleport-shared");
|
|
5
|
+
/**
|
|
6
|
+
* One map for both route families: the content presets' posts tables (ONLY
|
|
7
|
+
* `published` rows, never the author's email — see
|
|
8
|
+
* `CONTENT_POSTS_VISITOR_ROW_POLICY`) and the catalogue's products.
|
|
9
|
+
*/
|
|
10
|
+
exports.BROWSER_ROW_POLICIES = teleport_shared_1.ContentTables.VISITOR_ROW_POLICIES;
|
|
37
11
|
/**
|
|
38
12
|
* ES5 source inlined after the table-access preamble (it uses `__ta*` and
|
|
39
13
|
* `__tqSessionToken`). Declares `__brpAccess(req, tableName, rawQuery)`, which
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-row-policy.js","sourceRoot":"","sources":["../../../../src/fetchers/utils/browser-row-policy.ts"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"browser-row-policy.js","sourceRoot":"","sources":["../../../../src/fetchers/utils/browser-row-policy.ts"],"names":[],"mappings":";;;AAAA,+DAA2D;AAwB3D;;;;GAIG;AACU,QAAA,oBAAoB,GAC/B,+BAAa,CAAC,oBAAoB,CAAA;AAEpC;;;;;;;GAOG;AACI,IAAM,4BAA4B,GACvC,cAAc,OAAA,mHACO,IAAI,CAAC,SAAS,CAAC,4BAAoB,CAAC,q8JA8H1D,EA/He,CA+Hf,CAAA;AAhIY,QAAA,4BAA4B,gCAgIxC;AAED;;;GAGG;AACI,IAAM,oBAAoB,GAAG,UAClC,SAAiB,EACjB,eAAsC;IAEtC,IAAM,KAAK,GAAG,MAAM,CAAC,SAAS,IAAI,EAAE,CAAC;SAClC,IAAI,EAAE;SACN,WAAW,EAAE;SACb,KAAK,CAAC,GAAG,CAAC,CAAA;IACb,IAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;IACtD,OAAO,CACL,MAAM,CAAC,SAAS,CAAC,cAAc,CAAC,IAAI,CAAC,4BAAoB,EAAE,IAAI,CAAC;QAChE,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CACrC,CAAA;AACH,CAAC,CAAA;AAbY,QAAA,oBAAoB,wBAahC;AAED;;;GAGG;AACI,IAAM,4BAA4B,GAAG,UAC1C,SAAiB,EACjB,YAA2B;IAE3B,OAAO,uDAAgD,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,eAC9E,YAAY,IAAI,MAAM,yNAMzB,CAAA;AACD,CAAC,CAAA;AAZY,QAAA,4BAA4B,gCAYxC"}
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import * as types from '@babel/types';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* One entry of the filter TREE the inspector authors: a condition leaf, or a
|
|
4
|
+
* group of further entries joined with `and` / `or`. The generated fetchers
|
|
5
|
+
* read this same tree (`normalizeFilterTree` in utils.ts), so the group
|
|
6
|
+
* operator must reach them intact — flattening an `or` group into its leaves
|
|
7
|
+
* turns "any of" into "all of" on the published site.
|
|
8
|
+
*/
|
|
9
|
+
export type FilterCondition = {
|
|
3
10
|
source?: string;
|
|
4
11
|
operand?: string;
|
|
5
12
|
destination: unknown;
|
|
6
|
-
}
|
|
7
|
-
export
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
}
|
|
13
|
+
};
|
|
14
|
+
export type FilterGroup = {
|
|
15
|
+
type: 'group';
|
|
16
|
+
operator?: string;
|
|
17
|
+
children: FilterEntry[];
|
|
18
|
+
};
|
|
19
|
+
export type FilterEntry = FilterCondition | FilterGroup;
|
|
20
|
+
export declare const isFilterGroup: (entry: unknown) => entry is FilterGroup;
|
|
21
|
+
export declare const buildFiltersStringifyCall: (filters: FilterEntry[], buildDestinationExpression: (destination: unknown) => types.Expression) => types.CallExpression;
|
|
22
|
+
export declare const buildStaticFiltersStringifyCall: (filters: FilterEntry[]) => types.CallExpression;
|
|
23
|
+
export declare const appendFiltersParam: (paramsProps: types.ObjectProperty[], filters: FilterEntry[] | undefined, buildDestinationExpression: (destination: unknown) => types.Expression) => void;
|
|
12
24
|
export declare const pushStateIdsAsDeps: (deps: types.Expression[], seen: Set<string>, stateIds: string[]) => void;
|
|
13
25
|
export declare const pushPropIdsAsDeps: (deps: types.Expression[], seen: Set<string>, propIds: string[]) => void;
|
|
14
26
|
//# sourceMappingURL=filter-utils.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-utils.d.ts","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;
|
|
1
|
+
{"version":3,"file":"filter-utils.d.ts","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC;;;;;;GAMG;AACH,MAAM,MAAM,eAAe,GAAG;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAA;AACzF,MAAM,MAAM,WAAW,GAAG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,WAAW,EAAE,CAAA;CAAE,CAAA;AACvF,MAAM,MAAM,WAAW,GAAG,eAAe,GAAG,WAAW,CAAA;AAEvD,eAAO,MAAM,aAAa,UAAW,OAAO,yBAIe,CAAA;AA+H3D,eAAO,MAAM,yBAAyB,YAC3B,WAAW,EAAE,4CACoB,OAAO,KAAK,MAAM,UAAU,KACrE,MAAM,cAIN,CAAA;AAiBH,eAAO,MAAM,+BAA+B,YAAa,WAAW,EAAE,KAAG,MAAM,cAI5E,CAAA;AAGH,eAAO,MAAM,kBAAkB,gBAChB,MAAM,cAAc,EAAE,WAC1B,WAAW,EAAE,GAAG,SAAS,4CACQ,OAAO,KAAK,MAAM,UAAU,KACrE,IAUF,CAAA;AAUD,eAAO,MAAM,kBAAkB,SACvB,MAAM,UAAU,EAAE,QAClB,IAAI,MAAM,CAAC,YACP,MAAM,EAAE,KACjB,IAQF,CAAA;AAaD,eAAO,MAAM,iBAAiB,SACtB,MAAM,UAAU,EAAE,QAClB,IAAI,MAAM,CAAC,WACR,MAAM,EAAE,KAChB,IASF,CAAA"}
|
package/dist/cjs/filter-utils.js
CHANGED
|
@@ -23,8 +23,15 @@ var __importStar = (this && this.__importStar) || function (mod) {
|
|
|
23
23
|
return result;
|
|
24
24
|
};
|
|
25
25
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
-
exports.pushPropIdsAsDeps = exports.pushStateIdsAsDeps = exports.appendFiltersParam = exports.buildFiltersStringifyCall = void 0;
|
|
26
|
+
exports.pushPropIdsAsDeps = exports.pushStateIdsAsDeps = exports.appendFiltersParam = exports.buildStaticFiltersStringifyCall = exports.buildFiltersStringifyCall = exports.isFilterGroup = void 0;
|
|
27
27
|
var types = __importStar(require("@babel/types"));
|
|
28
|
+
var isFilterGroup = function (entry) {
|
|
29
|
+
return !!entry &&
|
|
30
|
+
typeof entry === 'object' &&
|
|
31
|
+
entry.type === 'group' &&
|
|
32
|
+
Array.isArray(entry.children);
|
|
33
|
+
};
|
|
34
|
+
exports.isFilterGroup = isFilterGroup;
|
|
28
35
|
// Build a single filter entry: { source: '<src>', destination: <destExpr>, operand: '<op>' }
|
|
29
36
|
var buildFilterEntry = function (source, destinationExpr, operand) {
|
|
30
37
|
return types.objectExpression([
|
|
@@ -33,10 +40,19 @@ var buildFilterEntry = function (source, destinationExpr, operand) {
|
|
|
33
40
|
types.objectProperty(types.identifier('operand'), types.stringLiteral(operand)),
|
|
34
41
|
]);
|
|
35
42
|
};
|
|
43
|
+
// { type: 'group', operator: 'and' | 'or', children: <childrenExpr> }
|
|
44
|
+
var buildFilterGroup = function (operator, childrenExpr) {
|
|
45
|
+
return types.objectExpression([
|
|
46
|
+
types.objectProperty(types.identifier('type'), types.stringLiteral('group')),
|
|
47
|
+
types.objectProperty(types.identifier('operator'), types.stringLiteral(operator === 'or' ? 'or' : 'and')),
|
|
48
|
+
types.objectProperty(types.identifier('children'), childrenExpr),
|
|
49
|
+
]);
|
|
50
|
+
};
|
|
36
51
|
// Predicate:
|
|
37
|
-
// (__f) => __f.
|
|
38
|
-
// __f.destination !==
|
|
39
|
-
//
|
|
52
|
+
// (__f) => __f.type === 'group' ||
|
|
53
|
+
// (__f.destination !== '' && __f.destination !== null &&
|
|
54
|
+
// __f.destination !== undefined &&
|
|
55
|
+
// !(Array.isArray(__f.destination) && __f.destination.filter(Boolean).length === 0))
|
|
40
56
|
// Used at runtime to drop filter conditions whose destination resolves to an
|
|
41
57
|
// empty value. Keeps the page generic: state-bound filters (e.g.
|
|
42
58
|
// `selectedCategory === ''` after picking "All Categories") and url-bound
|
|
@@ -46,19 +62,31 @@ var buildFilterEntry = function (source, destinationExpr, operand) {
|
|
|
46
62
|
// string and returns zero rows. The array clause covers array-overlap filters
|
|
47
63
|
// (e.g. category `CATEGORY_DESCENDANTS[selectedCategory] || []`) whose "All"
|
|
48
64
|
// reset resolves to `[]` — an empty overlap set must mean "no filter", not
|
|
49
|
-
// "match nothing".
|
|
65
|
+
// "match nothing". A group has no destination of its own and is kept; its
|
|
66
|
+
// children carry the same `.filter(...)`, and a group emptied that way is
|
|
67
|
+
// dropped by the fetcher's `normalizeFilterTree`.
|
|
50
68
|
var buildNonEmptyDestinationPredicate = function () {
|
|
51
69
|
var f = types.identifier('__f');
|
|
52
70
|
var dest = types.memberExpression(f, types.identifier('destination'));
|
|
53
71
|
var isEmptyArray = types.logicalExpression('&&', types.callExpression(types.memberExpression(types.identifier('Array'), types.identifier('isArray')), [dest]), types.binaryExpression('===', types.memberExpression(types.callExpression(types.memberExpression(dest, types.identifier('filter')), [
|
|
54
72
|
types.identifier('Boolean'),
|
|
55
73
|
]), types.identifier('length')), types.numericLiteral(0)));
|
|
56
|
-
return types.arrowFunctionExpression([f], types.logicalExpression('&&', types.logicalExpression('&&', types.logicalExpression('&&', types.binaryExpression('!==', dest, types.stringLiteral('')), types.binaryExpression('!==', dest, types.nullLiteral())), types.binaryExpression('!==', dest, types.identifier('undefined'))), types.unaryExpression('!', isEmptyArray)));
|
|
74
|
+
return types.arrowFunctionExpression([f], types.logicalExpression('||', types.binaryExpression('===', types.memberExpression(f, types.identifier('type')), types.stringLiteral('group')), types.logicalExpression('&&', types.logicalExpression('&&', types.logicalExpression('&&', types.binaryExpression('!==', dest, types.stringLiteral('')), types.binaryExpression('!==', dest, types.nullLiteral())), types.binaryExpression('!==', dest, types.identifier('undefined'))), types.unaryExpression('!', isEmptyArray))));
|
|
75
|
+
};
|
|
76
|
+
// `[ entry, ... ].filter(<non-empty destination>)`, recursing into groups so
|
|
77
|
+
// every level of the tree drops its empty conditions at runtime.
|
|
78
|
+
var buildFilteredEntriesArray = function (filters, buildDestinationExpression) {
|
|
79
|
+
var entries = filters.map(function (filter) {
|
|
80
|
+
return (0, exports.isFilterGroup)(filter)
|
|
81
|
+
? buildFilterGroup(filter.operator, buildFilteredEntriesArray(filter.children, buildDestinationExpression))
|
|
82
|
+
: buildFilterEntry(filter.source || '', buildDestinationExpression(filter.destination), filter.operand || '');
|
|
83
|
+
});
|
|
84
|
+
return types.callExpression(types.memberExpression(types.arrayExpression(entries), types.identifier('filter')), [buildNonEmptyDestinationPredicate()]);
|
|
57
85
|
};
|
|
58
86
|
// Build the AST for:
|
|
59
87
|
// JSON.stringify(
|
|
60
|
-
// [ {source, destination, operand}, ... ]
|
|
61
|
-
// .filter(__f => __f.destination !== '' && __f.destination !== null && __f.destination !== undefined)
|
|
88
|
+
// [ {source, destination, operand}, { type: 'group', operator, children: [...].filter(...) }, ... ]
|
|
89
|
+
// .filter(__f => __f.type === 'group' || (__f.destination !== '' && __f.destination !== null && __f.destination !== undefined))
|
|
62
90
|
// )
|
|
63
91
|
//
|
|
64
92
|
// The `.filter(...)` step is unconditional even when every entry is a static
|
|
@@ -67,13 +95,21 @@ var buildNonEmptyDestinationPredicate = function () {
|
|
|
67
95
|
// type is added but its empty-value behavior is forgotten don't silently
|
|
68
96
|
// re-introduce empty-string filters.
|
|
69
97
|
var buildFiltersStringifyCall = function (filters, buildDestinationExpression) {
|
|
70
|
-
|
|
71
|
-
return buildFilterEntry(filter.source || '', buildDestinationExpression(filter.destination), filter.operand || '');
|
|
72
|
-
});
|
|
73
|
-
var filteredArray = types.callExpression(types.memberExpression(types.arrayExpression(entries), types.identifier('filter')), [buildNonEmptyDestinationPredicate()]);
|
|
74
|
-
return types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [filteredArray]);
|
|
98
|
+
return types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [buildFilteredEntriesArray(filters, buildDestinationExpression)]);
|
|
75
99
|
};
|
|
76
100
|
exports.buildFiltersStringifyCall = buildFiltersStringifyCall;
|
|
101
|
+
// The build-time counterpart for `getStaticProps`: every destination is a
|
|
102
|
+
// literal (the dynamic ones were pruned — see `pruneFilterTree`), so the tree
|
|
103
|
+
// is written out as plain string literals with no runtime `.filter(...)`.
|
|
104
|
+
var buildStaticFilterEntryAST = function (filter) {
|
|
105
|
+
return (0, exports.isFilterGroup)(filter)
|
|
106
|
+
? buildFilterGroup(filter.operator, types.arrayExpression(filter.children.map(buildStaticFilterEntryAST)))
|
|
107
|
+
: buildFilterEntry(filter.source || '', types.stringLiteral(typeof filter.destination === 'string' ? filter.destination : ''), filter.operand || '');
|
|
108
|
+
};
|
|
109
|
+
var buildStaticFiltersStringifyCall = function (filters) {
|
|
110
|
+
return types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [types.arrayExpression(filters.map(buildStaticFilterEntryAST))]);
|
|
111
|
+
};
|
|
112
|
+
exports.buildStaticFiltersStringifyCall = buildStaticFiltersStringifyCall;
|
|
77
113
|
// Convenience: push `filters: <call>` onto a paramsProps array.
|
|
78
114
|
var appendFiltersParam = function (paramsProps, filters, buildDestinationExpression) {
|
|
79
115
|
if (!filters || filters.length === 0) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filter-utils.js","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kDAAqC;
|
|
1
|
+
{"version":3,"file":"filter-utils.js","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -14,6 +14,15 @@ import * as types from '@babel/types';
|
|
|
14
14
|
* and re-enter it. The ref is keyed by a SIGNATURE of every fetch param except
|
|
15
15
|
* the page, so a filter, sort or search change starts a fresh list instead of
|
|
16
16
|
* interleaving rows from two different queries.
|
|
17
|
+
*
|
|
18
|
+
* `fetchData` records the query and the page the list stands on BEFORE it
|
|
19
|
+
* requests them (`latest`), and only the answer to that request changes the
|
|
20
|
+
* list. A filter, sort or search change made past page 1 fires the old page
|
|
21
|
+
* under the new query first, then page 1 once the page is reset: kept, the
|
|
22
|
+
* stray page sat in the list, the page counter said 1, and the next "Load
|
|
23
|
+
* more" fetched a page already on show. `DataProvider` also renders whichever
|
|
24
|
+
* answer arrives LAST, so a late answer to an earlier query must not replace
|
|
25
|
+
* the list either.
|
|
17
26
|
*/
|
|
18
27
|
export interface InfiniteScrollVars {
|
|
19
28
|
accumRefVar: string;
|
|
@@ -37,11 +46,20 @@ export declare const getInfiniteScrollVars: (index: number) => InfiniteScrollVar
|
|
|
37
46
|
* being made at all; it is `0` while unknown, hence the explicit escape.
|
|
38
47
|
*/
|
|
39
48
|
export declare const buildInfiniteScrollDeclarations: (vars: InfiniteScrollVars, maxPagesVar: string, currentPageExpr: types.Expression, includeSentinel: boolean) => types.Statement[];
|
|
49
|
+
/**
|
|
50
|
+
* What `fetchData` runs before its request: the query and the page the list
|
|
51
|
+
* now stands on.
|
|
52
|
+
*
|
|
53
|
+
* ds_0_accumRef.current.latest = { sig: JSON.stringify({ ...params, page: 0 }), page: Number(params.page) || 1 }
|
|
54
|
+
*/
|
|
55
|
+
export declare const buildAccumulatingRequestMark: (vars: InfiniteScrollVars) => types.Statement;
|
|
40
56
|
/**
|
|
41
57
|
* The `.then(...)` tail that accumulates a page and reports whether more exist.
|
|
42
58
|
*
|
|
43
59
|
* Returned as the resolved value of `fetchData`, so `DataProvider` stores the
|
|
44
|
-
* whole accumulated list as its data
|
|
60
|
+
* whole accumulated list as its data: the pages of the query on show, first
|
|
61
|
+
* to the page it stands on. An answer to anything but the latest request
|
|
62
|
+
* (`buildAccumulatingRequestMark`) is not kept, and gets the list as it is.
|
|
45
63
|
*
|
|
46
64
|
* `itemsPath` is where the rows sit inside a payload that wraps them
|
|
47
65
|
* (`{ items: [...], total }`): the rows are read there and the accumulated list
|
|
@@ -66,6 +84,11 @@ export declare const buildSentinelObserverEffect: (vars: InfiniteScrollVars, max
|
|
|
66
84
|
* An invisible one-pixel row after the list. It is generated rather than
|
|
67
85
|
* authored because it is not a control — there is nothing to style or click,
|
|
68
86
|
* only a position in the document for the observer to watch.
|
|
87
|
+
*
|
|
88
|
+
* It takes the element its parent may hold: a table section holds rows, a
|
|
89
|
+
* list holds items, a paragraph holds phrasing. A `<div>` among a table's
|
|
90
|
+
* rows is moved out of the table by the parser, so the server's markup and
|
|
91
|
+
* the client's tree differ and React's hydration fails on every such list.
|
|
69
92
|
*/
|
|
70
|
-
export declare const buildSentinelElement: (vars: InfiniteScrollVars) => types.JSXElement;
|
|
93
|
+
export declare const buildSentinelElement: (vars: InfiniteScrollVars, parentTag?: string | null) => types.JSXElement;
|
|
71
94
|
//# sourceMappingURL=infinite-scroll.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"infinite-scroll.d.ts","sourceRoot":"","sources":["../../src/infinite-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC
|
|
1
|
+
{"version":3,"file":"infinite-scroll.d.ts","sourceRoot":"","sources":["../../src/infinite-scroll.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAErC;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAIH,MAAM,WAAW,kBAAkB;IACjC,WAAW,EAAE,MAAM,CAAA;IACnB,cAAc,EAAE,MAAM,CAAA;IACtB,iBAAiB,EAAE,MAAM,CAAA;IACzB,UAAU,EAAE,MAAM,CAAA;IAClB,cAAc,EAAE,MAAM,CAAA;CACvB;AAED,eAAO,MAAM,qBAAqB,UAAW,MAAM,KAAG,kBAMpD,CAAA;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,+BAA+B,SACpC,kBAAkB,eACX,MAAM,mBACF,MAAM,UAAU,mBAChB,OAAO,KACvB,MAAM,SAAS,EAuDjB,CAAA;AA+ED;;;;;GAKG;AACH,eAAO,MAAM,4BAA4B,SAAU,kBAAkB,KAAG,MAAM,SAU3E,CAAA;AAEH;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,gCAAgC,SACrC,kBAAkB,WACf,MAAM,cACH,MAAM,EAAE,KACnB,MAAM,uBA+KR,CAAA;AAED;;;;;;;;GAQG;AACH,eAAO,MAAM,2BAA2B,SAChC,kBAAkB,eACX,MAAM,6BACQ,MAAM,MAAM,SAAS,KAC/C,MAAM,mBAoGN,CAAA;AAmDH;;;;;;;;;;;GAWG;AACH,eAAO,MAAM,oBAAoB,SACzB,kBAAkB,cACb,MAAM,GAAG,IAAI,KACvB,MAAM,UAmCR,CAAA"}
|