@teleporthq/teleport-plugin-next-data-source 0.42.7 → 0.42.9
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__/fetchers.test.ts +2 -2
- package/dist/cjs/fetchers/airtable.d.ts.map +1 -1
- package/dist/cjs/fetchers/airtable.js +2 -2
- 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.d.ts.map +1 -1
- package/dist/cjs/fetchers/csv-file.js +2 -1
- package/dist/cjs/fetchers/csv-file.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/google-sheets.d.ts.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/javascript.d.ts.map +1 -1
- package/dist/cjs/fetchers/javascript.js +2 -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 +9 -3
- 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 +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 +4 -4
- package/dist/cjs/fetchers/postgresql.js.map +1 -1
- package/dist/cjs/fetchers/redis.d.ts.map +1 -1
- 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 +3 -3
- 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 +3 -2
- package/dist/cjs/fetchers/rest-api.js.map +1 -1
- package/dist/cjs/fetchers/static-collection.d.ts.map +1 -1
- package/dist/cjs/fetchers/static-collection.js +2 -1
- package/dist/cjs/fetchers/static-collection.js.map +1 -1
- package/dist/cjs/fetchers/supabase.d.ts.map +1 -1
- package/dist/cjs/fetchers/supabase.js +1 -1
- package/dist/cjs/fetchers/supabase.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/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +1 -0
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +5 -1
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/fetchers/airtable.d.ts.map +1 -1
- package/dist/esm/fetchers/airtable.js +3 -3
- 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 +2 -2
- package/dist/esm/fetchers/clickhouse.js.map +1 -1
- package/dist/esm/fetchers/csv-file.d.ts.map +1 -1
- package/dist/esm/fetchers/csv-file.js +2 -1
- package/dist/esm/fetchers/csv-file.js.map +1 -1
- package/dist/esm/fetchers/firestore.d.ts.map +1 -1
- package/dist/esm/fetchers/firestore.js +2 -2
- package/dist/esm/fetchers/firestore.js.map +1 -1
- package/dist/esm/fetchers/google-sheets.d.ts.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/javascript.d.ts.map +1 -1
- package/dist/esm/fetchers/javascript.js +2 -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 +10 -4
- 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 +2 -2
- 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 +5 -5
- package/dist/esm/fetchers/postgresql.js.map +1 -1
- package/dist/esm/fetchers/redis.d.ts.map +1 -1
- package/dist/esm/fetchers/redis.js +2 -2
- 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 +4 -4
- 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 +3 -2
- package/dist/esm/fetchers/rest-api.js.map +1 -1
- package/dist/esm/fetchers/static-collection.d.ts.map +1 -1
- package/dist/esm/fetchers/static-collection.js +2 -1
- package/dist/esm/fetchers/static-collection.js.map +1 -1
- package/dist/esm/fetchers/supabase.d.ts.map +1 -1
- package/dist/esm/fetchers/supabase.js +2 -2
- package/dist/esm/fetchers/supabase.js.map +1 -1
- 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/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +1 -0
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +3 -0
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/fetchers/airtable.ts +4 -2
- package/src/fetchers/clickhouse.ts +4 -2
- package/src/fetchers/csv-file.ts +5 -1
- package/src/fetchers/firestore.ts +4 -2
- package/src/fetchers/google-sheets.ts +109 -9
- package/src/fetchers/javascript.ts +6 -2
- package/src/fetchers/mariadb.ts +51 -10
- package/src/fetchers/mongodb.ts +9 -3
- package/src/fetchers/mysql.ts +28 -15
- package/src/fetchers/postgresql.ts +33 -18
- package/src/fetchers/redis.ts +4 -2
- package/src/fetchers/redshift.ts +21 -15
- package/src/fetchers/rest-api.ts +5 -1
- package/src/fetchers/static-collection.ts +5 -1
- package/src/fetchers/supabase.ts +4 -2
- package/src/fetchers/turso.ts +9 -3
- package/src/utils.ts +30 -0
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { generateDateFormatterCode } from '../utils'
|
|
2
|
+
|
|
1
3
|
export const validateJavaScriptConfig = (
|
|
2
4
|
config: Record<string, unknown>
|
|
3
5
|
): { isValid: boolean; error?: string } => {
|
|
@@ -35,7 +37,9 @@ interface JavaScriptConfig {
|
|
|
35
37
|
|
|
36
38
|
export const generateJavaScriptFetcher = (config: Record<string, unknown>): string => {
|
|
37
39
|
const jsConfig = config as JavaScriptConfig
|
|
38
|
-
return
|
|
40
|
+
return `${generateDateFormatterCode()}
|
|
41
|
+
|
|
42
|
+
export default async function handler(req, res) {
|
|
39
43
|
try {
|
|
40
44
|
const { limit, offset, page, perPage, query, queryColumns, sortBy, sortOrder, filters } = req.query
|
|
41
45
|
|
|
@@ -115,7 +119,7 @@ export const generateJavaScriptFetcher = (config: Record<string, unknown>): stri
|
|
|
115
119
|
}
|
|
116
120
|
}
|
|
117
121
|
|
|
118
|
-
const safeData = JSON.parse(JSON.stringify(data))
|
|
122
|
+
const safeData = JSON.parse(JSON.stringify(data, dateReplacer))
|
|
119
123
|
|
|
120
124
|
return res.status(200).json({
|
|
121
125
|
success: true,
|
package/src/fetchers/mariadb.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
interface MariaDBConfig {
|
|
4
4
|
host?: string
|
|
@@ -20,10 +20,12 @@ export const generateMariaDBFetcher = (
|
|
|
20
20
|
|
|
21
21
|
return `import mariadb from 'mariadb'
|
|
22
22
|
|
|
23
|
+
${generateDateFormatterCode()}
|
|
24
|
+
|
|
23
25
|
export default async function handler(req, res) {
|
|
24
|
-
let
|
|
26
|
+
let connection = null
|
|
25
27
|
try {
|
|
26
|
-
|
|
28
|
+
connection = await mariadb.createConnection({
|
|
27
29
|
host: ${JSON.stringify(mariaConfig.host)},
|
|
28
30
|
port: ${mariaConfig.port || 3306},
|
|
29
31
|
user: ${JSON.stringify(mariaConfig.user)},
|
|
@@ -52,7 +54,6 @@ export default async function handler(req, res) {
|
|
|
52
54
|
}
|
|
53
55
|
})
|
|
54
56
|
|
|
55
|
-
const connection = await pool.getConnection()
|
|
56
57
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset } = req.query
|
|
57
58
|
|
|
58
59
|
const conditions = []
|
|
@@ -127,8 +128,7 @@ export default async function handler(req, res) {
|
|
|
127
128
|
const plainRows = rowArray.map((row) =>
|
|
128
129
|
row && typeof row.toJSON === 'function' ? row.toJSON() : row
|
|
129
130
|
)
|
|
130
|
-
const safeData = JSON.parse(JSON.stringify(plainRows))
|
|
131
|
-
connection.release()
|
|
131
|
+
const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))
|
|
132
132
|
|
|
133
133
|
return res.status(200).json({
|
|
134
134
|
success: true,
|
|
@@ -143,8 +143,12 @@ export default async function handler(req, res) {
|
|
|
143
143
|
timestamp: Date.now()
|
|
144
144
|
})
|
|
145
145
|
} finally {
|
|
146
|
-
if (
|
|
147
|
-
|
|
146
|
+
if (connection) {
|
|
147
|
+
try {
|
|
148
|
+
await connection.end()
|
|
149
|
+
} catch (error) {
|
|
150
|
+
console.error('Error closing MariaDB connection:', error)
|
|
151
|
+
}
|
|
148
152
|
}
|
|
149
153
|
}
|
|
150
154
|
}
|
|
@@ -160,9 +164,38 @@ export const generateMariaDBCountFetcher = (
|
|
|
160
164
|
|
|
161
165
|
return `
|
|
162
166
|
async function getCount(req, res) {
|
|
163
|
-
|
|
167
|
+
let connection = null
|
|
164
168
|
|
|
165
169
|
try {
|
|
170
|
+
connection = await mariadb.createConnection({
|
|
171
|
+
host: ${JSON.stringify(mariaConfig.host)},
|
|
172
|
+
port: ${mariaConfig.port || 3306},
|
|
173
|
+
user: ${JSON.stringify(mariaConfig.user)},
|
|
174
|
+
password: ${replaceSecretReference(mariaConfig.password)},
|
|
175
|
+
database: ${JSON.stringify(mariaConfig.database)},
|
|
176
|
+
ssl: ${mariaConfig.ssl || false}${
|
|
177
|
+
mariaConfig.sslConfig
|
|
178
|
+
? `,
|
|
179
|
+
sslConfig: {
|
|
180
|
+
${
|
|
181
|
+
mariaConfig.sslConfig.ca ? `ca: ${replaceSecretReference(mariaConfig.sslConfig.ca)},` : ''
|
|
182
|
+
}
|
|
183
|
+
${
|
|
184
|
+
mariaConfig.sslConfig.cert
|
|
185
|
+
? `cert: ${replaceSecretReference(mariaConfig.sslConfig.cert)},`
|
|
186
|
+
: ''
|
|
187
|
+
}
|
|
188
|
+
${
|
|
189
|
+
mariaConfig.sslConfig.key
|
|
190
|
+
? `key: ${replaceSecretReference(mariaConfig.sslConfig.key)},`
|
|
191
|
+
: ''
|
|
192
|
+
}
|
|
193
|
+
rejectUnauthorized: ${mariaConfig.sslConfig.rejectUnauthorized !== false}
|
|
194
|
+
}`
|
|
195
|
+
: ''
|
|
196
|
+
}
|
|
197
|
+
})
|
|
198
|
+
|
|
166
199
|
const { query, queryColumns, filters } = req.query
|
|
167
200
|
const conditions = []
|
|
168
201
|
const queryParams = []
|
|
@@ -209,7 +242,7 @@ async function getCount(req, res) {
|
|
|
209
242
|
countSql += \` WHERE \${conditions.join(' AND ')}\`
|
|
210
243
|
}
|
|
211
244
|
|
|
212
|
-
const
|
|
245
|
+
const rows = await connection.query(countSql, queryParams)
|
|
213
246
|
const count = rows[0].count
|
|
214
247
|
|
|
215
248
|
return res.status(200).json({
|
|
@@ -224,6 +257,14 @@ async function getCount(req, res) {
|
|
|
224
257
|
error: error.message || 'Failed to get count',
|
|
225
258
|
timestamp: Date.now()
|
|
226
259
|
})
|
|
260
|
+
} finally {
|
|
261
|
+
if (connection) {
|
|
262
|
+
try {
|
|
263
|
+
await connection.end()
|
|
264
|
+
} catch (error) {
|
|
265
|
+
console.error('Error closing MariaDB connection:', error)
|
|
266
|
+
}
|
|
267
|
+
}
|
|
227
268
|
}
|
|
228
269
|
}
|
|
229
270
|
`
|
package/src/fetchers/mongodb.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
export const validateMongoDBConfig = (
|
|
4
4
|
config: Record<string, unknown>
|
|
@@ -67,6 +67,8 @@ export const generateMongoDBFetcher = (
|
|
|
67
67
|
|
|
68
68
|
return `import { MongoClient, ObjectId } from 'mongodb'
|
|
69
69
|
|
|
70
|
+
${generateDateFormatterCode()}
|
|
71
|
+
|
|
70
72
|
export default async function handler(req, res) {
|
|
71
73
|
let client = null
|
|
72
74
|
try {
|
|
@@ -151,7 +153,7 @@ export default async function handler(req, res) {
|
|
|
151
153
|
}
|
|
152
154
|
|
|
153
155
|
const documents = await cursor.toArray()
|
|
154
|
-
const safeData = JSON.parse(JSON.stringify(documents))
|
|
156
|
+
const safeData = JSON.parse(JSON.stringify(documents, dateReplacer))
|
|
155
157
|
|
|
156
158
|
return res.status(200).json({
|
|
157
159
|
success: true,
|
|
@@ -167,7 +169,11 @@ export default async function handler(req, res) {
|
|
|
167
169
|
})
|
|
168
170
|
} finally {
|
|
169
171
|
if (client) {
|
|
170
|
-
|
|
172
|
+
try {
|
|
173
|
+
await client.close()
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error('Error closing MongoDB client:', error)
|
|
176
|
+
}
|
|
171
177
|
}
|
|
172
178
|
}
|
|
173
179
|
}
|
package/src/fetchers/mysql.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
interface MySQLConfig {
|
|
4
4
|
host?: string
|
|
@@ -46,12 +46,8 @@ export const generateMySQLFetcher = (
|
|
|
46
46
|
|
|
47
47
|
return `import mysql from 'mysql2/promise'
|
|
48
48
|
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
const getPool = () => {
|
|
52
|
-
if (pool) return pool
|
|
53
|
-
|
|
54
|
-
pool = mysql.createPool({
|
|
49
|
+
const getConnection = () => {
|
|
50
|
+
return mysql.createConnection({
|
|
55
51
|
host: ${JSON.stringify(mysqlConfig.host)},
|
|
56
52
|
port: ${mysqlConfig.port || 3306},
|
|
57
53
|
user: ${resolvedUser !== null ? JSON.stringify(resolvedUser) : 'undefined'},
|
|
@@ -59,13 +55,14 @@ const getPool = () => {
|
|
|
59
55
|
database: ${JSON.stringify(mysqlConfig.database)},
|
|
60
56
|
ssl: ${sslConfigString}
|
|
61
57
|
})
|
|
62
|
-
|
|
63
|
-
return pool
|
|
64
58
|
}
|
|
65
59
|
|
|
60
|
+
${generateDateFormatterCode()}
|
|
61
|
+
|
|
66
62
|
export default async function handler(req, res) {
|
|
63
|
+
const connection = await getConnection()
|
|
64
|
+
|
|
67
65
|
try {
|
|
68
|
-
const pool = getPool()
|
|
69
66
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset } = req.query
|
|
70
67
|
|
|
71
68
|
const conditions = []
|
|
@@ -80,7 +77,7 @@ export default async function handler(req, res) {
|
|
|
80
77
|
} else {
|
|
81
78
|
// Fallback: Get all columns from information_schema
|
|
82
79
|
try {
|
|
83
|
-
const [schemaRows] = await
|
|
80
|
+
const [schemaRows] = await connection.query(
|
|
84
81
|
\`SELECT COLUMN_NAME FROM information_schema.COLUMNS
|
|
85
82
|
WHERE TABLE_SCHEMA = ? AND TABLE_NAME = ?
|
|
86
83
|
ORDER BY ORDINAL_POSITION\`,
|
|
@@ -135,12 +132,12 @@ export default async function handler(req, res) {
|
|
|
135
132
|
sql += \` OFFSET \${offsetValue}\`
|
|
136
133
|
}
|
|
137
134
|
|
|
138
|
-
const [rows] = await
|
|
135
|
+
const [rows] = await connection.query(sql, queryParams)
|
|
139
136
|
const rowArray = Array.isArray(rows) ? rows : []
|
|
140
137
|
const plainRows = rowArray.map((row) =>
|
|
141
138
|
row && typeof row.toJSON === 'function' ? row.toJSON() : row
|
|
142
139
|
)
|
|
143
|
-
const safeData = JSON.parse(JSON.stringify(plainRows))
|
|
140
|
+
const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))
|
|
144
141
|
|
|
145
142
|
return res.status(200).json({
|
|
146
143
|
success: true,
|
|
@@ -154,6 +151,14 @@ export default async function handler(req, res) {
|
|
|
154
151
|
error: error.message || 'Failed to fetch data',
|
|
155
152
|
timestamp: Date.now()
|
|
156
153
|
})
|
|
154
|
+
} finally {
|
|
155
|
+
if (connection) {
|
|
156
|
+
try {
|
|
157
|
+
await connection.end()
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.error('Error closing MySQL connection:', error)
|
|
160
|
+
}
|
|
161
|
+
}
|
|
157
162
|
}
|
|
158
163
|
}
|
|
159
164
|
`
|
|
@@ -167,7 +172,7 @@ export const generateMySQLCountFetcher = (
|
|
|
167
172
|
|
|
168
173
|
return `
|
|
169
174
|
async function getCount(req, res) {
|
|
170
|
-
const connection = getConnection()
|
|
175
|
+
const connection = await getConnection()
|
|
171
176
|
|
|
172
177
|
try {
|
|
173
178
|
const { query, queryColumns, filters } = req.query
|
|
@@ -216,7 +221,7 @@ async function getCount(req, res) {
|
|
|
216
221
|
countSql += \` WHERE \${conditions.join(' AND ')}\`
|
|
217
222
|
}
|
|
218
223
|
|
|
219
|
-
const [rows] = await connection.
|
|
224
|
+
const [rows] = await connection.query(countSql, queryParams)
|
|
220
225
|
const count = rows[0].count
|
|
221
226
|
|
|
222
227
|
return res.status(200).json({
|
|
@@ -231,6 +236,14 @@ async function getCount(req, res) {
|
|
|
231
236
|
error: error.message || 'Failed to get count',
|
|
232
237
|
timestamp: Date.now()
|
|
233
238
|
})
|
|
239
|
+
} finally {
|
|
240
|
+
if (connection) {
|
|
241
|
+
try {
|
|
242
|
+
await connection.end()
|
|
243
|
+
} catch (error) {
|
|
244
|
+
console.error('Error closing MySQL connection:', error)
|
|
245
|
+
}
|
|
246
|
+
}
|
|
234
247
|
}
|
|
235
248
|
}
|
|
236
249
|
`
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
interface PostgreSQLConfig {
|
|
4
4
|
host?: string
|
|
@@ -19,14 +19,10 @@ export const generatePostgreSQLFetcher = (
|
|
|
19
19
|
const pgConfig = config as PostgreSQLConfig
|
|
20
20
|
const schema = pgConfig.options?.schema
|
|
21
21
|
|
|
22
|
-
return `import {
|
|
22
|
+
return `import { Client } from 'pg'
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
const getPool = () => {
|
|
27
|
-
if (pool) return pool
|
|
28
|
-
|
|
29
|
-
pool = new Pool({
|
|
24
|
+
const getClient = () => {
|
|
25
|
+
return new Client({
|
|
30
26
|
host: ${JSON.stringify(pgConfig.host)},
|
|
31
27
|
port: ${pgConfig.port || 5432},
|
|
32
28
|
user: ${JSON.stringify(pgConfig.user || pgConfig.username)},
|
|
@@ -45,14 +41,16 @@ const getPool = () => {
|
|
|
45
41
|
: '{ rejectUnauthorized: false }'
|
|
46
42
|
}
|
|
47
43
|
})
|
|
48
|
-
|
|
49
|
-
return pool
|
|
50
44
|
}
|
|
51
45
|
|
|
46
|
+
${generateDateFormatterCode()}
|
|
47
|
+
|
|
52
48
|
export default async function handler(req, res) {
|
|
49
|
+
const client = getClient()
|
|
50
|
+
|
|
53
51
|
try {
|
|
54
|
-
|
|
55
|
-
${schema ? `await
|
|
52
|
+
await client.connect()
|
|
53
|
+
${schema ? `await client.query('SET search_path TO ${schema}')` : ''}
|
|
56
54
|
|
|
57
55
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset } = req.query
|
|
58
56
|
|
|
@@ -80,7 +78,7 @@ export default async function handler(req, res) {
|
|
|
80
78
|
? [${JSON.stringify(tableName)}, ${JSON.stringify(schema)}]
|
|
81
79
|
: [${JSON.stringify(tableName)}]
|
|
82
80
|
|
|
83
|
-
const schemaResult = await
|
|
81
|
+
const schemaResult = await client.query(schemaQuery, schemaParams)
|
|
84
82
|
columns = schemaResult.rows.map(row => row.column_name)
|
|
85
83
|
} catch (schemaError) {
|
|
86
84
|
console.warn('Failed to fetch column names from information_schema:', schemaError.message)
|
|
@@ -135,12 +133,12 @@ export default async function handler(req, res) {
|
|
|
135
133
|
sql += \` OFFSET \${offsetValue}\`
|
|
136
134
|
}
|
|
137
135
|
|
|
138
|
-
const result = await
|
|
136
|
+
const result = await client.query(sql, queryParams)
|
|
139
137
|
const rows = Array.isArray(result?.rows) ? result.rows : []
|
|
140
138
|
const plainRows = rows.map((row) =>
|
|
141
139
|
row && typeof row.toJSON === 'function' ? row.toJSON() : row
|
|
142
140
|
)
|
|
143
|
-
const safeData = JSON.parse(JSON.stringify(plainRows))
|
|
141
|
+
const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))
|
|
144
142
|
|
|
145
143
|
return res.status(200).json({
|
|
146
144
|
success: true,
|
|
@@ -154,6 +152,14 @@ export default async function handler(req, res) {
|
|
|
154
152
|
error: error.message || 'Failed to fetch data',
|
|
155
153
|
timestamp: Date.now()
|
|
156
154
|
})
|
|
155
|
+
} finally {
|
|
156
|
+
if (client) {
|
|
157
|
+
try {
|
|
158
|
+
await client.end()
|
|
159
|
+
} catch (error) {
|
|
160
|
+
console.error('Error closing PostgreSQL client:', error)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
157
163
|
}
|
|
158
164
|
}
|
|
159
165
|
`
|
|
@@ -168,9 +174,10 @@ export const generatePostgreSQLCountFetcher = (
|
|
|
168
174
|
|
|
169
175
|
return `
|
|
170
176
|
async function getCount(req, res) {
|
|
171
|
-
const
|
|
177
|
+
const client = getClient()
|
|
172
178
|
|
|
173
179
|
try {
|
|
180
|
+
await client.connect()
|
|
174
181
|
const { query, queryColumns, filters } = req.query
|
|
175
182
|
const conditions = []
|
|
176
183
|
const queryParams = []
|
|
@@ -198,7 +205,7 @@ async function getCount(req, res) {
|
|
|
198
205
|
: `[${JSON.stringify(tableName)}]`
|
|
199
206
|
}
|
|
200
207
|
|
|
201
|
-
const schemaResult = await
|
|
208
|
+
const schemaResult = await client.query(schemaQuery, schemaParams)
|
|
202
209
|
columns = schemaResult.rows.map(row => row.column_name)
|
|
203
210
|
} catch (schemaError) {
|
|
204
211
|
console.warn('Failed to fetch column names from information_schema:', schemaError.message)
|
|
@@ -226,7 +233,7 @@ async function getCount(req, res) {
|
|
|
226
233
|
countSql += \` WHERE \${conditions.join(' AND ')}\`
|
|
227
234
|
}
|
|
228
235
|
|
|
229
|
-
const result = await
|
|
236
|
+
const result = await client.query(countSql, queryParams)
|
|
230
237
|
const count = parseInt(result.rows[0].count, 10)
|
|
231
238
|
|
|
232
239
|
return res.status(200).json({
|
|
@@ -241,6 +248,14 @@ async function getCount(req, res) {
|
|
|
241
248
|
error: error.message || 'Failed to get count',
|
|
242
249
|
timestamp: Date.now()
|
|
243
250
|
})
|
|
251
|
+
} finally {
|
|
252
|
+
if (client) {
|
|
253
|
+
try {
|
|
254
|
+
await client.end()
|
|
255
|
+
} catch (error) {
|
|
256
|
+
console.error('Error closing PostgreSQL client:', error)
|
|
257
|
+
}
|
|
258
|
+
}
|
|
244
259
|
}
|
|
245
260
|
}
|
|
246
261
|
`
|
package/src/fetchers/redis.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
export const validateRedisConfig = (
|
|
4
4
|
config: Record<string, unknown>
|
|
@@ -63,6 +63,8 @@ export const generateRedisFetcher = (config: Record<string, unknown>): string =>
|
|
|
63
63
|
|
|
64
64
|
return `import { createClient } from 'redis'
|
|
65
65
|
|
|
66
|
+
${generateDateFormatterCode()}
|
|
67
|
+
|
|
66
68
|
export default async function handler(req, res) {
|
|
67
69
|
let client = null
|
|
68
70
|
try {
|
|
@@ -128,7 +130,7 @@ export default async function handler(req, res) {
|
|
|
128
130
|
})
|
|
129
131
|
}
|
|
130
132
|
|
|
131
|
-
const safeData = JSON.parse(JSON.stringify(results))
|
|
133
|
+
const safeData = JSON.parse(JSON.stringify(results, dateReplacer))
|
|
132
134
|
|
|
133
135
|
return res.status(200).json({
|
|
134
136
|
success: true,
|
package/src/fetchers/redshift.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
interface RedshiftConfig {
|
|
4
4
|
host?: string
|
|
@@ -25,14 +25,10 @@ export const generateRedshiftFetcher = (
|
|
|
25
25
|
const sslConfig = redshiftConfig.sslConfig
|
|
26
26
|
const schema = redshiftConfig.options?.schema
|
|
27
27
|
|
|
28
|
-
return `import {
|
|
28
|
+
return `import { Client } from 'pg'
|
|
29
29
|
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
const getPool = () => {
|
|
33
|
-
if (pool) return pool
|
|
34
|
-
|
|
35
|
-
pool = new Pool({
|
|
30
|
+
const getClient = () => {
|
|
31
|
+
return new Client({
|
|
36
32
|
host: ${JSON.stringify(host)},
|
|
37
33
|
port: ${port || 5439},
|
|
38
34
|
user: ${JSON.stringify(user)},
|
|
@@ -51,14 +47,16 @@ const getPool = () => {
|
|
|
51
47
|
: '{ rejectUnauthorized: false }' // Default to SSL with no cert verification for Redshift
|
|
52
48
|
}
|
|
53
49
|
})
|
|
54
|
-
|
|
55
|
-
return pool
|
|
56
50
|
}
|
|
57
51
|
|
|
52
|
+
${generateDateFormatterCode()}
|
|
53
|
+
|
|
58
54
|
export default async function handler(req, res) {
|
|
55
|
+
const client = getClient()
|
|
56
|
+
|
|
59
57
|
try {
|
|
60
|
-
|
|
61
|
-
${schema ? `await
|
|
58
|
+
await client.connect()
|
|
59
|
+
${schema ? `await client.query('SET search_path TO ${schema}')` : ''}
|
|
62
60
|
|
|
63
61
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset } = req.query
|
|
64
62
|
|
|
@@ -82,7 +80,7 @@ export default async function handler(req, res) {
|
|
|
82
80
|
? `[${JSON.stringify(tableName)}, ${JSON.stringify(schema)}]`
|
|
83
81
|
: `[${JSON.stringify(tableName)}]`
|
|
84
82
|
}
|
|
85
|
-
const schemaResult = await
|
|
83
|
+
const schemaResult = await client.query(schemaQuery, schemaParams)
|
|
86
84
|
columns = schemaResult.rows.map(row => row.column_name)
|
|
87
85
|
} catch (schemaError) {
|
|
88
86
|
console.warn('Failed to fetch column names from information_schema:', schemaError.message)
|
|
@@ -136,12 +134,12 @@ export default async function handler(req, res) {
|
|
|
136
134
|
sql += \` OFFSET \${offsetValue}\`
|
|
137
135
|
}
|
|
138
136
|
|
|
139
|
-
const result = await
|
|
137
|
+
const result = await client.query(sql, queryParams)
|
|
140
138
|
const rows = Array.isArray(result?.rows) ? result.rows : []
|
|
141
139
|
const plainRows = rows.map((row) =>
|
|
142
140
|
row && typeof row.toJSON === 'function' ? row.toJSON() : row
|
|
143
141
|
)
|
|
144
|
-
const safeData = JSON.parse(JSON.stringify(plainRows))
|
|
142
|
+
const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))
|
|
145
143
|
|
|
146
144
|
return res.status(200).json({
|
|
147
145
|
success: true,
|
|
@@ -155,6 +153,14 @@ export default async function handler(req, res) {
|
|
|
155
153
|
error: error.message || 'Failed to fetch data',
|
|
156
154
|
timestamp: Date.now()
|
|
157
155
|
})
|
|
156
|
+
} finally {
|
|
157
|
+
if (client) {
|
|
158
|
+
try {
|
|
159
|
+
await client.end()
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('Error closing Redshift client:', error)
|
|
162
|
+
}
|
|
163
|
+
}
|
|
158
164
|
}
|
|
159
165
|
}
|
|
160
166
|
`
|
package/src/fetchers/rest-api.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { generateDateFormatterCode } from '../utils'
|
|
2
|
+
|
|
1
3
|
export const validateRESTAPIConfig = (
|
|
2
4
|
config: Record<string, unknown>
|
|
3
5
|
): { isValid: boolean; error?: string } => {
|
|
@@ -75,6 +77,8 @@ export const generateRESTAPIFetcher = (config: Record<string, unknown>): string
|
|
|
75
77
|
|
|
76
78
|
return `import fetch from 'node-fetch'
|
|
77
79
|
|
|
80
|
+
${generateDateFormatterCode()}
|
|
81
|
+
|
|
78
82
|
export default async function handler(req, res) {
|
|
79
83
|
try {
|
|
80
84
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset } = req.query
|
|
@@ -190,7 +194,7 @@ export default async function handler(req, res) {
|
|
|
190
194
|
}
|
|
191
195
|
}
|
|
192
196
|
|
|
193
|
-
const safeData = JSON.parse(JSON.stringify(data))
|
|
197
|
+
const safeData = JSON.parse(JSON.stringify(data, dateReplacer))
|
|
194
198
|
|
|
195
199
|
return res.status(200).json({
|
|
196
200
|
success: true,
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { generateDateFormatterCode } from '../utils'
|
|
2
|
+
|
|
1
3
|
export const validateStaticCollectionConfig = (
|
|
2
4
|
config: Record<string, unknown>
|
|
3
5
|
): { isValid: boolean; error?: string } => {
|
|
@@ -20,6 +22,8 @@ export const generateStaticCollectionFetcher = (config: Record<string, unknown>)
|
|
|
20
22
|
const staticConfig = config as StaticCollectionConfig
|
|
21
23
|
return `const data = ${JSON.stringify(staticConfig.data || [])}
|
|
22
24
|
|
|
25
|
+
${generateDateFormatterCode()}
|
|
26
|
+
|
|
23
27
|
export default async function handler(req, res) {
|
|
24
28
|
try {
|
|
25
29
|
const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, offset: offsetParam } = req.query
|
|
@@ -79,7 +83,7 @@ export default async function handler(req, res) {
|
|
|
79
83
|
filteredData = filteredData.slice(offsetValue, offsetValue + parseInt(limitValue))
|
|
80
84
|
}
|
|
81
85
|
|
|
82
|
-
const safeData = JSON.parse(JSON.stringify(filteredData))
|
|
86
|
+
const safeData = JSON.parse(JSON.stringify(filteredData, dateReplacer))
|
|
83
87
|
|
|
84
88
|
return res.status(200).json({
|
|
85
89
|
success: true,
|
package/src/fetchers/supabase.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
export const validateSupabaseConfig = (
|
|
4
4
|
config: Record<string, unknown>
|
|
@@ -61,6 +61,8 @@ const getClient = () => {
|
|
|
61
61
|
return client
|
|
62
62
|
}
|
|
63
63
|
|
|
64
|
+
${generateDateFormatterCode()}
|
|
65
|
+
|
|
64
66
|
export default async function handler(req, res) {
|
|
65
67
|
try {
|
|
66
68
|
const client = getClient()
|
|
@@ -159,7 +161,7 @@ export default async function handler(req, res) {
|
|
|
159
161
|
})
|
|
160
162
|
}
|
|
161
163
|
|
|
162
|
-
const safeData = JSON.parse(JSON.stringify(data))
|
|
164
|
+
const safeData = JSON.parse(JSON.stringify(data, dateReplacer))
|
|
163
165
|
|
|
164
166
|
return res.status(200).json({
|
|
165
167
|
success: true,
|
package/src/fetchers/turso.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { replaceSecretReference } from '../utils'
|
|
1
|
+
import { replaceSecretReference, generateDateFormatterCode } from '../utils'
|
|
2
2
|
|
|
3
3
|
export const validateTursoConfig = (
|
|
4
4
|
config: Record<string, unknown>
|
|
@@ -35,6 +35,8 @@ export const generateTursoFetcher = (
|
|
|
35
35
|
|
|
36
36
|
return `import { createClient } from '@libsql/client'
|
|
37
37
|
|
|
38
|
+
${generateDateFormatterCode()}
|
|
39
|
+
|
|
38
40
|
export default async function handler(req, res) {
|
|
39
41
|
let client = null
|
|
40
42
|
try {
|
|
@@ -137,7 +139,7 @@ export default async function handler(req, res) {
|
|
|
137
139
|
}
|
|
138
140
|
}
|
|
139
141
|
|
|
140
|
-
const safeData = JSON.parse(JSON.stringify(data))
|
|
142
|
+
const safeData = JSON.parse(JSON.stringify(data, dateReplacer))
|
|
141
143
|
|
|
142
144
|
return res.status(200).json({
|
|
143
145
|
success: true,
|
|
@@ -153,7 +155,11 @@ export default async function handler(req, res) {
|
|
|
153
155
|
})
|
|
154
156
|
} finally {
|
|
155
157
|
if (client) {
|
|
156
|
-
|
|
158
|
+
try {
|
|
159
|
+
await client.close()
|
|
160
|
+
} catch (error) {
|
|
161
|
+
console.error('Error closing Turso client:', error)
|
|
162
|
+
}
|
|
157
163
|
}
|
|
158
164
|
}
|
|
159
165
|
}
|
package/src/utils.ts
CHANGED
|
@@ -510,6 +510,36 @@ export const replaceSecretReference = (
|
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
export const generateDateFormatterCode = (): string => {
|
|
514
|
+
return `const formatDateValue = (date) => {
|
|
515
|
+
const options = {
|
|
516
|
+
year: 'numeric',
|
|
517
|
+
month: 'short',
|
|
518
|
+
day: 'numeric',
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const timeOptions = {
|
|
522
|
+
hour: '2-digit',
|
|
523
|
+
minute: '2-digit',
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
const hasTime = date.getHours() !== 0 || date.getMinutes() !== 0 || date.getSeconds() !== 0
|
|
527
|
+
|
|
528
|
+
if (hasTime) {
|
|
529
|
+
return date.toLocaleString('en-US', { ...options, ...timeOptions })
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
return date.toLocaleDateString('en-US', options)
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const dateReplacer = (key, value) => {
|
|
536
|
+
if (value instanceof Date) {
|
|
537
|
+
return formatDateValue(value)
|
|
538
|
+
}
|
|
539
|
+
return value
|
|
540
|
+
}`
|
|
541
|
+
}
|
|
542
|
+
|
|
513
543
|
export const sanitizeNumericParam = (value: unknown, defaultValue: number = 0): number => {
|
|
514
544
|
if (typeof value === 'number' && !isNaN(value) && isFinite(value)) {
|
|
515
545
|
return Math.max(0, Math.floor(value))
|