@teleporthq/teleport-plugin-next-data-source 0.43.66 → 0.43.68
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__/array-mapper-cache-wiring.test.ts +11 -0
- package/__tests__/array-overlap-sql.test.ts +53 -0
- package/__tests__/blog-post-page-enrichment.test.ts +214 -0
- package/__tests__/browser-row-policy.test.ts +503 -0
- package/__tests__/data-source-cache-wrapping.test.ts +18 -2
- package/__tests__/data-source-request-locale.test.ts +313 -0
- package/__tests__/ecommerce-product-options.test.ts +206 -0
- package/__tests__/ecommerce-product-pages.test.ts +82 -0
- package/__tests__/ecommerce-product-pre-options.golden.json +505 -0
- package/__tests__/ecommerce-product-storefront-contract.test.ts +293 -0
- package/__tests__/ecommerce-product-subscriptions.test.ts +121 -0
- package/__tests__/fetchers.test.ts +2 -2
- package/__tests__/gated-data-provider.test.ts +88 -0
- package/__tests__/items-path.test.ts +150 -0
- package/__tests__/localized-columns.test.ts +217 -0
- package/__tests__/numbered-pagination.test.ts +15 -0
- package/__tests__/product-filter-fields.ts +230 -0
- package/__tests__/product-filter-sql.fixture.json +7 -0
- package/__tests__/product-options-storefront.fixture.json +2510 -0
- package/__tests__/product-page-url-fixtures.json +25 -0
- package/__tests__/product-price-sort.ts +4 -2
- package/__tests__/raw-rows-mode.test.ts +111 -0
- package/__tests__/refetch-loading-state.test.ts +23 -0
- package/__tests__/rest-api-response-cache.test.ts +434 -0
- package/__tests__/search-clear-button.test.ts +122 -0
- package/__tests__/table-read-route-protected-tables.test.ts +493 -0
- package/dist/cjs/array-overlap-sql.d.ts +21 -0
- package/dist/cjs/array-overlap-sql.d.ts.map +1 -0
- package/dist/cjs/array-overlap-sql.js +25 -0
- package/dist/cjs/array-overlap-sql.js.map +1 -0
- package/dist/cjs/content-localization.d.ts +37 -0
- package/dist/cjs/content-localization.d.ts.map +1 -0
- package/dist/cjs/content-localization.js +29 -0
- package/dist/cjs/content-localization.js.map +1 -0
- package/dist/cjs/count-effect.d.ts +11 -1
- package/dist/cjs/count-effect.d.ts.map +1 -1
- package/dist/cjs/count-effect.js +30 -2
- package/dist/cjs/count-effect.js.map +1 -1
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +10 -4
- package/dist/cjs/data-source-fetchers.js.map +1 -1
- package/dist/cjs/fetchers/airtable.d.ts.map +1 -1
- package/dist/cjs/fetchers/airtable.js +1 -1
- package/dist/cjs/fetchers/airtable.js.map +1 -1
- package/dist/cjs/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/cjs/fetchers/clickhouse.js +1 -1
- package/dist/cjs/fetchers/clickhouse.js.map +1 -1
- package/dist/cjs/fetchers/firestore.d.ts.map +1 -1
- package/dist/cjs/fetchers/firestore.js +1 -1
- package/dist/cjs/fetchers/firestore.js.map +1 -1
- package/dist/cjs/fetchers/javascript.d.ts.map +1 -1
- package/dist/cjs/fetchers/javascript.js +1 -1
- package/dist/cjs/fetchers/javascript.js.map +1 -1
- package/dist/cjs/fetchers/mariadb.d.ts.map +1 -1
- package/dist/cjs/fetchers/mariadb.js +1 -1
- package/dist/cjs/fetchers/mariadb.js.map +1 -1
- package/dist/cjs/fetchers/mongodb.d.ts.map +1 -1
- package/dist/cjs/fetchers/mongodb.js +1 -1
- package/dist/cjs/fetchers/mongodb.js.map +1 -1
- package/dist/cjs/fetchers/mysql.d.ts.map +1 -1
- package/dist/cjs/fetchers/mysql.js +1 -1
- package/dist/cjs/fetchers/mysql.js.map +1 -1
- package/dist/cjs/fetchers/postgresql.d.ts +1 -1
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +9 -4
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/raw-query.d.ts +8 -1
- package/dist/cjs/fetchers/raw-query.d.ts.map +1 -1
- package/dist/cjs/fetchers/raw-query.js +42 -4
- package/dist/cjs/fetchers/raw-query.js.map +1 -1
- package/dist/cjs/fetchers/redshift.d.ts.map +1 -1
- package/dist/cjs/fetchers/redshift.js +1 -1
- package/dist/cjs/fetchers/redshift.js.map +1 -1
- package/dist/cjs/fetchers/rest-api.d.ts.map +1 -1
- package/dist/cjs/fetchers/rest-api.js +7 -2
- 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 +16 -6
- package/dist/cjs/fetchers/teleport.js.map +1 -1
- package/dist/cjs/fetchers/turso.d.ts.map +1 -1
- package/dist/cjs/fetchers/turso.js +1 -1
- package/dist/cjs/fetchers/turso.js.map +1 -1
- package/dist/cjs/fetchers/utils/browser-row-policy.d.ts +43 -0
- package/dist/cjs/fetchers/utils/browser-row-policy.d.ts.map +1 -0
- package/dist/cjs/fetchers/utils/browser-row-policy.js +66 -0
- package/dist/cjs/fetchers/utils/browser-row-policy.js.map +1 -0
- package/dist/cjs/fetchers/utils/request-sql-guards.d.ts +8 -0
- package/dist/cjs/fetchers/utils/request-sql-guards.d.ts.map +1 -0
- package/dist/cjs/fetchers/utils/request-sql-guards.js +12 -0
- package/dist/cjs/fetchers/utils/request-sql-guards.js.map +1 -0
- package/dist/cjs/fetchers/utils/rest-api-response-cache.d.ts +40 -0
- package/dist/cjs/fetchers/utils/rest-api-response-cache.d.ts.map +1 -0
- package/dist/cjs/fetchers/utils/rest-api-response-cache.js +64 -0
- package/dist/cjs/fetchers/utils/rest-api-response-cache.js.map +1 -0
- package/dist/cjs/fetchers/utils/table-access-guard.d.ts +23 -0
- package/dist/cjs/fetchers/utils/table-access-guard.d.ts.map +1 -0
- package/dist/cjs/fetchers/utils/table-access-guard.js +34 -0
- package/dist/cjs/fetchers/utils/table-access-guard.js.map +1 -0
- package/dist/cjs/index.d.ts +5 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +60 -8
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/items-path.d.ts +10 -0
- package/dist/cjs/items-path.d.ts.map +1 -0
- package/dist/cjs/items-path.js +86 -0
- package/dist/cjs/items-path.js.map +1 -0
- package/dist/cjs/loading-state.d.ts +16 -1
- package/dist/cjs/loading-state.d.ts.map +1 -1
- package/dist/cjs/loading-state.js +69 -3
- package/dist/cjs/loading-state.js.map +1 -1
- package/dist/cjs/localized-columns.d.ts +56 -0
- package/dist/cjs/localized-columns.d.ts.map +1 -0
- package/dist/cjs/localized-columns.js +137 -0
- package/dist/cjs/localized-columns.js.map +1 -0
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +140 -50
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/product-filter-fields.d.ts +87 -0
- package/dist/cjs/product-filter-fields.d.ts.map +1 -0
- package/dist/cjs/product-filter-fields.js +161 -0
- package/dist/cjs/product-filter-fields.js.map +1 -0
- package/dist/cjs/request-locale.d.ts +49 -0
- package/dist/cjs/request-locale.d.ts.map +1 -0
- package/dist/cjs/request-locale.js +130 -0
- package/dist/cjs/request-locale.js.map +1 -0
- package/dist/cjs/search-clear.d.ts +31 -0
- package/dist/cjs/search-clear.d.ts.map +1 -0
- package/dist/cjs/search-clear.js +103 -0
- package/dist/cjs/search-clear.js.map +1 -0
- package/dist/cjs/transformations/blog-adjacent-posts.d.ts +16 -0
- package/dist/cjs/transformations/blog-adjacent-posts.d.ts.map +1 -0
- package/dist/cjs/transformations/blog-adjacent-posts.js +25 -0
- package/dist/cjs/transformations/blog-adjacent-posts.js.map +1 -0
- package/dist/cjs/transformations/blog-comments.d.ts +30 -0
- package/dist/cjs/transformations/blog-comments.d.ts.map +1 -0
- package/dist/cjs/transformations/blog-comments.js +34 -0
- package/dist/cjs/transformations/blog-comments.js.map +1 -0
- package/dist/cjs/transformations/blog-post.d.ts +2 -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/ecommerce-product.d.ts +9 -1
- package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/cjs/transformations/ecommerce-product.js +28 -1
- package/dist/cjs/transformations/ecommerce-product.js.map +1 -1
- package/dist/cjs/transformations/heading-anchors.d.ts +25 -0
- package/dist/cjs/transformations/heading-anchors.d.ts.map +1 -0
- package/dist/cjs/transformations/heading-anchors.js +29 -0
- package/dist/cjs/transformations/heading-anchors.js.map +1 -0
- package/dist/cjs/transformations/index.d.ts +61 -4
- package/dist/cjs/transformations/index.d.ts.map +1 -1
- package/dist/cjs/transformations/index.js +69 -19
- package/dist/cjs/transformations/index.js.map +1 -1
- package/dist/cjs/transformations/shared-utils.d.ts.map +1 -1
- package/dist/cjs/transformations/shared-utils.js +1 -1
- package/dist/cjs/transformations/shared-utils.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +11 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +60 -16
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/array-overlap-sql.d.ts +21 -0
- package/dist/esm/array-overlap-sql.d.ts.map +1 -0
- package/dist/esm/array-overlap-sql.js +21 -0
- package/dist/esm/array-overlap-sql.js.map +1 -0
- package/dist/esm/content-localization.d.ts +37 -0
- package/dist/esm/content-localization.d.ts.map +1 -0
- package/dist/esm/content-localization.js +24 -0
- package/dist/esm/content-localization.js.map +1 -0
- package/dist/esm/count-effect.d.ts +11 -1
- package/dist/esm/count-effect.d.ts.map +1 -1
- package/dist/esm/count-effect.js +28 -1
- package/dist/esm/count-effect.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +11 -5
- package/dist/esm/data-source-fetchers.js.map +1 -1
- package/dist/esm/fetchers/airtable.d.ts.map +1 -1
- package/dist/esm/fetchers/airtable.js +1 -1
- package/dist/esm/fetchers/airtable.js.map +1 -1
- package/dist/esm/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/esm/fetchers/clickhouse.js +1 -1
- package/dist/esm/fetchers/clickhouse.js.map +1 -1
- package/dist/esm/fetchers/firestore.d.ts.map +1 -1
- package/dist/esm/fetchers/firestore.js +1 -1
- package/dist/esm/fetchers/firestore.js.map +1 -1
- package/dist/esm/fetchers/javascript.d.ts.map +1 -1
- package/dist/esm/fetchers/javascript.js +1 -1
- package/dist/esm/fetchers/javascript.js.map +1 -1
- package/dist/esm/fetchers/mariadb.d.ts.map +1 -1
- package/dist/esm/fetchers/mariadb.js +1 -1
- package/dist/esm/fetchers/mariadb.js.map +1 -1
- package/dist/esm/fetchers/mongodb.d.ts.map +1 -1
- package/dist/esm/fetchers/mongodb.js +1 -1
- package/dist/esm/fetchers/mongodb.js.map +1 -1
- package/dist/esm/fetchers/mysql.d.ts.map +1 -1
- package/dist/esm/fetchers/mysql.js +1 -1
- package/dist/esm/fetchers/mysql.js.map +1 -1
- package/dist/esm/fetchers/postgresql.d.ts +1 -1
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +9 -4
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/raw-query.d.ts +8 -1
- package/dist/esm/fetchers/raw-query.d.ts.map +1 -1
- package/dist/esm/fetchers/raw-query.js +42 -4
- package/dist/esm/fetchers/raw-query.js.map +1 -1
- package/dist/esm/fetchers/redshift.d.ts.map +1 -1
- package/dist/esm/fetchers/redshift.js +1 -1
- package/dist/esm/fetchers/redshift.js.map +1 -1
- package/dist/esm/fetchers/rest-api.d.ts.map +1 -1
- package/dist/esm/fetchers/rest-api.js +7 -2
- 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 +16 -6
- package/dist/esm/fetchers/teleport.js.map +1 -1
- package/dist/esm/fetchers/turso.d.ts.map +1 -1
- package/dist/esm/fetchers/turso.js +1 -1
- package/dist/esm/fetchers/turso.js.map +1 -1
- package/dist/esm/fetchers/utils/browser-row-policy.d.ts +43 -0
- package/dist/esm/fetchers/utils/browser-row-policy.d.ts.map +1 -0
- package/dist/esm/fetchers/utils/browser-row-policy.js +60 -0
- package/dist/esm/fetchers/utils/browser-row-policy.js.map +1 -0
- package/dist/esm/fetchers/utils/request-sql-guards.d.ts +8 -0
- package/dist/esm/fetchers/utils/request-sql-guards.d.ts.map +1 -0
- package/dist/esm/fetchers/utils/request-sql-guards.js +8 -0
- package/dist/esm/fetchers/utils/request-sql-guards.js.map +1 -0
- package/dist/esm/fetchers/utils/rest-api-response-cache.d.ts +40 -0
- package/dist/esm/fetchers/utils/rest-api-response-cache.d.ts.map +1 -0
- package/dist/esm/fetchers/utils/rest-api-response-cache.js +59 -0
- package/dist/esm/fetchers/utils/rest-api-response-cache.js.map +1 -0
- package/dist/esm/fetchers/utils/table-access-guard.d.ts +23 -0
- package/dist/esm/fetchers/utils/table-access-guard.d.ts.map +1 -0
- package/dist/esm/fetchers/utils/table-access-guard.js +29 -0
- package/dist/esm/fetchers/utils/table-access-guard.js.map +1 -0
- package/dist/esm/index.d.ts +5 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +55 -7
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/items-path.d.ts +10 -0
- package/dist/esm/items-path.d.ts.map +1 -0
- package/dist/esm/items-path.js +58 -0
- package/dist/esm/items-path.js.map +1 -0
- package/dist/esm/loading-state.d.ts +16 -1
- package/dist/esm/loading-state.d.ts.map +1 -1
- package/dist/esm/loading-state.js +69 -3
- package/dist/esm/loading-state.js.map +1 -1
- package/dist/esm/localized-columns.d.ts +56 -0
- package/dist/esm/localized-columns.d.ts.map +1 -0
- package/dist/esm/localized-columns.js +132 -0
- package/dist/esm/localized-columns.js.map +1 -0
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +141 -51
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/product-filter-fields.d.ts +87 -0
- package/dist/esm/product-filter-fields.d.ts.map +1 -0
- package/dist/esm/product-filter-fields.js +154 -0
- package/dist/esm/product-filter-fields.js.map +1 -0
- package/dist/esm/request-locale.d.ts +49 -0
- package/dist/esm/request-locale.d.ts.map +1 -0
- package/dist/esm/request-locale.js +98 -0
- package/dist/esm/request-locale.js.map +1 -0
- package/dist/esm/search-clear.d.ts +31 -0
- package/dist/esm/search-clear.d.ts.map +1 -0
- package/dist/esm/search-clear.js +74 -0
- package/dist/esm/search-clear.js.map +1 -0
- package/dist/esm/transformations/blog-adjacent-posts.d.ts +16 -0
- package/dist/esm/transformations/blog-adjacent-posts.d.ts.map +1 -0
- package/dist/esm/transformations/blog-adjacent-posts.js +21 -0
- package/dist/esm/transformations/blog-adjacent-posts.js.map +1 -0
- package/dist/esm/transformations/blog-comments.d.ts +30 -0
- package/dist/esm/transformations/blog-comments.d.ts.map +1 -0
- package/dist/esm/transformations/blog-comments.js +30 -0
- package/dist/esm/transformations/blog-comments.js.map +1 -0
- package/dist/esm/transformations/blog-post.d.ts +2 -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/ecommerce-product.d.ts +9 -1
- package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -1
- package/dist/esm/transformations/ecommerce-product.js +29 -2
- package/dist/esm/transformations/ecommerce-product.js.map +1 -1
- package/dist/esm/transformations/heading-anchors.d.ts +25 -0
- package/dist/esm/transformations/heading-anchors.d.ts.map +1 -0
- package/dist/esm/transformations/heading-anchors.js +25 -0
- package/dist/esm/transformations/heading-anchors.js.map +1 -0
- package/dist/esm/transformations/index.d.ts +61 -4
- package/dist/esm/transformations/index.d.ts.map +1 -1
- package/dist/esm/transformations/index.js +69 -19
- package/dist/esm/transformations/index.js.map +1 -1
- package/dist/esm/transformations/shared-utils.d.ts.map +1 -1
- package/dist/esm/transformations/shared-utils.js +1 -1
- package/dist/esm/transformations/shared-utils.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +11 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +60 -16
- package/dist/esm/utils.js.map +1 -1
- package/package.json +5 -5
- package/src/array-overlap-sql.ts +41 -0
- package/src/content-localization.ts +53 -0
- package/src/count-effect.ts +53 -2
- package/src/data-source-fetchers.ts +41 -5
- package/src/fetchers/airtable.ts +4 -2
- package/src/fetchers/clickhouse.ts +4 -2
- package/src/fetchers/firestore.ts +4 -2
- package/src/fetchers/javascript.ts +9 -1
- package/src/fetchers/mariadb.ts +4 -2
- package/src/fetchers/mongodb.ts +4 -2
- package/src/fetchers/mysql.ts +4 -2
- package/src/fetchers/postgresql.ts +53 -12
- package/src/fetchers/raw-query.ts +60 -5
- package/src/fetchers/redshift.ts +4 -2
- package/src/fetchers/rest-api.ts +27 -5
- package/src/fetchers/teleport.ts +85 -22
- package/src/fetchers/turso.ts +4 -2
- package/src/fetchers/utils/browser-row-policy.ts +212 -0
- package/src/fetchers/utils/request-sql-guards.ts +25 -0
- package/src/fetchers/utils/rest-api-response-cache.ts +188 -0
- package/src/fetchers/utils/table-access-guard.ts +39 -0
- package/src/index.ts +79 -11
- package/src/items-path.ts +74 -0
- package/src/loading-state.ts +134 -3
- package/src/localized-columns.ts +146 -0
- package/src/pagination-plugin.ts +206 -60
- package/src/product-filter-fields.ts +173 -0
- package/src/request-locale.ts +113 -0
- package/src/search-clear.ts +102 -0
- package/src/transformations/blog-adjacent-posts.ts +74 -0
- package/src/transformations/blog-comments.ts +132 -0
- package/src/transformations/blog-post.ts +38 -5
- package/src/transformations/ecommerce-product.ts +568 -5
- package/src/transformations/heading-anchors.ts +85 -0
- package/src/transformations/index.ts +191 -23
- package/src/transformations/shared-utils.ts +6 -0
- package/src/utils.ts +109 -19
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filtering and sorting a translatable column in the visitor's language.
|
|
3
|
+
*
|
|
4
|
+
* A translatable column of a platform table exists once per language:
|
|
5
|
+
* `slug` holds the main language and `es_slug` the Spanish copy (see
|
|
6
|
+
* `ContentLocalization`). The row transform resolves what a page DISPLAYS —
|
|
7
|
+
* a Spanish listing shows `es_name` and links to `es_slug` — but the SQL a
|
|
8
|
+
* fetch runs still names the base column, so without this file:
|
|
9
|
+
*
|
|
10
|
+
* - the details page a Spanish card links to (`/es/products/<es_slug>`)
|
|
11
|
+
* looks the row up with `slug = $1` and answers 404;
|
|
12
|
+
* - "sort by name" on the Spanish listing orders the Spanish names by
|
|
13
|
+
* their ENGLISH counterparts.
|
|
14
|
+
*
|
|
15
|
+
* The teleport fetcher (`fetchers/teleport.ts`) therefore embeds the helper
|
|
16
|
+
* emitted here:
|
|
17
|
+
*
|
|
18
|
+
* - equality on a translatable column matches the value in ANY language:
|
|
19
|
+
* `("slug" = $1 OR "es_slug" = $1)`. Deliberately every language, not the
|
|
20
|
+
* request's: the language switcher keeps the URL and changes the locale,
|
|
21
|
+
* so `/products/<es_slug>` (English page, Spanish slug) has to resolve as
|
|
22
|
+
* well as `/es/products/<slug>`. Only `=` (and the `in` it is normalised
|
|
23
|
+
* to) — a translatable column is never compared with `<`, and `!=` on one
|
|
24
|
+
* has no sensible cross-language reading;
|
|
25
|
+
* - ordering by a translatable column orders by the REQUEST's language,
|
|
26
|
+
* falling back to the base column exactly like the transform does:
|
|
27
|
+
* `COALESCE(NULLIF("es_name", ''), "name")`.
|
|
28
|
+
*
|
|
29
|
+
* Which columns take part is decided at GENERATION time from the table's
|
|
30
|
+
* schema and the project's languages — never by prefix-sniffing column names,
|
|
31
|
+
* which would mistake `og_title` for a translation. A copy the schema does not
|
|
32
|
+
* list (a language added before a column became translatable) is simply not
|
|
33
|
+
* referenced, so the SQL can only ever name columns that exist.
|
|
34
|
+
*/
|
|
35
|
+
|
|
36
|
+
import type { ContentLocalization } from './content-localization'
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Base column → `{ locale: copy column }`, for every translatable column of a
|
|
40
|
+
* table that has at least one per-language copy in the schema.
|
|
41
|
+
*/
|
|
42
|
+
export type LocalizedColumnMap = Record<string, Record<string, string>>
|
|
43
|
+
|
|
44
|
+
/** The only identifiers the generated SQL is allowed to quote — same rule as the search columns. */
|
|
45
|
+
const SQL_IDENTIFIER_PATTERN = /^[a-zA-Z_][a-zA-Z0-9_]*$/
|
|
46
|
+
|
|
47
|
+
/** The column holding `column` in `locale` — the editor's `getI18nColumnName`. */
|
|
48
|
+
const localizedColumnName = (locale: string, column: string): string => `${locale}_${column}`
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Pairs every column with the per-language copies the schema actually holds.
|
|
52
|
+
* Empty (no families) when the project has one language or the table has no
|
|
53
|
+
* translated column — the emitted helper is then inert.
|
|
54
|
+
*/
|
|
55
|
+
export const collectLocalizedColumns = (
|
|
56
|
+
columnNames: string[],
|
|
57
|
+
localization: ContentLocalization | undefined
|
|
58
|
+
): LocalizedColumnMap => {
|
|
59
|
+
const families: LocalizedColumnMap = {}
|
|
60
|
+
if (!localization || localization.secondaryLocales.length === 0) {
|
|
61
|
+
return families
|
|
62
|
+
}
|
|
63
|
+
const present = new Set(columnNames.filter((name) => SQL_IDENTIFIER_PATTERN.test(name)))
|
|
64
|
+
present.forEach((column) => {
|
|
65
|
+
localization.secondaryLocales.forEach((locale) => {
|
|
66
|
+
const copy = localizedColumnName(locale, column)
|
|
67
|
+
if (!present.has(copy)) {
|
|
68
|
+
return
|
|
69
|
+
}
|
|
70
|
+
if (!families[column]) {
|
|
71
|
+
families[column] = {}
|
|
72
|
+
}
|
|
73
|
+
families[column][locale] = copy
|
|
74
|
+
})
|
|
75
|
+
})
|
|
76
|
+
return families
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The `localizedEqualityClause` / `localizedSortFieldSql` helpers a fetcher
|
|
81
|
+
* embeds, with the column map baked in.
|
|
82
|
+
*
|
|
83
|
+
* Emitted as plain source with no backtick and no `${`, because the fetcher
|
|
84
|
+
* interpolates it into a template literal. Every identifier it quotes comes
|
|
85
|
+
* from the baked map, so a request can only ever name a column the schema had.
|
|
86
|
+
*/
|
|
87
|
+
export const generateLocalizedColumnsHelper = (families: LocalizedColumnMap): string => {
|
|
88
|
+
const lines = [
|
|
89
|
+
'// Per-language copies of the translatable columns, base column -> locale -> copy.',
|
|
90
|
+
'// Baked from the table schema and the project languages at generation time.',
|
|
91
|
+
`var LOCALIZED_COLUMNS = ${JSON.stringify(families)}`,
|
|
92
|
+
'',
|
|
93
|
+
'function quoteLocalizedColumn(column) {',
|
|
94
|
+
" return '\"' + column + '\"'",
|
|
95
|
+
'}',
|
|
96
|
+
'',
|
|
97
|
+
'// Equality on a translatable column matches the value in ANY language, so a',
|
|
98
|
+
'// localized slug resolves whichever locale the URL is under. Answers null',
|
|
99
|
+
'// for every other column and operand, leaving them to the ordinary branches.',
|
|
100
|
+
'function localizedEqualityClause(field, operand, value, pushParam) {',
|
|
101
|
+
' var copies = LOCALIZED_COLUMNS[field]',
|
|
102
|
+
" if (!copies || operand !== '=' || value === null || value === undefined) return null",
|
|
103
|
+
' // An empty set means "no filter", as it does in the ordinary array branch.',
|
|
104
|
+
' if (Array.isArray(value) && value.length === 0) return null',
|
|
105
|
+
' var columns = [field]',
|
|
106
|
+
' for (var locale in copies) {',
|
|
107
|
+
' if (Object.prototype.hasOwnProperty.call(copies, locale)) columns.push(copies[locale])',
|
|
108
|
+
' }',
|
|
109
|
+
' var param = Array.isArray(value) ? pushParam(value.map(String)) : pushParam(value)',
|
|
110
|
+
' var clauses = []',
|
|
111
|
+
' for (var i = 0; i < columns.length; i++) {',
|
|
112
|
+
' clauses.push(',
|
|
113
|
+
' Array.isArray(value)',
|
|
114
|
+
" ? quoteLocalizedColumn(columns[i]) + '::text = ANY(' + param + '::text[])'",
|
|
115
|
+
" : quoteLocalizedColumn(columns[i]) + ' = ' + param",
|
|
116
|
+
' )',
|
|
117
|
+
' }',
|
|
118
|
+
" return '(' + clauses.join(' OR ') + ')'",
|
|
119
|
+
'}',
|
|
120
|
+
'',
|
|
121
|
+
'// A translatable list (tags) and its per-language copies, for a filter that',
|
|
122
|
+
'// matches a value in ANY language (a localized tag link resolves under every',
|
|
123
|
+
'// locale, like a localized slug). Null for a column with no copies.',
|
|
124
|
+
'function localizedColumnList(field) {',
|
|
125
|
+
' var copies = LOCALIZED_COLUMNS[field]',
|
|
126
|
+
' if (!copies) return null',
|
|
127
|
+
' var columns = [quoteLocalizedColumn(field)]',
|
|
128
|
+
' for (var locale in copies) {',
|
|
129
|
+
' if (Object.prototype.hasOwnProperty.call(copies, locale)) columns.push(quoteLocalizedColumn(copies[locale]))',
|
|
130
|
+
' }',
|
|
131
|
+
' return columns',
|
|
132
|
+
'}',
|
|
133
|
+
'',
|
|
134
|
+
"// ORDER BY a translatable column in the request's language, falling back to",
|
|
135
|
+
'// the base column for a row with no translation — the same resolution the',
|
|
136
|
+
'// row transform applies to what is displayed. Null when the field or the',
|
|
137
|
+
'// locale has no copy, so the ordinary sort runs.',
|
|
138
|
+
'function localizedSortFieldSql(field, locale) {',
|
|
139
|
+
' var copies = LOCALIZED_COLUMNS[field]',
|
|
140
|
+
" var copy = copies && typeof locale === 'string' ? copies[locale] : null",
|
|
141
|
+
' if (!copy) return null',
|
|
142
|
+
" return 'COALESCE(NULLIF(' + quoteLocalizedColumn(copy) + \", ''), \" + quoteLocalizedColumn(field) + ')'",
|
|
143
|
+
'}',
|
|
144
|
+
]
|
|
145
|
+
return lines.join('\n')
|
|
146
|
+
}
|