@teleporthq/teleport-plugin-next-data-source 0.42.35 → 0.43.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__/ecommerce-product-out-of-stock.test.ts +112 -0
- package/__tests__/fetchers.test.ts +0 -42
- package/__tests__/filter-utils.test.ts +149 -0
- package/__tests__/mocks.ts +0 -12
- package/__tests__/utils.test.ts +0 -2
- package/dist/cjs/array-mapper-registry.d.ts +2 -0
- package/dist/cjs/array-mapper-registry.d.ts.map +1 -1
- package/dist/cjs/array-mapper-registry.js +9 -1
- package/dist/cjs/array-mapper-registry.js.map +1 -1
- package/dist/cjs/count-fetchers.d.ts +2 -2
- package/dist/cjs/count-fetchers.d.ts.map +1 -1
- package/dist/cjs/count-fetchers.js +5 -5
- package/dist/cjs/count-fetchers.js.map +1 -1
- package/dist/cjs/data-source-fetchers.d.ts +2 -1
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +11 -9
- package/dist/cjs/data-source-fetchers.js.map +1 -1
- package/dist/cjs/fetchers/airtable.d.ts.map +1 -1
- package/dist/cjs/fetchers/airtable.js +1 -1
- package/dist/cjs/fetchers/airtable.js.map +1 -1
- package/dist/cjs/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/cjs/fetchers/clickhouse.js +1 -1
- package/dist/cjs/fetchers/clickhouse.js.map +1 -1
- package/dist/cjs/fetchers/csv-file.js +1 -1
- package/dist/cjs/fetchers/csv-file.js.map +1 -1
- package/dist/cjs/fetchers/firestore.js +1 -1
- package/dist/cjs/fetchers/firestore.js.map +1 -1
- package/dist/cjs/fetchers/google-sheets.js +1 -1
- package/dist/cjs/fetchers/google-sheets.js.map +1 -1
- package/dist/cjs/fetchers/index.d.ts +2 -1
- package/dist/cjs/fetchers/index.d.ts.map +1 -1
- package/dist/cjs/fetchers/index.js +8 -5
- package/dist/cjs/fetchers/index.js.map +1 -1
- package/dist/cjs/fetchers/javascript.js +1 -1
- package/dist/cjs/fetchers/javascript.js.map +1 -1
- package/dist/cjs/fetchers/mariadb.d.ts.map +1 -1
- package/dist/cjs/fetchers/mariadb.js +3 -3
- package/dist/cjs/fetchers/mariadb.js.map +1 -1
- package/dist/cjs/fetchers/mongodb.js +1 -1
- package/dist/cjs/fetchers/mongodb.js.map +1 -1
- package/dist/cjs/fetchers/mysql.d.ts.map +1 -1
- package/dist/cjs/fetchers/mysql.js +2 -2
- package/dist/cjs/fetchers/mysql.js.map +1 -1
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -1
- package/dist/cjs/fetchers/postgresql.js +2 -2
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/raw-query.d.ts +18 -0
- package/dist/cjs/fetchers/raw-query.d.ts.map +1 -0
- package/dist/cjs/fetchers/raw-query.js +70 -0
- package/dist/cjs/fetchers/raw-query.js.map +1 -0
- package/dist/cjs/fetchers/redis.js +1 -1
- package/dist/cjs/fetchers/redis.js.map +1 -1
- package/dist/cjs/fetchers/redshift.d.ts.map +1 -1
- package/dist/cjs/fetchers/redshift.js +2 -2
- package/dist/cjs/fetchers/redshift.js.map +1 -1
- package/dist/cjs/fetchers/rest-api.js +1 -1
- package/dist/cjs/fetchers/rest-api.js.map +1 -1
- package/dist/cjs/fetchers/supabase.d.ts.map +1 -1
- package/dist/cjs/fetchers/supabase.js +62 -2
- package/dist/cjs/fetchers/supabase.js.map +1 -1
- package/dist/cjs/fetchers/teleport.d.ts +7 -0
- package/dist/cjs/fetchers/teleport.d.ts.map +1 -0
- package/dist/cjs/fetchers/teleport.js +63 -0
- package/dist/cjs/fetchers/teleport.js.map +1 -0
- package/dist/cjs/fetchers/turso.d.ts.map +1 -1
- package/dist/cjs/fetchers/turso.js +1 -1
- package/dist/cjs/fetchers/turso.js.map +1 -1
- package/dist/cjs/filter-utils.d.ts +13 -0
- package/dist/cjs/filter-utils.d.ts.map +1 -0
- package/dist/cjs/filter-utils.js +95 -0
- package/dist/cjs/filter-utils.js.map +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +112 -9
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +389 -128
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/sort-utils.d.ts +10 -0
- package/dist/cjs/sort-utils.d.ts.map +1 -0
- package/dist/cjs/sort-utils.js +141 -0
- package/dist/cjs/sort-utils.js.map +1 -0
- package/dist/cjs/transformations/blog-post.d.ts +7 -0
- package/dist/cjs/transformations/blog-post.d.ts.map +1 -0
- package/dist/cjs/transformations/blog-post.js +13 -0
- package/dist/cjs/transformations/blog-post.js.map +1 -0
- package/dist/cjs/transformations/ecommerce-product.d.ts +7 -0
- package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -0
- package/dist/cjs/transformations/ecommerce-product.js +13 -0
- package/dist/cjs/transformations/ecommerce-product.js.map +1 -0
- package/dist/cjs/transformations/index.d.ts +26 -0
- package/dist/cjs/transformations/index.d.ts.map +1 -0
- package/dist/cjs/transformations/index.js +81 -0
- package/dist/cjs/transformations/index.js.map +1 -0
- package/dist/cjs/transformations/shared-utils.d.ts +7 -0
- package/dist/cjs/transformations/shared-utils.d.ts.map +1 -0
- package/dist/cjs/transformations/shared-utils.js +13 -0
- package/dist/cjs/transformations/shared-utils.js.map +1 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +30 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +173 -10
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/array-mapper-registry.d.ts +2 -0
- package/dist/esm/array-mapper-registry.d.ts.map +1 -1
- package/dist/esm/array-mapper-registry.js +9 -1
- package/dist/esm/array-mapper-registry.js.map +1 -1
- package/dist/esm/count-fetchers.d.ts +2 -2
- package/dist/esm/count-fetchers.d.ts.map +1 -1
- package/dist/esm/count-fetchers.js +4 -4
- package/dist/esm/count-fetchers.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts +2 -1
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +10 -9
- package/dist/esm/data-source-fetchers.js.map +1 -1
- package/dist/esm/fetchers/airtable.d.ts.map +1 -1
- package/dist/esm/fetchers/airtable.js +1 -1
- package/dist/esm/fetchers/airtable.js.map +1 -1
- package/dist/esm/fetchers/clickhouse.d.ts.map +1 -1
- package/dist/esm/fetchers/clickhouse.js +1 -1
- package/dist/esm/fetchers/clickhouse.js.map +1 -1
- package/dist/esm/fetchers/csv-file.js +1 -1
- package/dist/esm/fetchers/csv-file.js.map +1 -1
- package/dist/esm/fetchers/firestore.js +1 -1
- package/dist/esm/fetchers/firestore.js.map +1 -1
- package/dist/esm/fetchers/google-sheets.js +1 -1
- package/dist/esm/fetchers/google-sheets.js.map +1 -1
- package/dist/esm/fetchers/index.d.ts +2 -1
- package/dist/esm/fetchers/index.d.ts.map +1 -1
- package/dist/esm/fetchers/index.js +2 -1
- package/dist/esm/fetchers/index.js.map +1 -1
- package/dist/esm/fetchers/javascript.js +1 -1
- package/dist/esm/fetchers/javascript.js.map +1 -1
- package/dist/esm/fetchers/mariadb.d.ts.map +1 -1
- package/dist/esm/fetchers/mariadb.js +4 -4
- package/dist/esm/fetchers/mariadb.js.map +1 -1
- package/dist/esm/fetchers/mongodb.js +1 -1
- package/dist/esm/fetchers/mongodb.js.map +1 -1
- package/dist/esm/fetchers/mysql.d.ts.map +1 -1
- package/dist/esm/fetchers/mysql.js +3 -3
- package/dist/esm/fetchers/mysql.js.map +1 -1
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -1
- package/dist/esm/fetchers/postgresql.js +3 -3
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/raw-query.d.ts +18 -0
- package/dist/esm/fetchers/raw-query.d.ts.map +1 -0
- package/dist/esm/fetchers/raw-query.js +65 -0
- package/dist/esm/fetchers/raw-query.js.map +1 -0
- package/dist/esm/fetchers/redis.js +1 -1
- package/dist/esm/fetchers/redis.js.map +1 -1
- package/dist/esm/fetchers/redshift.d.ts.map +1 -1
- package/dist/esm/fetchers/redshift.js +3 -3
- package/dist/esm/fetchers/redshift.js.map +1 -1
- package/dist/esm/fetchers/rest-api.js +1 -1
- package/dist/esm/fetchers/rest-api.js.map +1 -1
- package/dist/esm/fetchers/supabase.d.ts.map +1 -1
- package/dist/esm/fetchers/supabase.js +63 -3
- package/dist/esm/fetchers/supabase.js.map +1 -1
- package/dist/esm/fetchers/teleport.d.ts +7 -0
- package/dist/esm/fetchers/teleport.d.ts.map +1 -0
- package/dist/esm/fetchers/teleport.js +57 -0
- package/dist/esm/fetchers/teleport.js.map +1 -0
- package/dist/esm/fetchers/turso.d.ts.map +1 -1
- package/dist/esm/fetchers/turso.js +2 -2
- package/dist/esm/fetchers/turso.js.map +1 -1
- package/dist/esm/filter-utils.d.ts +13 -0
- package/dist/esm/filter-utils.d.ts.map +1 -0
- package/dist/esm/filter-utils.js +66 -0
- package/dist/esm/filter-utils.js.map +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +113 -10
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +389 -128
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/sort-utils.d.ts +10 -0
- package/dist/esm/sort-utils.d.ts.map +1 -0
- package/dist/esm/sort-utils.js +113 -0
- package/dist/esm/sort-utils.js.map +1 -0
- package/dist/esm/transformations/blog-post.d.ts +7 -0
- package/dist/esm/transformations/blog-post.d.ts.map +1 -0
- package/dist/esm/transformations/blog-post.js +9 -0
- package/dist/esm/transformations/blog-post.js.map +1 -0
- package/dist/esm/transformations/ecommerce-product.d.ts +7 -0
- package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -0
- package/dist/esm/transformations/ecommerce-product.js +9 -0
- package/dist/esm/transformations/ecommerce-product.js.map +1 -0
- package/dist/esm/transformations/index.d.ts +26 -0
- package/dist/esm/transformations/index.d.ts.map +1 -0
- package/dist/esm/transformations/index.js +74 -0
- package/dist/esm/transformations/index.js.map +1 -0
- package/dist/esm/transformations/shared-utils.d.ts +7 -0
- package/dist/esm/transformations/shared-utils.d.ts.map +1 -0
- package/dist/esm/transformations/shared-utils.js +9 -0
- package/dist/esm/transformations/shared-utils.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +30 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +170 -9
- package/dist/esm/utils.js.map +1 -1
- package/package.json +6 -5
- package/src/array-mapper-registry.ts +13 -0
- package/src/count-fetchers.ts +5 -5
- package/src/data-source-fetchers.ts +15 -11
- package/src/fetchers/airtable.ts +54 -8
- package/src/fetchers/clickhouse.ts +25 -19
- package/src/fetchers/csv-file.ts +2 -2
- package/src/fetchers/firestore.ts +2 -2
- package/src/fetchers/google-sheets.ts +2 -2
- package/src/fetchers/index.ts +6 -5
- package/src/fetchers/javascript.ts +2 -2
- package/src/fetchers/mariadb.ts +27 -12
- package/src/fetchers/mongodb.ts +2 -2
- package/src/fetchers/mysql.ts +27 -12
- package/src/fetchers/postgresql.ts +31 -18
- package/src/fetchers/raw-query.ts +178 -0
- package/src/fetchers/redis.ts +2 -2
- package/src/fetchers/redshift.ts +14 -10
- package/src/fetchers/rest-api.ts +2 -2
- package/src/fetchers/supabase.ts +97 -14
- package/src/fetchers/teleport.ts +485 -0
- package/src/fetchers/turso.ts +15 -7
- package/src/filter-utils.ts +111 -0
- package/src/index.ts +146 -6
- package/src/pagination-plugin.ts +547 -308
- package/src/sort-utils.ts +150 -0
- package/src/transformations/blog-post.ts +128 -0
- package/src/transformations/ecommerce-product.ts +173 -0
- package/src/transformations/index.ts +97 -0
- package/src/transformations/shared-utils.ts +271 -0
- package/src/utils.ts +227 -11
- package/dist/cjs/fetchers/static-collection.d.ts +0 -7
- package/dist/cjs/fetchers/static-collection.d.ts.map +0 -1
- package/dist/cjs/fetchers/static-collection.js +0 -25
- package/dist/cjs/fetchers/static-collection.js.map +0 -1
- package/dist/esm/fetchers/static-collection.d.ts +0 -7
- package/dist/esm/fetchers/static-collection.d.ts.map +0 -1
- package/dist/esm/fetchers/static-collection.js +0 -19
- package/dist/esm/fetchers/static-collection.js.map +0 -1
- package/src/fetchers/static-collection.ts +0 -231
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates JavaScript code for shared data transformation utilities.
|
|
3
|
+
* These are included in the generated data source fetcher files
|
|
4
|
+
* when the table requires blog post or e-commerce product transformations.
|
|
5
|
+
*/
|
|
6
|
+
export const generateSharedTransformationCode = (): string => {
|
|
7
|
+
return `
|
|
8
|
+
// ============================================================
|
|
9
|
+
// Shared Data Transformation Utilities
|
|
10
|
+
// ============================================================
|
|
11
|
+
|
|
12
|
+
var CURRENCY_SYMBOLS = {
|
|
13
|
+
USD: { symbol: '$', position: 'before' },
|
|
14
|
+
EUR: { symbol: '€', position: 'before' },
|
|
15
|
+
GBP: { symbol: '£', position: 'before' },
|
|
16
|
+
JPY: { symbol: '¥', position: 'before' },
|
|
17
|
+
CAD: { symbol: 'C$', position: 'before' },
|
|
18
|
+
AUD: { symbol: 'A$', position: 'before' },
|
|
19
|
+
CHF: { symbol: 'CHF', position: 'before' },
|
|
20
|
+
CNY: { symbol: '¥', position: 'before' },
|
|
21
|
+
INR: { symbol: '₹', position: 'before' },
|
|
22
|
+
BRL: { symbol: 'R$', position: 'before' },
|
|
23
|
+
MXN: { symbol: 'MX$', position: 'before' },
|
|
24
|
+
KRW: { symbol: '₩', position: 'before' },
|
|
25
|
+
SGD: { symbol: 'S$', position: 'before' },
|
|
26
|
+
HKD: { symbol: 'HK$', position: 'before' },
|
|
27
|
+
NOK: { symbol: 'kr', position: 'after' },
|
|
28
|
+
SEK: { symbol: 'kr', position: 'after' },
|
|
29
|
+
DKK: { symbol: 'kr', position: 'after' },
|
|
30
|
+
PLN: { symbol: 'zł', position: 'after' },
|
|
31
|
+
CZK: { symbol: 'Kč', position: 'after' },
|
|
32
|
+
HUF: { symbol: 'Ft', position: 'after' },
|
|
33
|
+
RON: { symbol: 'lei', position: 'after' },
|
|
34
|
+
TRY: { symbol: '₺', position: 'before' },
|
|
35
|
+
THB: { symbol: '฿', position: 'before' },
|
|
36
|
+
IDR: { symbol: 'Rp', position: 'before' },
|
|
37
|
+
PHP: { symbol: '₱', position: 'before' },
|
|
38
|
+
ZAR: { symbol: 'R', position: 'before' },
|
|
39
|
+
RUB: { symbol: '₽', position: 'after' },
|
|
40
|
+
NZD: { symbol: 'NZ$', position: 'before' },
|
|
41
|
+
TWD: { symbol: 'NT$', position: 'before' },
|
|
42
|
+
ILS: { symbol: '₪', position: 'before' },
|
|
43
|
+
AED: { symbol: 'د.إ', position: 'before' },
|
|
44
|
+
SAR: { symbol: '﷼', position: 'before' },
|
|
45
|
+
MYR: { symbol: 'RM', position: 'before' },
|
|
46
|
+
VND: { symbol: '₫', position: 'after' },
|
|
47
|
+
CLP: { symbol: '$', position: 'before' },
|
|
48
|
+
COP: { symbol: '$', position: 'before' },
|
|
49
|
+
ARS: { symbol: '$', position: 'before' },
|
|
50
|
+
PEN: { symbol: 'S/', position: 'before' },
|
|
51
|
+
UAH: { symbol: '₴', position: 'after' },
|
|
52
|
+
BGN: { symbol: 'лв', position: 'after' },
|
|
53
|
+
HRK: { symbol: 'kn', position: 'after' },
|
|
54
|
+
ISK: { symbol: 'kr', position: 'after' },
|
|
55
|
+
NGN: { symbol: '₦', position: 'before' },
|
|
56
|
+
KES: { symbol: 'KSh', position: 'before' },
|
|
57
|
+
EGP: { symbol: 'E£', position: 'before' },
|
|
58
|
+
PKR: { symbol: '₨', position: 'before' },
|
|
59
|
+
BDT: { symbol: '৳', position: 'before' },
|
|
60
|
+
LKR: { symbol: '₨', position: 'before' },
|
|
61
|
+
GHS: { symbol: 'GH₵', position: 'before' },
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function getCurrencyInfo(currencyCode) {
|
|
65
|
+
if (!currencyCode) return { symbol: '$', position: 'before' }
|
|
66
|
+
var upper = currencyCode.toUpperCase()
|
|
67
|
+
var entry = CURRENCY_SYMBOLS[upper]
|
|
68
|
+
return entry || { symbol: upper, position: 'before' }
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
function getCurrencySymbol(currencyCode) {
|
|
72
|
+
return getCurrencyInfo(currencyCode).symbol
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function normalizeTimestamp(value) {
|
|
76
|
+
if (value == null) return Date.now()
|
|
77
|
+
if (typeof value === 'number') {
|
|
78
|
+
if (isNaN(value)) return Date.now()
|
|
79
|
+
return value < 100000000000 ? value * 1000 : value
|
|
80
|
+
}
|
|
81
|
+
if (typeof value === 'string') {
|
|
82
|
+
var parsed = Date.parse(value)
|
|
83
|
+
return isNaN(parsed) ? Date.now() : parsed
|
|
84
|
+
}
|
|
85
|
+
return Date.now()
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function safeNumber(value, defaultValue) {
|
|
89
|
+
if (value == null) return defaultValue
|
|
90
|
+
var n = Number(value)
|
|
91
|
+
return isNaN(n) ? defaultValue : n
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function parseJsonArray(value) {
|
|
95
|
+
if (!value) return []
|
|
96
|
+
if (Array.isArray(value)) return value.filter(function(item) { return typeof item === 'string' })
|
|
97
|
+
if (typeof value === 'string') {
|
|
98
|
+
try {
|
|
99
|
+
var parsed = JSON.parse(value)
|
|
100
|
+
if (Array.isArray(parsed)) return parsed.filter(function(item) { return typeof item === 'string' })
|
|
101
|
+
return []
|
|
102
|
+
} catch (e) {
|
|
103
|
+
return value.split(',').map(function(s) { return s.trim() }).filter(Boolean)
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return []
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
function parseJsonObject(value) {
|
|
110
|
+
if (value == null) return {}
|
|
111
|
+
if (typeof value === 'object' && !Array.isArray(value)) return value
|
|
112
|
+
if (typeof value === 'string') {
|
|
113
|
+
try {
|
|
114
|
+
var parsed = JSON.parse(value)
|
|
115
|
+
if (parsed && typeof parsed === 'object' && !Array.isArray(parsed)) return parsed
|
|
116
|
+
return {}
|
|
117
|
+
} catch (e) {
|
|
118
|
+
return {}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return {}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
var HTML_ENTITY_MAP = {
|
|
125
|
+
'&': '&', '<': '<', '>': '>', '"': '"',
|
|
126
|
+
''': "'", ''': "'", ''': "'", ' ': ' ',
|
|
127
|
+
' ': ' ', '©': '©', '®': '®', '™': '™',
|
|
128
|
+
'…': '…', '—': '—', '–': '–',
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function decodeHtmlEntities(str) {
|
|
132
|
+
if (!str) return str
|
|
133
|
+
// Decode named and numeric entities
|
|
134
|
+
return str
|
|
135
|
+
.replace(/&(?:#x([0-9a-fA-F]+)|#([0-9]+)|([a-zA-Z]+));/g, function(match, hex, dec, named) {
|
|
136
|
+
if (hex) return String.fromCharCode(parseInt(hex, 16))
|
|
137
|
+
if (dec) return String.fromCharCode(parseInt(dec, 10))
|
|
138
|
+
var namedRef = '&' + named + ';'
|
|
139
|
+
return HTML_ENTITY_MAP[namedRef] || match
|
|
140
|
+
})
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function stripHtmlTags(html) {
|
|
144
|
+
if (!html || typeof html !== 'string') return ''
|
|
145
|
+
// Remove script and style blocks entirely (including content)
|
|
146
|
+
var cleaned = html
|
|
147
|
+
.replace(/<script[\\s\\S]*?<\\/script>/gi, ' ')
|
|
148
|
+
.replace(/<style[\\s\\S]*?<\\/style>/gi, ' ')
|
|
149
|
+
// Strip remaining tags
|
|
150
|
+
cleaned = cleaned.replace(/<[^>]*>/g, ' ')
|
|
151
|
+
// Decode HTML entities
|
|
152
|
+
cleaned = decodeHtmlEntities(cleaned)
|
|
153
|
+
// Collapse whitespace
|
|
154
|
+
return cleaned.replace(/\\s+/g, ' ').trim()
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
function coerceBoolean(value, defaultValue) {
|
|
158
|
+
if (value === true || value === 'true' || value === 1 || value === '1') return true
|
|
159
|
+
if (value === false || value === 'false' || value === 0 || value === '0') return false
|
|
160
|
+
return defaultValue
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
function pickFirst() {
|
|
164
|
+
for (var i = 0; i < arguments.length; i++) {
|
|
165
|
+
var val = arguments[i]
|
|
166
|
+
if (val !== undefined && val !== null) return val
|
|
167
|
+
}
|
|
168
|
+
return null
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
function resolveI18nField(record, snakeCol, camelCol, currentLang, mainLang) {
|
|
172
|
+
if (currentLang && mainLang && currentLang !== mainLang) {
|
|
173
|
+
// Try language-prefixed snake_case column first, then camelCase
|
|
174
|
+
var langSnakeKey = currentLang + '_' + snakeCol
|
|
175
|
+
if (record[langSnakeKey] !== undefined && record[langSnakeKey] !== null && record[langSnakeKey] !== '') {
|
|
176
|
+
return record[langSnakeKey]
|
|
177
|
+
}
|
|
178
|
+
if (snakeCol !== camelCol) {
|
|
179
|
+
var langCamelKey = currentLang + '_' + camelCol
|
|
180
|
+
if (record[langCamelKey] !== undefined && record[langCamelKey] !== null && record[langCamelKey] !== '') {
|
|
181
|
+
return record[langCamelKey]
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
if (record[snakeCol] !== undefined && record[snakeCol] !== null) return record[snakeCol]
|
|
186
|
+
if (snakeCol !== camelCol && record[camelCol] !== undefined && record[camelCol] !== null) return record[camelCol]
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Asset URL Resolution with TTL-based caching
|
|
191
|
+
var __assetUrlCache = {}
|
|
192
|
+
var __assetMapCache = null
|
|
193
|
+
var __assetMapTimestamp = 0
|
|
194
|
+
var ASSET_CACHE_TTL_MS = 5 * 60 * 1000 // 5 minutes
|
|
195
|
+
|
|
196
|
+
function isUrl(value) {
|
|
197
|
+
if (!value || typeof value !== 'string') return false
|
|
198
|
+
return value.startsWith('http://') || value.startsWith('https://') || value.startsWith('data:')
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
function resolveAssetUrl(value, assetMap) {
|
|
202
|
+
if (!value || typeof value !== 'string') return null
|
|
203
|
+
if (isUrl(value)) return value
|
|
204
|
+
// Also treat absolute paths (starting with /) as URLs
|
|
205
|
+
if (value.charAt(0) === '/') return value
|
|
206
|
+
if (__assetUrlCache[value]) return __assetUrlCache[value]
|
|
207
|
+
if (assetMap && assetMap[value]) {
|
|
208
|
+
var asset = assetMap[value]
|
|
209
|
+
var resolved = asset.remoteSrc || asset.imageSrc || asset.src || asset.url || value
|
|
210
|
+
__assetUrlCache[value] = resolved
|
|
211
|
+
return resolved
|
|
212
|
+
}
|
|
213
|
+
// Not found in asset map - return as-is (might already be a usable reference)
|
|
214
|
+
return value
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
function resolveAssetUrls(values, assetMap) {
|
|
218
|
+
if (!Array.isArray(values)) return []
|
|
219
|
+
return values
|
|
220
|
+
.map(function(v) { return resolveAssetUrl(v, assetMap) })
|
|
221
|
+
.filter(function(v) { return v != null && typeof v === 'string' })
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function deduplicateStrings(arr) {
|
|
225
|
+
var seen = {}
|
|
226
|
+
return arr.filter(function(v) {
|
|
227
|
+
if (!v || typeof v !== 'string' || seen[v]) return false
|
|
228
|
+
seen[v] = true
|
|
229
|
+
return true
|
|
230
|
+
})
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Fetches the asset map from the database if available, with TTL-based caching
|
|
234
|
+
async function getAssetMap(getClientFn) {
|
|
235
|
+
var now = Date.now()
|
|
236
|
+
if (__assetMapCache && (now - __assetMapTimestamp) < ASSET_CACHE_TTL_MS) {
|
|
237
|
+
return __assetMapCache
|
|
238
|
+
}
|
|
239
|
+
// Reset per-URL cache when asset map is refreshed
|
|
240
|
+
__assetUrlCache = {}
|
|
241
|
+
var map = {}
|
|
242
|
+
var client
|
|
243
|
+
try {
|
|
244
|
+
client = getClientFn()
|
|
245
|
+
await client.connect()
|
|
246
|
+
var result = await client.query('SELECT id, src, remote_src, image_src, url FROM teleport_assets')
|
|
247
|
+
if (result && result.rows) {
|
|
248
|
+
result.rows.forEach(function(row) {
|
|
249
|
+
map[row.id] = {
|
|
250
|
+
src: row.src || null,
|
|
251
|
+
remoteSrc: row.remote_src || null,
|
|
252
|
+
imageSrc: row.image_src || null,
|
|
253
|
+
url: row.url || null,
|
|
254
|
+
}
|
|
255
|
+
})
|
|
256
|
+
}
|
|
257
|
+
__assetMapCache = map
|
|
258
|
+
__assetMapTimestamp = now
|
|
259
|
+
} catch (e) {
|
|
260
|
+
// teleport_assets table may not exist - cache empty map with short TTL
|
|
261
|
+
__assetMapCache = map
|
|
262
|
+
__assetMapTimestamp = now
|
|
263
|
+
} finally {
|
|
264
|
+
if (client) {
|
|
265
|
+
try { await client.end() } catch (e) { /* ignore */ }
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
return map
|
|
269
|
+
}
|
|
270
|
+
`
|
|
271
|
+
}
|
package/src/utils.ts
CHANGED
|
@@ -15,6 +15,7 @@ import { generateDataSourceFetcherWithCore } from './data-source-fetchers'
|
|
|
15
15
|
|
|
16
16
|
const VALID_DATA_SOURCE_TYPES: DataSourceType[] = [
|
|
17
17
|
'rest-api',
|
|
18
|
+
'teleport',
|
|
18
19
|
'postgresql',
|
|
19
20
|
'mysql',
|
|
20
21
|
'mariadb',
|
|
@@ -31,7 +32,6 @@ const VALID_DATA_SOURCE_TYPES: DataSourceType[] = [
|
|
|
31
32
|
'javascript',
|
|
32
33
|
'google-sheets',
|
|
33
34
|
'csv-file',
|
|
34
|
-
'static-collection',
|
|
35
35
|
]
|
|
36
36
|
|
|
37
37
|
export const sanitizeFileName = (input: string): string => {
|
|
@@ -460,7 +460,7 @@ export default dataSourceModule.handler
|
|
|
460
460
|
}
|
|
461
461
|
|
|
462
462
|
export const isEmbeddedDataSource = (dataSourceType: string): boolean => {
|
|
463
|
-
return ['javascript', 'csv-file'
|
|
463
|
+
return ['javascript', 'csv-file'].includes(dataSourceType)
|
|
464
464
|
}
|
|
465
465
|
|
|
466
466
|
export const replaceSecretReference = (
|
|
@@ -510,6 +510,41 @@ export const replaceSecretReference = (
|
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
/**
|
|
514
|
+
* Emit runtime helpers that every SQL-based fetcher needs to safely
|
|
515
|
+
* apply the `{ query, queryColumns }` search contract:
|
|
516
|
+
*
|
|
517
|
+
* - `SEARCH_LIKE_ESCAPE_CHAR` — the char we register via `ESCAPE '|'`
|
|
518
|
+
* in LIKE / ILIKE expressions. `|` is not special in any SQL
|
|
519
|
+
* dialect's string-literal grammar, so the emitted SQL parses
|
|
520
|
+
* unambiguously across Postgres, MySQL (regardless of
|
|
521
|
+
* `NO_BACKSLASH_ESCAPES`), and SQLite.
|
|
522
|
+
*
|
|
523
|
+
* - `escapeLikePattern(term)` — prefixes `|` to `|`, `%`, `_` so a
|
|
524
|
+
* user typing `50%` matches a literal `%` rather than any-chars.
|
|
525
|
+
*
|
|
526
|
+
* - `sanitizeSearchIdentifier(name)` — validates column identifiers
|
|
527
|
+
* against `[A-Za-z_][A-Za-z0-9_]*` and throws on anything else. The
|
|
528
|
+
* caller is responsible for wrapping in the dialect's quote chars.
|
|
529
|
+
*
|
|
530
|
+
* Kept as a single snippet so every fetcher imports the exact same
|
|
531
|
+
* contract and the canvas preview (data-fetcher-worker /
|
|
532
|
+
* database-provider-worker) and the generated Next.js app emit
|
|
533
|
+
* byte-identical search SQL.
|
|
534
|
+
*/
|
|
535
|
+
export const generateSearchEscapeHelpersCode = (): string => {
|
|
536
|
+
return `const SEARCH_LIKE_ESCAPE_CHAR = '|'
|
|
537
|
+
const escapeLikePattern = (term) => {
|
|
538
|
+
return String(term == null ? '' : term).replace(/[|%_]/g, (m) => SEARCH_LIKE_ESCAPE_CHAR + m)
|
|
539
|
+
}
|
|
540
|
+
const sanitizeSearchIdentifier = (name) => {
|
|
541
|
+
if (typeof name !== 'string' || !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {
|
|
542
|
+
throw new Error('Invalid search column identifier: ' + String(name))
|
|
543
|
+
}
|
|
544
|
+
return name
|
|
545
|
+
}`
|
|
546
|
+
}
|
|
547
|
+
|
|
513
548
|
export const generateSafeJSONParseCode = (): string => {
|
|
514
549
|
return `const safeJSONParse = (value) => {
|
|
515
550
|
if (!value) return value
|
|
@@ -706,6 +741,147 @@ export const sanitizeIdentifier = (identifier: unknown): string => {
|
|
|
706
741
|
return identifier.replace(/[^a-zA-Z0-9_-]/g, '').substring(0, 64)
|
|
707
742
|
}
|
|
708
743
|
|
|
744
|
+
/**
|
|
745
|
+
* Checks if a dynamic param is resolvable from the route's dynamic attribute
|
|
746
|
+
* (i.e. available via context.params in getStaticProps/getServerSideProps).
|
|
747
|
+
*/
|
|
748
|
+
const isDynamicParamRouteResolvable = (
|
|
749
|
+
param: { type: string; content?: { referenceType?: string; id?: string } },
|
|
750
|
+
dynamicRouteAttr: string
|
|
751
|
+
): boolean => {
|
|
752
|
+
if (param.type !== 'dynamic') {
|
|
753
|
+
return false
|
|
754
|
+
}
|
|
755
|
+
return param.content?.referenceType === 'prop' && param.content?.id === dynamicRouteAttr
|
|
756
|
+
}
|
|
757
|
+
|
|
758
|
+
/**
|
|
759
|
+
* Checks if a filter destination (within a static filters array) is resolvable
|
|
760
|
+
* from the route's dynamic attribute.
|
|
761
|
+
*/
|
|
762
|
+
const isFilterDestinationRouteResolvable = (
|
|
763
|
+
destination: unknown,
|
|
764
|
+
dynamicRouteAttr: string
|
|
765
|
+
): boolean => {
|
|
766
|
+
if (!ASTUtils.isUIDLDynamicReference(destination)) {
|
|
767
|
+
return false
|
|
768
|
+
}
|
|
769
|
+
const content = (destination as { content: { referenceType: string; id: string } }).content
|
|
770
|
+
return content.referenceType === 'prop' && content.id === dynamicRouteAttr
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
/**
|
|
774
|
+
* Determines if any resource params have dynamic values that cannot be resolved
|
|
775
|
+
* server-side. Params whose dynamic references match the page's dynamicRouteAttribute
|
|
776
|
+
* can be resolved from context.params and are NOT considered unresolvable.
|
|
777
|
+
*/
|
|
778
|
+
// tslint:disable-next-line:no-any
|
|
779
|
+
export const hasUnresolvableDynamicParams = (
|
|
780
|
+
params: Record<string, any>,
|
|
781
|
+
dynamicRouteAttr?: string
|
|
782
|
+
): boolean => {
|
|
783
|
+
return Object.values(params).some((param: any) => {
|
|
784
|
+
if (param.type === 'expr') {
|
|
785
|
+
return true
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
if (param.type === 'dynamic') {
|
|
789
|
+
if (dynamicRouteAttr && isDynamicParamRouteResolvable(param, dynamicRouteAttr)) {
|
|
790
|
+
return false
|
|
791
|
+
}
|
|
792
|
+
return true
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
if (param.type === 'static' && Array.isArray(param.content)) {
|
|
796
|
+
const hasDynamicDestinations = param.content.some(
|
|
797
|
+
(item: any) =>
|
|
798
|
+
item && typeof item === 'object' && ASTUtils.isUIDLDynamicReference(item?.destination)
|
|
799
|
+
)
|
|
800
|
+
|
|
801
|
+
if (hasDynamicDestinations && dynamicRouteAttr) {
|
|
802
|
+
const allResolvable = param.content.every((item: any) => {
|
|
803
|
+
if (!item || typeof item !== 'object') {
|
|
804
|
+
return true
|
|
805
|
+
}
|
|
806
|
+
if (!ASTUtils.isUIDLDynamicReference(item.destination)) {
|
|
807
|
+
return true
|
|
808
|
+
}
|
|
809
|
+
return isFilterDestinationRouteResolvable(item.destination, dynamicRouteAttr)
|
|
810
|
+
})
|
|
811
|
+
return !allResolvable
|
|
812
|
+
}
|
|
813
|
+
|
|
814
|
+
return hasDynamicDestinations
|
|
815
|
+
}
|
|
816
|
+
|
|
817
|
+
return false
|
|
818
|
+
})
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
const isValidJSIdentifier = (name: string): boolean => /^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)
|
|
822
|
+
|
|
823
|
+
/**
|
|
824
|
+
* Generates context.params.attr or context.params['attr'] depending on
|
|
825
|
+
* whether the attribute name is a valid JS identifier.
|
|
826
|
+
*/
|
|
827
|
+
const createContextParamsAccess = (attr: string): types.MemberExpression => {
|
|
828
|
+
const contextParams = types.memberExpression(
|
|
829
|
+
types.identifier('context'),
|
|
830
|
+
types.identifier('params')
|
|
831
|
+
)
|
|
832
|
+
return isValidJSIdentifier(attr)
|
|
833
|
+
? types.memberExpression(contextParams, types.identifier(attr))
|
|
834
|
+
: types.memberExpression(contextParams, types.stringLiteral(attr), true)
|
|
835
|
+
}
|
|
836
|
+
|
|
837
|
+
/**
|
|
838
|
+
* Builds an AST ObjectExpression for a filter item, resolving dynamic destinations
|
|
839
|
+
* that reference the route attribute to context.params[attr].
|
|
840
|
+
*/
|
|
841
|
+
const buildFilterObjectAST = (
|
|
842
|
+
filterItem: Record<string, unknown>,
|
|
843
|
+
dynamicRouteAttr?: string
|
|
844
|
+
): types.ObjectExpression => {
|
|
845
|
+
const properties: types.ObjectProperty[] = []
|
|
846
|
+
|
|
847
|
+
for (const [key, value] of Object.entries(filterItem)) {
|
|
848
|
+
if (value === undefined) {
|
|
849
|
+
continue
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
if (key === 'destination' && dynamicRouteAttr && ASTUtils.isUIDLDynamicReference(value)) {
|
|
853
|
+
const content = (value as { content: { id: string } }).content
|
|
854
|
+
properties.push(
|
|
855
|
+
types.objectProperty(types.stringLiteral(key), createContextParamsAccess(content.id))
|
|
856
|
+
)
|
|
857
|
+
} else if (typeof value === 'string') {
|
|
858
|
+
properties.push(types.objectProperty(types.stringLiteral(key), types.stringLiteral(value)))
|
|
859
|
+
} else if (typeof value === 'number') {
|
|
860
|
+
properties.push(types.objectProperty(types.stringLiteral(key), types.numericLiteral(value)))
|
|
861
|
+
} else if (typeof value === 'boolean') {
|
|
862
|
+
properties.push(types.objectProperty(types.stringLiteral(key), types.booleanLiteral(value)))
|
|
863
|
+
} else if (value === null) {
|
|
864
|
+
properties.push(types.objectProperty(types.stringLiteral(key), types.nullLiteral()))
|
|
865
|
+
} else if (Array.isArray(value)) {
|
|
866
|
+
properties.push(
|
|
867
|
+
types.objectProperty(
|
|
868
|
+
types.stringLiteral(key),
|
|
869
|
+
types.arrayExpression(value.map((v) => ASTUtils.convertValueToLiteral(v)))
|
|
870
|
+
)
|
|
871
|
+
)
|
|
872
|
+
} else if (typeof value === 'object') {
|
|
873
|
+
properties.push(
|
|
874
|
+
types.objectProperty(
|
|
875
|
+
types.stringLiteral(key),
|
|
876
|
+
ASTUtils.objectToObjectExpression(value as Record<string, unknown>)
|
|
877
|
+
)
|
|
878
|
+
)
|
|
879
|
+
}
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
return types.objectExpression(properties)
|
|
883
|
+
}
|
|
884
|
+
|
|
709
885
|
// tslint:disable-next-line:no-any
|
|
710
886
|
export const extractDataSourceIntoGetStaticProps = (
|
|
711
887
|
node: UIDLDataSourceItemNode | UIDLDataSourceListNode,
|
|
@@ -714,7 +890,9 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
714
890
|
getStaticPropsChunk: any,
|
|
715
891
|
chunks: any[],
|
|
716
892
|
extractedResources: GeneratorOptions['extractedResources'],
|
|
717
|
-
dependencies: Record<string, any
|
|
893
|
+
dependencies: Record<string, any>,
|
|
894
|
+
dynamicRouteAttr?: string,
|
|
895
|
+
folderPath?: string[]
|
|
718
896
|
): { success: boolean; chunk?: any } => {
|
|
719
897
|
try {
|
|
720
898
|
// Validate node content
|
|
@@ -1061,9 +1239,16 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
1061
1239
|
|
|
1062
1240
|
// Add dependency for the fetcher
|
|
1063
1241
|
const fetcherImportName = StringUtils.dashCaseToCamelCase(fileName)
|
|
1242
|
+
// Calculate the correct relative path based on page folder depth.
|
|
1243
|
+
// folderPath contains subfolders within pages/ (e.g. ['admin'] for pages/admin/X.js).
|
|
1244
|
+
// We add 1 for the pages/ directory itself.
|
|
1245
|
+
// Pages at pages/X.js (folderPath=[]) need '../' (1 level up)
|
|
1246
|
+
// Pages at pages/admin/X.js (folderPath=['admin']) need '../../' (2 levels up)
|
|
1247
|
+
const depth = (folderPath ? folderPath.length : 0) + 1
|
|
1248
|
+
const relativePrefix = '../'.repeat(depth)
|
|
1064
1249
|
dependencies[fetcherImportName] = {
|
|
1065
1250
|
type: 'local',
|
|
1066
|
-
path:
|
|
1251
|
+
path: `${relativePrefix}utils/data-sources/${fileName}`,
|
|
1067
1252
|
}
|
|
1068
1253
|
|
|
1069
1254
|
// Build params object from resource params
|
|
@@ -1092,18 +1277,34 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
1092
1277
|
|
|
1093
1278
|
// For sorts, filters, and queryColumns, stringify the array for consistency with API handler
|
|
1094
1279
|
if (key === 'sorts' || key === 'filters' || key === 'queryColumns') {
|
|
1095
|
-
// For filters, filter out items with dynamic destinations (can't be resolved at build time)
|
|
1096
1280
|
let itemsToProcess = validItems
|
|
1097
1281
|
if (key === 'filters') {
|
|
1098
|
-
|
|
1099
|
-
|
|
1100
|
-
)
|
|
1101
|
-
|
|
1282
|
+
// Keep filter items that are either static or route-resolvable (via dynamicRouteAttr)
|
|
1283
|
+
// Filter out items with unresolvable dynamic destinations
|
|
1284
|
+
itemsToProcess = validItems.filter((item: any) => {
|
|
1285
|
+
if (!ASTUtils.isUIDLDynamicReference(item?.destination)) {
|
|
1286
|
+
return true
|
|
1287
|
+
}
|
|
1288
|
+
if (dynamicRouteAttr) {
|
|
1289
|
+
return isFilterDestinationRouteResolvable(item.destination, dynamicRouteAttr)
|
|
1290
|
+
}
|
|
1291
|
+
return false
|
|
1292
|
+
})
|
|
1102
1293
|
if (itemsToProcess.length === 0) {
|
|
1103
1294
|
return
|
|
1104
1295
|
}
|
|
1105
1296
|
}
|
|
1106
1297
|
|
|
1298
|
+
const hasRouteResolvableFilters =
|
|
1299
|
+
key === 'filters' &&
|
|
1300
|
+
dynamicRouteAttr &&
|
|
1301
|
+
itemsToProcess.some(
|
|
1302
|
+
(item: any) =>
|
|
1303
|
+
item &&
|
|
1304
|
+
typeof item === 'object' &&
|
|
1305
|
+
ASTUtils.isUIDLDynamicReference(item?.destination)
|
|
1306
|
+
)
|
|
1307
|
+
|
|
1107
1308
|
const arrayExpr = types.arrayExpression(
|
|
1108
1309
|
itemsToProcess.map((item: any) => {
|
|
1109
1310
|
if (typeof item === 'string') {
|
|
@@ -1116,6 +1317,12 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
1116
1317
|
return types.booleanLiteral(item)
|
|
1117
1318
|
}
|
|
1118
1319
|
if (typeof item === 'object' && item !== null) {
|
|
1320
|
+
if (
|
|
1321
|
+
hasRouteResolvableFilters &&
|
|
1322
|
+
ASTUtils.isUIDLDynamicReference(item?.destination)
|
|
1323
|
+
) {
|
|
1324
|
+
return buildFilterObjectAST(item, dynamicRouteAttr)
|
|
1325
|
+
}
|
|
1119
1326
|
return ASTUtils.objectToObjectExpression(item)
|
|
1120
1327
|
}
|
|
1121
1328
|
return types.nullLiteral()
|
|
@@ -1159,9 +1366,18 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
1159
1366
|
}
|
|
1160
1367
|
|
|
1161
1368
|
paramsProperties.push(types.objectProperty(types.stringLiteral(key), astValue))
|
|
1369
|
+
} else if (
|
|
1370
|
+
value.type === 'dynamic' &&
|
|
1371
|
+
dynamicRouteAttr &&
|
|
1372
|
+
isDynamicParamRouteResolvable(value, dynamicRouteAttr)
|
|
1373
|
+
) {
|
|
1374
|
+
paramsProperties.push(
|
|
1375
|
+
types.objectProperty(
|
|
1376
|
+
types.stringLiteral(key),
|
|
1377
|
+
createContextParamsAccess(value.content.id)
|
|
1378
|
+
)
|
|
1379
|
+
)
|
|
1162
1380
|
}
|
|
1163
|
-
// Note: We don't handle 'expr' or 'dynamic' params in getStaticProps
|
|
1164
|
-
// as those should be detected by hasResourceDynamicParams check earlier
|
|
1165
1381
|
})
|
|
1166
1382
|
|
|
1167
1383
|
const fetchCallExpression = types.callExpression(
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const validateStaticCollectionConfig: (config: Record<string, unknown>) => {
|
|
2
|
-
isValid: boolean;
|
|
3
|
-
error?: string;
|
|
4
|
-
};
|
|
5
|
-
export declare const generateStaticCollectionFetcher: (config: Record<string, unknown>) => string;
|
|
6
|
-
export declare const generateStaticCollectionCountFetcher: (_config: any) => string;
|
|
7
|
-
//# sourceMappingURL=static-collection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-collection.d.ts","sourceRoot":"","sources":["../../../src/fetchers/static-collection.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,8BAA8B,WACjC,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAUpC,CAAA;AAMD,eAAO,MAAM,+BAA+B,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MA4JjF,CAAA;AAGD,eAAO,MAAM,oCAAoC,YAAa,GAAG,KAAG,MA+CnE,CAAA"}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.generateStaticCollectionCountFetcher = exports.generateStaticCollectionFetcher = exports.validateStaticCollectionConfig = void 0;
|
|
4
|
-
var utils_1 = require("../utils");
|
|
5
|
-
var validateStaticCollectionConfig = function (config) {
|
|
6
|
-
if (!config || typeof config !== 'object') {
|
|
7
|
-
return { isValid: false, error: 'Config must be a valid object' };
|
|
8
|
-
}
|
|
9
|
-
if (!config.data || !Array.isArray(config.data)) {
|
|
10
|
-
return { isValid: false, error: 'Data must be an array' };
|
|
11
|
-
}
|
|
12
|
-
return { isValid: true };
|
|
13
|
-
};
|
|
14
|
-
exports.validateStaticCollectionConfig = validateStaticCollectionConfig;
|
|
15
|
-
var generateStaticCollectionFetcher = function (config) {
|
|
16
|
-
var staticConfig = config;
|
|
17
|
-
return "const data = ".concat(JSON.stringify(staticConfig.data || []), "\n\n").concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, utils_1.generateSortFilterHelperCode)(), "\n\nexport default async function handler(req, res) {\n try {\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset: offsetParam } = req.query\n \n let filteredData = [...data]\n \n if (query) {\n const searchQuery = query.toLowerCase()\n \n if (queryColumns) {\n const columns = safeJSONParse(queryColumns)\n filteredData = filteredData.filter((item) => {\n return columns.some((col) => {\n const value = getNestedValue(item, col)\n return value && String(value).toLowerCase().includes(searchQuery)\n })\n })\n } else {\n filteredData = filteredData.filter((item) => {\n try {\n const stringified = JSON.stringify(item).toLowerCase()\n return stringified.includes(searchQuery)\n } catch {\n return false\n }\n })\n }\n }\n \n if (filters) {\n const parsedFilters = safeJSONParse(filters)\n \n if (Array.isArray(parsedFilters)) {\n filteredData = filteredData.filter((item) => {\n return parsedFilters.every((filter) => {\n if (!filter.source || filter.destination === undefined) return true\n \n const field = filter.source\n const value = getNestedValue(item, field)\n const target = filter.destination\n const operand = filter.operand || '='\n \n if (Array.isArray(target)) {\n if (operand === '!=') {\n return !target.includes(value)\n }\n return target.includes(value)\n }\n \n return compareValues(value, target, operand)\n })\n })\n } else {\n filteredData = filteredData.filter((item) => {\n return Object.entries(parsedFilters).every(([key, value]) => {\n const itemValue = getNestedValue(item, key)\n if (Array.isArray(value)) {\n return value.includes(itemValue)\n }\n return compareValues(itemValue, value, '=')\n })\n })\n }\n }\n \n if (sorts) {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n filteredData.sort((a, b) => {\n for (const sort of parsedSorts) {\n if (!sort.field) continue\n const aVal = getNestedValue(a, sort.field)\n const bVal = getNestedValue(b, sort.field)\n const sortOrderValue = sort.order?.toLowerCase() === 'desc' ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n if (comparison !== 0) return comparison * sortOrderValue\n }\n return 0\n })\n }\n } else if (sortBy) {\n filteredData.sort((a, b) => {\n const aVal = getNestedValue(a, sortBy)\n const bVal = getNestedValue(b, sortBy)\n const sortOrderValue = sortOrder?.toLowerCase() === 'desc' ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n return comparison * sortOrderValue\n })\n }\n \n const limitValue = limit || perPage\n const offsetValue = offsetParam !== undefined ? parseInt(offsetParam) : (page && perPage ? (parseInt(page) - 1) * parseInt(perPage) : 0)\n \n if (limitValue) {\n filteredData = filteredData.slice(offsetValue, offsetValue + parseInt(limitValue))\n }\n \n const safeData = JSON.parse(JSON.stringify(filteredData, dateReplacer))\n \n return res.status(200).json({\n success: true,\n data: safeData,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Static collection fetch error:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to fetch data',\n timestamp: Date.now()\n })\n }\n}\n");
|
|
18
|
-
};
|
|
19
|
-
exports.generateStaticCollectionFetcher = generateStaticCollectionFetcher;
|
|
20
|
-
// tslint:disable-next-line:variable-name
|
|
21
|
-
var generateStaticCollectionCountFetcher = function (_config) {
|
|
22
|
-
return "\nasync function getCount(req, res) {\n try {\n const { query, queryColumns, filters } = req.query\n const fakeReq = { query: { query, queryColumns, filters }, method: 'GET' }\n let result = null\n let statusCode = 200\n \n const fakeRes = {\n status: (code) => {\n statusCode = code\n return fakeRes\n },\n json: (data) => {\n result = data\n return fakeRes\n },\n }\n \n await handler(fakeReq, fakeRes)\n \n if (statusCode !== 200 || !result || !result.success) {\n return res.status(500).json({\n success: false,\n error: 'Failed to get data for counting',\n timestamp: Date.now()\n })\n }\n \n const count = Array.isArray(result.data) ? result.data.length : 0\n \n return res.status(200).json({\n success: true,\n count: count,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Error getting count:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to get count',\n timestamp: Date.now()\n })\n }\n}\n";
|
|
23
|
-
};
|
|
24
|
-
exports.generateStaticCollectionCountFetcher = generateStaticCollectionCountFetcher;
|
|
25
|
-
//# sourceMappingURL=static-collection.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-collection.js","sourceRoot":"","sources":["../../../src/fetchers/static-collection.ts"],"names":[],"mappings":";;;AAAA,kCAIiB;AAEV,IAAM,8BAA8B,GAAG,UAC5C,MAA+B;IAE/B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAA;KAClE;IAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;QAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,uBAAuB,EAAE,CAAA;KAC1D;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC,CAAA;AAZY,QAAA,8BAA8B,kCAY1C;AAMM,IAAM,+BAA+B,GAAG,UAAC,MAA+B;IAC7E,IAAM,YAAY,GAAG,MAAgC,CAAA;IACrD,OAAO,uBAAgB,IAAI,CAAC,SAAS,CAAC,YAAY,CAAC,IAAI,IAAI,EAAE,CAAC,iBAE9D,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,oCAA4B,GAAE,ypKAmJ/B,CAAA;AACD,CAAC,CAAA;AA5JY,QAAA,+BAA+B,mCA4J3C;AAED,yCAAyC;AAClC,IAAM,oCAAoC,GAAG,UAAC,OAAY;IAC/D,OAAO,knCA6CR,CAAA;AACD,CAAC,CAAA;AA/CY,QAAA,oCAAoC,wCA+ChD"}
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
export declare const validateStaticCollectionConfig: (config: Record<string, unknown>) => {
|
|
2
|
-
isValid: boolean;
|
|
3
|
-
error?: string;
|
|
4
|
-
};
|
|
5
|
-
export declare const generateStaticCollectionFetcher: (config: Record<string, unknown>) => string;
|
|
6
|
-
export declare const generateStaticCollectionCountFetcher: (_config: any) => string;
|
|
7
|
-
//# sourceMappingURL=static-collection.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"static-collection.d.ts","sourceRoot":"","sources":["../../../src/fetchers/static-collection.ts"],"names":[],"mappings":"AAMA,eAAO,MAAM,8BAA8B,WACjC,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAUpC,CAAA;AAMD,eAAO,MAAM,+BAA+B,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MA4JjF,CAAA;AAGD,eAAO,MAAM,oCAAoC,YAAa,GAAG,KAAG,MA+CnE,CAAA"}
|