@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,7 @@
|
|
|
1
|
+
export declare const validateTeleportConfig: (config: Record<string, unknown>) => {
|
|
2
|
+
isValid: boolean;
|
|
3
|
+
error?: string;
|
|
4
|
+
};
|
|
5
|
+
export declare const generateTeleportFetcher: (config: Record<string, unknown>, tableName: string) => string;
|
|
6
|
+
export declare const generateTeleportCountFetcher: (config: Record<string, unknown>, tableName: string) => string;
|
|
7
|
+
//# sourceMappingURL=teleport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teleport.d.ts","sourceRoot":"","sources":["../../../src/fetchers/teleport.ts"],"names":[],"mappings":"AAwCA,eAAO,MAAM,sBAAsB,WACzB,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAMpC,CAAA;AAED,eAAO,MAAM,uBAAuB,WAC1B,OAAO,MAAM,EAAE,OAAO,CAAC,aACpB,MAAM,KAChB,MAgVF,CAAA;AAED,eAAO,MAAM,4BAA4B,WAC/B,OAAO,MAAM,EAAE,OAAO,CAAC,aACpB,MAAM,KAChB,MA0FF,CAAA"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateTeleportCountFetcher = exports.generateTeleportFetcher = exports.validateTeleportConfig = void 0;
|
|
4
|
+
var utils_1 = require("../utils");
|
|
5
|
+
var transformations_1 = require("../transformations");
|
|
6
|
+
var DEFAULT_ENV_KEYS = {
|
|
7
|
+
host: 'TELEPORT_DB_HOST',
|
|
8
|
+
port: 'TELEPORT_DB_PORT',
|
|
9
|
+
user: 'TELEPORT_DB_USER',
|
|
10
|
+
password: 'TELEPORT_DB_PASSWORD',
|
|
11
|
+
database: 'TELEPORT_DB_NAME',
|
|
12
|
+
ssl: 'TELEPORT_DB_SSL',
|
|
13
|
+
};
|
|
14
|
+
var resolveEnvReference = function (value, defaultEnvKey) {
|
|
15
|
+
if (typeof value === 'string' && value.startsWith('teleporthq.secrets.')) {
|
|
16
|
+
return (0, utils_1.replaceSecretReference)(value);
|
|
17
|
+
}
|
|
18
|
+
return "process.env.".concat(defaultEnvKey);
|
|
19
|
+
};
|
|
20
|
+
var validateTeleportConfig = function (config) {
|
|
21
|
+
if (!config || typeof config !== 'object') {
|
|
22
|
+
return { isValid: false, error: 'Config must be a valid object' };
|
|
23
|
+
}
|
|
24
|
+
return { isValid: true };
|
|
25
|
+
};
|
|
26
|
+
exports.validateTeleportConfig = validateTeleportConfig;
|
|
27
|
+
var generateTeleportFetcher = function (config, tableName) {
|
|
28
|
+
var _a;
|
|
29
|
+
var dbConfig = config;
|
|
30
|
+
var schema = (_a = dbConfig.options) === null || _a === void 0 ? void 0 : _a.schema;
|
|
31
|
+
var hostRef = resolveEnvReference(dbConfig.host, DEFAULT_ENV_KEYS.host);
|
|
32
|
+
var portRef = resolveEnvReference(dbConfig.port, DEFAULT_ENV_KEYS.port);
|
|
33
|
+
var userRef = resolveEnvReference(dbConfig.user || dbConfig.username, DEFAULT_ENV_KEYS.user);
|
|
34
|
+
var passwordRef = resolveEnvReference(dbConfig.password, DEFAULT_ENV_KEYS.password);
|
|
35
|
+
var databaseRef = resolveEnvReference(dbConfig.database, DEFAULT_ENV_KEYS.database);
|
|
36
|
+
var sslCode = dbConfig.ssl === false
|
|
37
|
+
? 'false'
|
|
38
|
+
: dbConfig.sslConfig
|
|
39
|
+
? "{\n ".concat(dbConfig.sslConfig.ca
|
|
40
|
+
? "ca: ".concat(resolveEnvReference(dbConfig.sslConfig.ca, 'TELEPORT_DB_SSL_CA'), ",")
|
|
41
|
+
: '', "\n ").concat(dbConfig.sslConfig.cert
|
|
42
|
+
? "cert: ".concat(resolveEnvReference(dbConfig.sslConfig.cert, 'TELEPORT_DB_SSL_CERT'), ",")
|
|
43
|
+
: '', "\n ").concat(dbConfig.sslConfig.key
|
|
44
|
+
? "key: ".concat(resolveEnvReference(dbConfig.sslConfig.key, 'TELEPORT_DB_SSL_KEY'), ",")
|
|
45
|
+
: '', "\n rejectUnauthorized: false\n }")
|
|
46
|
+
: "(process.env.".concat(DEFAULT_ENV_KEYS.ssl, " === 'false' ? false : process.env.").concat(DEFAULT_ENV_KEYS.ssl, " === 'true' ? { rejectUnauthorized: false } : undefined)");
|
|
47
|
+
return "import { Client } from 'pg'\n\nfunction normalizePostgresConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n if (/^postgresql:\\/(?!\\/)/i.test(connectionString)) {\n return connectionString.replace(/^postgresql:\\//i, 'postgresql://');\n }\n return connectionString;\n}\n\nfunction stripSslQueryParamsFromConnectionString(connectionString) {\n if (!connectionString || typeof connectionString !== 'string') return connectionString;\n try {\n var u = new URL(connectionString.replace(/^postgresql:/i, 'postgres:'));\n u.searchParams.delete('sslmode');\n u.searchParams.delete('ssl');\n u.searchParams.delete('sslrootcert');\n u.searchParams.delete('sslcert');\n u.searchParams.delete('sslkey');\n return u.toString().replace(/^postgres:/i, 'postgresql:');\n } catch (e) {\n return connectionString;\n }\n}\n\nconst getClient = () => {\n var ssl = ".concat(sslCode, ";\n var connStr = process.env.TELEPORT_DB_CONNECTION_STRING;\n if (connStr) {\n connStr = normalizePostgresConnectionString(connStr);\n }\n if (ssl === false && connStr) {\n connStr = stripSslQueryParamsFromConnectionString(connStr);\n }\n if (connStr) {\n return new Client(Object.assign(\n { connectionString: connStr },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n }\n return new Client(Object.assign(\n {\n host: ").concat(hostRef, ",\n port: parseInt(").concat(portRef, " || '5432', 10),\n user: ").concat(userRef, ",\n password: ").concat(passwordRef, ",\n database: ").concat(databaseRef, ",\n },\n ssl !== undefined ? { ssl: ssl } : {}\n ));\n}\n\n").concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateSearchEscapeHelpersCode)(), "\n").concat((0, transformations_1.getTransformationCode)(tableName), "\n").concat((0, transformations_1.getTransformWrapperCode)(tableName), "\nconst processFilters = (filters, conditions, queryParams, paramIndex) => {\n if (!filters) return paramIndex\n \n const parsedFilters = safeJSONParse(filters)\n \n if (Array.isArray(parsedFilters)) {\n parsedFilters.forEach((filter) => {\n if (!filter.source || filter.destination === undefined) return\n \n const field = filter.source\n const value = filter.destination\n const operand = filter.operand || '='\n \n if (Array.isArray(value)) {\n if (value.length === 0) return\n const placeholders = value.map(() => `$${paramIndex++}`)\n queryParams.push(...value)\n if (operand === '!=') {\n conditions.push(`${field} NOT IN (${placeholders.join(', ')})`)\n } else {\n conditions.push(`${field} IN (${placeholders.join(', ')})`)\n }\n } else {\n if (value === null) {\n if (operand === '=') {\n conditions.push(`${field} IS NULL`)\n } else if (operand === '!=') {\n conditions.push(`${field} IS NOT NULL`)\n }\n } else {\n const validOps = ['=', '!=', '>', '<', '>=', '<=']\n const sqlOperator = validOps.includes(operand) ? operand : '='\n conditions.push(`${field} ${sqlOperator} $${paramIndex}`)\n queryParams.push(value)\n paramIndex++\n }\n }\n })\n } else {\n Object.entries(parsedFilters).forEach(([key, value]) => {\n if (Array.isArray(value)) {\n const placeholders = value.map(() => `$${paramIndex++}`)\n queryParams.push(...value)\n conditions.push(`${key} IN (${placeholders.join(', ')})`)\n } else {\n conditions.push(`${key} = $${paramIndex}`)\n queryParams.push(value)\n paramIndex++\n }\n })\n }\n \n return paramIndex\n}\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n// Matches DDL / dangerous statements the raw-query branch should refuse.\n// Keep this list conservative \u2014 anything destructive or schema-changing is\n// out of scope for a client-triggered fetch. SELECT and CTEs (WITH ...) are\n// the only shapes consumers legitimately need.\nconst BLOCKED_RAW_QUERY_PATTERNS = [\n /\\bcreate\\s+(?:temporary\\s+|temp\\s+|unlogged\\s+|global\\s+|local\\s+)?table\\b/i,\n /\\bcreate\\s+(?:unique\\s+)?index\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:materialized\\s+)?view\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?trigger\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?(?:aggregate\\s+)?function\\b/i,\n /\\bcreate\\s+(?:or\\s+replace\\s+)?procedure\\b/i,\n /\\bcreate\\s+(?:database|schema|sequence|extension|type|role|user)\\b/i,\n /\\bdrop\\s+(?:table|view|index|schema|database|sequence|trigger|function|procedure|role|user|extension|type|materialized)\\b/i,\n /\\balter\\s+(?:table|view|index|schema|database|sequence|role|user|system)\\b/i,\n /\\btruncate\\b/i,\n /\\bgrant\\b/i,\n /\\brevoke\\b/i,\n /\\binsert\\b/i,\n /\\bupdate\\b/i,\n /\\bdelete\\b/i,\n /\\bcopy\\b/i,\n /\\bvacuum\\b/i,\n /\\breindex\\b/i,\n /\\bcluster\\b/i,\n]\n\nfunction assertRawQuerySafe(rawQuery) {\n if (typeof rawQuery !== 'string' || rawQuery.length === 0) {\n throw new Error('rawQuery must be a non-empty string')\n }\n // Reject multi-statement payloads \u2014 only single SELECT / WITH statements.\n // A trailing semicolon is tolerated but any content after it fails.\n var trimmed = rawQuery.trim().replace(/;\\s*$/, '')\n if (trimmed.indexOf(';') !== -1) {\n throw new Error('rawQuery must contain exactly one statement')\n }\n for (var i = 0; i < BLOCKED_RAW_QUERY_PATTERNS.length; i++) {\n if (BLOCKED_RAW_QUERY_PATTERNS[i].test(trimmed)) {\n throw new Error('rawQuery contains a blocked statement')\n }\n }\n}\n\nexport default async function handler(req, res) {\n const client = getClient()\n\n try {\n await client.connect()\n ").concat(schema ? "await client.query('SET search_path TO ".concat(schema, "')") : '', "\n\n // If the caller supplied a rawQuery, run it verbatim (after a safety\n // guard). The schema-driven branch below builds `SELECT * FROM ").concat(tableName, "`\n // with optional filters \u2014 it's the default read path and ignores\n // rawQuery. Page-load workflows and other consumers that need a JOIN\n // or a user-scoped filter pass their fully-rendered SQL here via\n // `fetchData({ rawQuery })` and expect it to execute verbatim.\n if (req.query && typeof req.query.rawQuery === 'string' && req.query.rawQuery.length > 0) {\n assertRawQuerySafe(req.query.rawQuery)\n const rawResult = await client.query(req.query.rawQuery)\n const rawRows = Array.isArray(rawResult?.rows) ? rawResult.rows : []\n const rawPlain = rawRows.map((row) =>\n row && typeof row.toJSON === 'function' ? row.toJSON() : row\n )\n const rawSafe = JSON.parse(JSON.stringify(rawPlain, dateReplacer))\n return res.status(200).json({\n success: true,\n data: rawSafe,\n timestamp: Date.now()\n })\n }\n\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n \n const conditions = []\n const queryParams = []\n let paramIndex = 1\n \n if (query) {\n let columns = []\n \n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n columns = Array.isArray(parsed) ? parsed : (parsed ? [parsed] : [])\n } else {\n try {\n const schemaQuery = `\n SELECT column_name \n FROM information_schema.columns \n WHERE table_name = $1\n ").concat(schema ? "AND table_schema = $2" : '', "\n ORDER BY ordinal_position\n `\n const schemaParams = ").concat(schema
|
|
48
|
+
? "[".concat(JSON.stringify(tableName), ", ").concat(JSON.stringify(schema), "]")
|
|
49
|
+
: "[".concat(JSON.stringify(tableName), "]"), "\n \n const schemaResult = await client.query(schemaQuery, schemaParams)\n columns = schemaResult.rows.map(row => row.column_name)\n } catch (schemaError) {\n console.warn('Failed to fetch column names from information_schema:', schemaError.message)\n }\n }\n \n if (columns.length > 0) {\n const pattern = '%' + escapeLikePattern(query) + '%'\n const placeholder = '$' + paramIndex\n paramIndex++\n queryParams.push(pattern)\n const searchConditions = columns.map(\n (col) => '\"' + sanitizeSearchIdentifier(col) + '\"::text ILIKE ' + placeholder + \" ESCAPE '|'\"\n )\n conditions.push('(' + searchConditions.join(' OR ') + ')')\n }\n }\n \n paramIndex = processFilters(filters, conditions, queryParams, paramIndex)\n \n let sql = `SELECT * FROM ").concat(tableName, "`\n \n if (conditions.length > 0) {\n sql += ` WHERE ${conditions.join(' AND ')}`\n }\n \n if (sorts) {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n const orderClauses = parsedSorts.map((sort) => {\n if (!sort.field) return null\n const order = (sort.order || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'\n return `${sort.field} ${order}`\n }).filter(Boolean)\n\n if (orderClauses.length > 0) {\n sql += ` ORDER BY ${orderClauses.join(', ')}`\n }\n }\n } else if (sortBy) {\n sql += ` ORDER BY ${sortBy} ${(sortOrder || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'}`\n }\n \n const limitValue = limit || perPage\n const offsetValue = offset !== undefined ? parseInt(offset) : (page && perPage ? (parseInt(page) - 1) * parseInt(perPage) : undefined)\n \n if (limitValue) {\n sql += ` LIMIT ${limitValue}`\n }\n \n if (offsetValue !== undefined) {\n sql += ` OFFSET ${offsetValue}`\n }\n \n const result = await client.query(sql, queryParams)\n const rows = Array.isArray(result?.rows) ? result.rows : []\n const plainRows = rows.map((row) =>\n row && typeof row.toJSON === 'function' ? row.toJSON() : row\n )\n const safeData = JSON.parse(JSON.stringify(plainRows, dateReplacer))\n ").concat((0, transformations_1.getTransformExpression)(tableName)
|
|
50
|
+
? "const transformedData = ".concat((0, transformations_1.getTransformExpression)(tableName))
|
|
51
|
+
: '', "\n\n return res.status(200).json({\n success: true,\n data: ").concat((0, transformations_1.getTransformExpression)(tableName) ? 'transformedData' : 'safeData', ",\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Teleport DB 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 } finally {\n if (client) {\n try {\n await client.end()\n } catch (error) {\n console.error('Error closing database client:', error)\n }\n }\n }\n}\n");
|
|
52
|
+
};
|
|
53
|
+
exports.generateTeleportFetcher = generateTeleportFetcher;
|
|
54
|
+
var generateTeleportCountFetcher = function (config, tableName) {
|
|
55
|
+
var _a;
|
|
56
|
+
var dbConfig = config;
|
|
57
|
+
var hasSchema = !!((_a = dbConfig.options) === null || _a === void 0 ? void 0 : _a.schema);
|
|
58
|
+
return "\nasync function getCount(req, res) {\n const client = getClient()\n\n try {\n await client.connect()\n const { query, queryColumns, filters } = req.query\n const conditions = []\n const queryParams = []\n let paramIndex = 1\n\n if (query) {\n let columns = []\n \n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n columns = Array.isArray(parsed) ? parsed : [parsed]\n } else {\n try {\n const schemaQuery = `\n SELECT column_name \n FROM information_schema.columns \n WHERE table_name = $1\n ".concat(hasSchema ? "AND table_schema = $2" : '', "\n ORDER BY ordinal_position\n `\n const schemaParams = ").concat(hasSchema
|
|
59
|
+
? "[".concat(JSON.stringify(tableName), ", ").concat(JSON.stringify(dbConfig.options.schema), "]")
|
|
60
|
+
: "[".concat(JSON.stringify(tableName), "]"), "\n \n const schemaResult = await client.query(schemaQuery, schemaParams)\n columns = schemaResult.rows.map(row => row.column_name)\n } catch (schemaError) {\n console.warn('Failed to fetch column names from information_schema:', schemaError.message)\n }\n }\n \n if (columns.length > 0) {\n const pattern = '%' + escapeLikePattern(query) + '%'\n const placeholder = '$' + paramIndex\n paramIndex++\n queryParams.push(pattern)\n const searchConditions = columns\n .map(\n (col) => '\"' + sanitizeSearchIdentifier(col) + '\"::text ILIKE ' + placeholder + \" ESCAPE '|'\"\n )\n .join(' OR ')\n conditions.push('(' + searchConditions + ')')\n }\n }\n\n paramIndex = processFilters(filters, conditions, queryParams, paramIndex)\n\n let countSql = `SELECT COUNT(*) FROM ").concat(tableName, "`\n if (conditions.length > 0) {\n countSql += ` WHERE ${conditions.join(' AND ')}`\n }\n\n const result = await client.query(countSql, queryParams)\n const count = parseInt(result.rows[0].count, 10)\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 } finally {\n if (client) {\n try {\n await client.end()\n } catch (error) {\n console.error('Error closing database client:', error)\n }\n }\n }\n}\n");
|
|
61
|
+
};
|
|
62
|
+
exports.generateTeleportCountFetcher = generateTeleportCountFetcher;
|
|
63
|
+
//# sourceMappingURL=teleport.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"teleport.js","sourceRoot":"","sources":["../../../src/fetchers/teleport.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turso.d.ts","sourceRoot":"","sources":["../../../src/fetchers/turso.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"turso.d.ts","sourceRoot":"","sources":["../../../src/fetchers/turso.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,mBAAmB,WACtB,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAcpC,CAAA;AASD,eAAO,MAAM,oBAAoB,WACvB,OAAO,MAAM,EAAE,OAAO,CAAC,aACpB,MAAM,KAChB,MA8MF,CAAA"}
|
|
@@ -19,7 +19,7 @@ var generateTursoFetcher = function (config, tableName) {
|
|
|
19
19
|
var tursoConfig = config;
|
|
20
20
|
var databaseUrl = tursoConfig.databaseUrl;
|
|
21
21
|
var token = tursoConfig.token;
|
|
22
|
-
return "import { createClient } from '@libsql/client'\n\n".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\nexport default async function handler(req, res) {\n let client = null\n try {\n client = createClient({\n url: ").concat(JSON.stringify(databaseUrl), ",\n authToken: ").concat((0, utils_1.replaceSecretReference)(token), "\n })\n \n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n \n let sql = `SELECT * FROM ").concat(tableName, "`\n const whereClauses = []\n const queryParams = []\n let searchQueryColumns = null\n \n if (query) {\n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n // Cast columns to TEXT
|
|
22
|
+
return "import { createClient } from '@libsql/client'\n\n".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateSearchEscapeHelpersCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\nexport default async function handler(req, res) {\n let client = null\n try {\n client = createClient({\n url: ").concat(JSON.stringify(databaseUrl), ",\n authToken: ").concat((0, utils_1.replaceSecretReference)(token), "\n })\n \n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n \n let sql = `SELECT * FROM ").concat(tableName, "`\n const whereClauses = []\n const queryParams = []\n let searchQueryColumns = null\n \n if (query) {\n if (queryColumns) {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n // Cast columns to TEXT and LOWER both sides so the match is\n // case-insensitive regardless of SQLite collation.\n const pattern = \"%\" + escapeLikePattern(query) + \"%\"\n const searchConditions = columns.map(\n (col) =>\n 'LOWER(CAST(\"' + sanitizeSearchIdentifier(col) + '\" AS TEXT)) LIKE LOWER(?) ESCAPE ' + \"'|'\"\n )\n whereClauses.push(\"(\" + searchConditions.join(\" OR \") + \")\")\n columns.forEach(() => {\n queryParams.push(pattern)\n })\n } else {\n // Store query for post-filtering if columns not specified\n searchQueryColumns = query\n }\n }\n \n // Helper to sanitize identifier (prevent SQL injection in column names)\n const sanitizeIdentifier = (name) => {\n // Only allow alphanumeric and underscore\n if (!/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(name)) {\n throw new Error(`Invalid identifier: ${name}`)\n }\n return `\"${name}\"`\n }\n \n if (filters) {\n const parsedFilters = safeJSONParse(filters)\n \n if (Array.isArray(parsedFilters)) {\n parsedFilters.forEach((filter) => {\n if (!filter.source || filter.destination === undefined) return\n \n const field = sanitizeIdentifier(filter.source)\n const value = filter.destination\n const operand = filter.operand || '='\n \n if (Array.isArray(value)) {\n if (value.length === 0) return\n const placeholders = value.map(() => '?').join(', ')\n queryParams.push(...value)\n if (operand === '!=') {\n whereClauses.push(`${field} NOT IN (${placeholders})`)\n } else {\n whereClauses.push(`${field} IN (${placeholders})`)\n }\n } else {\n if (value === null) {\n if (operand === '=') {\n whereClauses.push(`${field} IS NULL`)\n } else if (operand === '!=') {\n whereClauses.push(`${field} IS NOT NULL`)\n }\n } else {\n const validOps = ['=', '!=', '>', '<', '>=', '<=']\n const sqlOperator = validOps.includes(operand) ? operand : '='\n whereClauses.push(`${field} ${sqlOperator} ?`)\n queryParams.push(value)\n }\n }\n })\n } else {\n Object.entries(parsedFilters).forEach(([key, value]) => {\n const field = sanitizeIdentifier(key)\n if (Array.isArray(value)) {\n const placeholders = value.map(() => '?').join(', ')\n queryParams.push(...value)\n whereClauses.push(`${field} IN (${placeholders})`)\n } else {\n whereClauses.push(`${field} = ?`)\n queryParams.push(value)\n }\n })\n }\n }\n \n if (whereClauses.length > 0) {\n sql += ` WHERE ${whereClauses.join(' AND ')}`\n }\n \n // Handle sorts - new array format\n if (sorts) {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n const orderClauses = parsedSorts.map((sort) => {\n if (!sort.field) return null\n const order = (sort.order || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'\n return `${sanitizeIdentifier(sort.field)} ${order}`\n }).filter(Boolean)\n\n if (orderClauses.length > 0) {\n sql += ` ORDER BY ${orderClauses.join(', ')}`\n }\n }\n } else if (sortBy) {\n const sortOrderValue = (sortOrder || '').toUpperCase().startsWith('DESC') ? 'DESC' : 'ASC'\n sql += ` ORDER BY ${sanitizeIdentifier(sortBy)} ${sortOrderValue}`\n }\n \n const limitValue = limit || perPage\n const offsetValue = offset !== undefined ? parseInt(offset) : (page && perPage ? (parseInt(page) - 1) * parseInt(perPage) : undefined)\n \n // Only apply SQL pagination if we're not doing post-filtering\n if (!searchQueryColumns) {\n if (limitValue) {\n sql += ` LIMIT ?`\n queryParams.push(parseInt(limitValue))\n }\n \n if (offsetValue !== undefined) {\n sql += ` OFFSET ?`\n queryParams.push(offsetValue)\n }\n }\n \n const result = await client.execute({\n sql,\n args: queryParams\n })\n \n let data = result.rows.map((row) => {\n const obj = {}\n result.columns.forEach((col, idx) => {\n obj[col] = row[col]\n })\n return obj\n })\n \n // Apply post-filtering for search without queryColumns\n if (searchQueryColumns) {\n const searchQuery = searchQueryColumns.toLowerCase()\n data = data.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 // Apply pagination after filtering\n if (limitValue) {\n const start = offsetValue || 0\n data = data.slice(start, start + parseInt(limitValue))\n } else if (offsetValue) {\n data = data.slice(offsetValue)\n }\n }\n \n const safeData = JSON.parse(JSON.stringify(data, 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('Turso 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 } finally {\n if (client) {\n try {\n await client.close()\n } catch (error) {\n console.error('Error closing Turso client:', error)\n }\n }\n }\n}\n");
|
|
23
23
|
};
|
|
24
24
|
exports.generateTursoFetcher = generateTursoFetcher;
|
|
25
25
|
//# sourceMappingURL=turso.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"turso.js","sourceRoot":"","sources":["../../../src/fetchers/turso.ts"],"names":[],"mappings":";;;AAAA,
|
|
1
|
+
{"version":3,"file":"turso.js","sourceRoot":"","sources":["../../../src/fetchers/turso.ts"],"names":[],"mappings":";;;AAAA,kCAKiB;AAEV,IAAM,mBAAmB,GAAG,UACjC,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,WAAW,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,EAAE;QACjE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,gCAAgC,EAAE,CAAA;KACnE;IAED,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,EAAE;QACrD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,wCAAwC,EAAE,CAAA;KAC3E;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC,CAAA;AAhBY,QAAA,mBAAmB,uBAgB/B;AASM,IAAM,oBAAoB,GAAG,UAClC,MAA+B,EAC/B,SAAiB;IAEjB,IAAM,WAAW,GAAG,MAAqB,CAAA;IACzC,IAAM,WAAW,GAAG,WAAW,CAAC,WAAW,CAAA;IAC3C,IAAM,KAAK,GAAG,WAAW,CAAC,KAAK,CAAA;IAE/B,OAAO,2DAEP,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,uCAA+B,GAAE,iBAEjC,IAAA,iCAAyB,GAAE,0IAMhB,IAAI,CAAC,SAAS,CAAC,WAAW,CAAC,iCACrB,IAAA,8BAAsB,EAAC,KAAK,CAAC,gLAKhB,SAAS,g/LAsLxC,CAAA;AACD,CAAC,CAAA;AAjNY,QAAA,oBAAoB,wBAiNhC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import * as types from '@babel/types';
|
|
2
|
+
export declare const buildFiltersStringifyCall: (filters: Array<{
|
|
3
|
+
source?: string;
|
|
4
|
+
operand?: string;
|
|
5
|
+
destination: unknown;
|
|
6
|
+
}>, buildDestinationExpression: (destination: unknown) => types.Expression) => types.CallExpression;
|
|
7
|
+
export declare const appendFiltersParam: (paramsProps: types.ObjectProperty[], filters: Array<{
|
|
8
|
+
source?: string;
|
|
9
|
+
operand?: string;
|
|
10
|
+
destination: unknown;
|
|
11
|
+
}> | undefined, buildDestinationExpression: (destination: unknown) => types.Expression) => void;
|
|
12
|
+
export declare const pushStateIdsAsDeps: (deps: types.Expression[], seen: Set<string>, stateIds: string[]) => void;
|
|
13
|
+
//# sourceMappingURL=filter-utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-utils.d.ts","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AAkDrC,eAAO,MAAM,yBAAyB,YAC3B,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,4CACjC,OAAO,KAAK,MAAM,UAAU,KACrE,MAAM,cAkBR,CAAA;AAGD,eAAO,MAAM,kBAAkB,gBAChB,MAAM,cAAc,EAAE,WAC1B,MAAM;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,OAAO,CAAA;CAAE,CAAC,GAAG,SAAS,4CAC7C,OAAO,KAAK,MAAM,UAAU,KACrE,IAUF,CAAA;AAUD,eAAO,MAAM,kBAAkB,SACvB,MAAM,UAAU,EAAE,QAClB,IAAI,MAAM,CAAC,YACP,MAAM,EAAE,KACjB,IAQF,CAAA"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
26
|
+
exports.pushStateIdsAsDeps = exports.appendFiltersParam = exports.buildFiltersStringifyCall = void 0;
|
|
27
|
+
var types = __importStar(require("@babel/types"));
|
|
28
|
+
// Build a single filter entry: { source: '<src>', destination: <destExpr>, operand: '<op>' }
|
|
29
|
+
var buildFilterEntry = function (source, destinationExpr, operand) {
|
|
30
|
+
return types.objectExpression([
|
|
31
|
+
types.objectProperty(types.identifier('source'), types.stringLiteral(source)),
|
|
32
|
+
types.objectProperty(types.identifier('destination'), destinationExpr),
|
|
33
|
+
types.objectProperty(types.identifier('operand'), types.stringLiteral(operand)),
|
|
34
|
+
]);
|
|
35
|
+
};
|
|
36
|
+
// Predicate `(__f) => __f.destination !== '' && __f.destination !== null && __f.destination !== undefined`
|
|
37
|
+
// Used at runtime to drop filter conditions whose destination resolves to an
|
|
38
|
+
// empty value. Keeps the page generic: state-bound filters (e.g.
|
|
39
|
+
// `selectedCategory === ''` after picking "All Categories") and url-bound
|
|
40
|
+
// filters (e.g. no `?categoryFilter=` in URL → `router?.query?.categoryFilter`
|
|
41
|
+
// is `undefined`) both fall away cleanly instead of being sent to the API as
|
|
42
|
+
// `destination: ''`, which the SQL backend interprets as a literal empty
|
|
43
|
+
// string and returns zero rows.
|
|
44
|
+
var buildNonEmptyDestinationPredicate = function () {
|
|
45
|
+
var f = types.identifier('__f');
|
|
46
|
+
var dest = types.memberExpression(f, types.identifier('destination'));
|
|
47
|
+
return types.arrowFunctionExpression([f], types.logicalExpression('&&', types.logicalExpression('&&', types.binaryExpression('!==', dest, types.stringLiteral('')), types.binaryExpression('!==', dest, types.nullLiteral())), types.binaryExpression('!==', dest, types.identifier('undefined'))));
|
|
48
|
+
};
|
|
49
|
+
// Build the AST for:
|
|
50
|
+
// JSON.stringify(
|
|
51
|
+
// [ {source, destination, operand}, ... ]
|
|
52
|
+
// .filter(__f => __f.destination !== '' && __f.destination !== null && __f.destination !== undefined)
|
|
53
|
+
// )
|
|
54
|
+
//
|
|
55
|
+
// The `.filter(...)` step is unconditional even when every entry is a static
|
|
56
|
+
// (always-truthy) destination — the cost is negligible at runtime and it
|
|
57
|
+
// keeps the generated code uniform, so future regressions where a new filter
|
|
58
|
+
// type is added but its empty-value behavior is forgotten don't silently
|
|
59
|
+
// re-introduce empty-string filters.
|
|
60
|
+
var buildFiltersStringifyCall = function (filters, buildDestinationExpression) {
|
|
61
|
+
var entries = filters.map(function (filter) {
|
|
62
|
+
return buildFilterEntry(filter.source || '', buildDestinationExpression(filter.destination), filter.operand || '');
|
|
63
|
+
});
|
|
64
|
+
var filteredArray = types.callExpression(types.memberExpression(types.arrayExpression(entries), types.identifier('filter')), [buildNonEmptyDestinationPredicate()]);
|
|
65
|
+
return types.callExpression(types.memberExpression(types.identifier('JSON'), types.identifier('stringify')), [filteredArray]);
|
|
66
|
+
};
|
|
67
|
+
exports.buildFiltersStringifyCall = buildFiltersStringifyCall;
|
|
68
|
+
// Convenience: push `filters: <call>` onto a paramsProps array.
|
|
69
|
+
var appendFiltersParam = function (paramsProps, filters, buildDestinationExpression) {
|
|
70
|
+
if (!filters || filters.length === 0) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
paramsProps.push(types.objectProperty(types.identifier('filters'), (0, exports.buildFiltersStringifyCall)(filters, buildDestinationExpression)));
|
|
74
|
+
};
|
|
75
|
+
exports.appendFiltersParam = appendFiltersParam;
|
|
76
|
+
// Appends each id in `stateIds` as a bare `Identifier` onto `deps`, skipping
|
|
77
|
+
// any id already tracked in `seen`. Mutates both `deps` and `seen`.
|
|
78
|
+
//
|
|
79
|
+
// Used by every count-fetch and params-`useMemo` builder in the pagination
|
|
80
|
+
// plugin to wire state-bound filter destinations into React's deps array.
|
|
81
|
+
// Centralising the loop here means a new dep-source (sort, future filter
|
|
82
|
+
// shapes) can hook into the same dedup-by-name set without re-implementing
|
|
83
|
+
// it at four call sites.
|
|
84
|
+
var pushStateIdsAsDeps = function (deps, seen, stateIds) {
|
|
85
|
+
for (var _i = 0, stateIds_1 = stateIds; _i < stateIds_1.length; _i++) {
|
|
86
|
+
var id = stateIds_1[_i];
|
|
87
|
+
if (seen.has(id)) {
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
seen.add(id);
|
|
91
|
+
deps.push(types.identifier(id));
|
|
92
|
+
}
|
|
93
|
+
};
|
|
94
|
+
exports.pushStateIdsAsDeps = pushStateIdsAsDeps;
|
|
95
|
+
//# sourceMappingURL=filter-utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"filter-utils.js","sourceRoot":"","sources":["../../src/filter-utils.ts"],"names":[],"mappings":"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"}
|
package/dist/cjs/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,sBAAsB,EAKvB,MAAM,4BAA4B,CAAA;AA6anC,eAAO,MAAM,+BAA+B,EAAE,sBAAsB,CAAC,EAAE,CAietE,CAAA;AAiOD,eAAO,MAAM,mCAAmC,EAAE,sBAAsB,CAAC,EAAE,CA0O1E,CAAA;AAED,cAAc,wBAAwB,CAAA;AACtC,cAAc,SAAS,CAAA;AACvB,cAAc,2BAA2B,CAAA;AACzC,cAAc,qBAAqB,CAAA;AACnC,cAAc,kBAAkB,CAAA"}
|
package/dist/cjs/index.js
CHANGED
|
@@ -312,8 +312,8 @@ function extractPaginationConfigEarly(uidlNode, resources) {
|
|
|
312
312
|
var createNextPagesDataSourcePlugin = function () {
|
|
313
313
|
var nextPagesDataSourcePlugin = function (structure) { return __awaiter(void 0, void 0, void 0, function () {
|
|
314
314
|
var uidl, chunks, options, dependencies, dataSources, componentChunk, opts, pageConfig, getStaticPropsChunk, firstDataSourceInfo, fetcherImportName, dataProviderPositionCounters, existingPropKeys, funcDecl, tryStmt, retStmt, propsProp, propsVal, _i, _a, prop, keyName, wrapContext, functionDeclaration, functionBody, tryBlock, returnStatement, propsObject, propsValue, meta, _b, _c, wrapped, fetchCallExpression, safeFetchExpression, existingIndex, promiseAllCall, arrayPattern, hasPaginatedOrSearchDataSources, getStaticPropsAST, paginationPlugin;
|
|
315
|
-
var _d;
|
|
316
|
-
return __generator(this, function (
|
|
315
|
+
var _d, _e;
|
|
316
|
+
return __generator(this, function (_f) {
|
|
317
317
|
uidl = structure.uidl, chunks = structure.chunks, options = structure.options, dependencies = structure.dependencies;
|
|
318
318
|
// Early return if no options or dataSources
|
|
319
319
|
if (!options || !options.dataSources) {
|
|
@@ -362,7 +362,7 @@ var createNextPagesDataSourcePlugin = function () {
|
|
|
362
362
|
// Data source nodes can be either:
|
|
363
363
|
// 1. Direct: node.type === 'data-source-item' or 'data-source-list'
|
|
364
364
|
// 2. Wrapped in element: node.type === 'element' && node.content.type === 'data-source-item' or 'data-source-list'
|
|
365
|
-
var _a;
|
|
365
|
+
var _a, _b, _c;
|
|
366
366
|
var dataSourceNode = null;
|
|
367
367
|
if (node.type === 'data-source-item' || node.type === 'data-source-list') {
|
|
368
368
|
// Direct data source node
|
|
@@ -433,19 +433,20 @@ var createNextPagesDataSourcePlugin = function () {
|
|
|
433
433
|
// Skip this node but position counter is already incremented above
|
|
434
434
|
return;
|
|
435
435
|
}
|
|
436
|
-
// Check if resource has dynamic parameters
|
|
436
|
+
// Check if resource has dynamic parameters that can't be resolved server-side
|
|
437
|
+
var dynamicRouteAttr = (_a = uidl.outputOptions) === null || _a === void 0 ? void 0 : _a.dynamicRouteAttribute;
|
|
437
438
|
// tslint:disable-next-line:no-any
|
|
438
|
-
var hasResourceDynamicParams = ((
|
|
439
|
-
?
|
|
439
|
+
var hasResourceDynamicParams = ((_b = dataSourceNode.content.resource) === null || _b === void 0 ? void 0 : _b.params)
|
|
440
|
+
? (0, utils_1.hasUnresolvableDynamicParams)(dataSourceNode.content.resource.params, dynamicRouteAttr)
|
|
440
441
|
: false;
|
|
441
|
-
// If no dynamic params, extract to getStaticProps (server-side)
|
|
442
|
+
// If no dynamic params (or all are route-resolvable), extract to getStaticProps (server-side)
|
|
442
443
|
// Otherwise, extract to API route (client-side)
|
|
443
444
|
if (!hasResourceDynamicParams) {
|
|
444
445
|
// extractDataSourceIntoGetStaticProps is called for every UIDL data-source node.
|
|
445
446
|
// When multiple nodes share the same dataSourceKey (same resource ID), the function is
|
|
446
447
|
// idempotent for getStaticProps (skips duplicate fetches via existingInFetchMeta) but
|
|
447
448
|
// still updates the next uninitialized DataProvider JSX node on each call.
|
|
448
|
-
var result = (0, utils_1.extractDataSourceIntoGetStaticProps)(dataSourceNode, dataSources, componentChunk, getStaticPropsChunk, chunks, options.extractedResources, dependencies);
|
|
449
|
+
var result = (0, utils_1.extractDataSourceIntoGetStaticProps)(dataSourceNode, dataSources, componentChunk, getStaticPropsChunk, chunks, options.extractedResources, dependencies, dynamicRouteAttr, (_c = uidl.outputOptions) === null || _c === void 0 ? void 0 : _c.folderPath);
|
|
449
450
|
if (result.success && result.chunk) {
|
|
450
451
|
getStaticPropsChunk = result.chunk;
|
|
451
452
|
// Track the first data source info for wrapping dataSourceData expressions
|
|
@@ -500,7 +501,7 @@ var createNextPagesDataSourcePlugin = function () {
|
|
|
500
501
|
}
|
|
501
502
|
}
|
|
502
503
|
}
|
|
503
|
-
catch (
|
|
504
|
+
catch (_g) {
|
|
504
505
|
// Ignore errors in parsing existing props
|
|
505
506
|
}
|
|
506
507
|
}
|
|
@@ -605,6 +606,13 @@ var createNextPagesDataSourcePlugin = function () {
|
|
|
605
606
|
chunks.push(getStaticPropsChunk);
|
|
606
607
|
}
|
|
607
608
|
}
|
|
609
|
+
// For pages with dynamicRouteAttribute and dynamic SEO references,
|
|
610
|
+
// add the SEO-referenced fields as direct page props from the fetched data.
|
|
611
|
+
// The head config plugin generates props?.metaTitle from refPath: ['metaTitle'],
|
|
612
|
+
// so we need those fields at the top level of props.
|
|
613
|
+
if (((_e = uidl.outputOptions) === null || _e === void 0 ? void 0 : _e.dynamicRouteAttribute) && getStaticPropsChunk && uidl.seo) {
|
|
614
|
+
addDynamicSeoPropsToGetStaticProps(uidl.seo, getStaticPropsChunk);
|
|
615
|
+
}
|
|
608
616
|
paginationPlugin = (0, pagination_plugin_1.createNextArrayMapperPaginationPlugin)();
|
|
609
617
|
return [2 /*return*/, paginationPlugin(structure)];
|
|
610
618
|
});
|
|
@@ -612,6 +620,101 @@ var createNextPagesDataSourcePlugin = function () {
|
|
|
612
620
|
return nextPagesDataSourcePlugin;
|
|
613
621
|
};
|
|
614
622
|
exports.createNextPagesDataSourcePlugin = createNextPagesDataSourcePlugin;
|
|
623
|
+
/**
|
|
624
|
+
* Extracts dynamic SEO reference paths from UIDLComponentSEO and returns the
|
|
625
|
+
* refPath arrays for prop-based dynamic references.
|
|
626
|
+
*/
|
|
627
|
+
function extractDynamicSeoRefPaths(seo) {
|
|
628
|
+
var paths = [];
|
|
629
|
+
var extractFromValue = function (value) {
|
|
630
|
+
var _a;
|
|
631
|
+
if (typeof value === 'object' &&
|
|
632
|
+
value !== null &&
|
|
633
|
+
'type' in value &&
|
|
634
|
+
value.type === 'dynamic') {
|
|
635
|
+
var dynRef = value;
|
|
636
|
+
if (dynRef.content.referenceType === 'prop' && ((_a = dynRef.content.refPath) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
637
|
+
paths.push(dynRef.content.refPath);
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
};
|
|
641
|
+
if (seo.title) {
|
|
642
|
+
extractFromValue(seo.title);
|
|
643
|
+
}
|
|
644
|
+
if (seo.metaTags) {
|
|
645
|
+
seo.metaTags.forEach(function (tag) {
|
|
646
|
+
Object.values(tag).forEach(extractFromValue);
|
|
647
|
+
});
|
|
648
|
+
}
|
|
649
|
+
return paths;
|
|
650
|
+
}
|
|
651
|
+
/**
|
|
652
|
+
* For pages with dynamic route attributes and dynamic SEO prop references,
|
|
653
|
+
* augments the getStaticProps return to include SEO fields extracted from
|
|
654
|
+
* the first fetched entity. This enables server-side SEO resolution.
|
|
655
|
+
*/
|
|
656
|
+
function addDynamicSeoPropsToGetStaticProps(seo, getStaticPropsChunk) {
|
|
657
|
+
var seoRefPaths = extractDynamicSeoRefPaths(seo);
|
|
658
|
+
if (seoRefPaths.length === 0) {
|
|
659
|
+
return;
|
|
660
|
+
}
|
|
661
|
+
try {
|
|
662
|
+
var exportDecl = getStaticPropsChunk.content;
|
|
663
|
+
if (!(exportDecl === null || exportDecl === void 0 ? void 0 : exportDecl.declaration) || exportDecl.declaration.type !== 'FunctionDeclaration') {
|
|
664
|
+
return;
|
|
665
|
+
}
|
|
666
|
+
var funcBody = exportDecl.declaration.body;
|
|
667
|
+
var tryStmt = funcBody.body.find(function (s) { return s.type === 'TryStatement'; });
|
|
668
|
+
if (!tryStmt) {
|
|
669
|
+
return;
|
|
670
|
+
}
|
|
671
|
+
var returnStmt = tryStmt.block.body.find(function (s) { return s.type === 'ReturnStatement'; });
|
|
672
|
+
if (!(returnStmt === null || returnStmt === void 0 ? void 0 : returnStmt.argument) || returnStmt.argument.type !== 'ObjectExpression') {
|
|
673
|
+
return;
|
|
674
|
+
}
|
|
675
|
+
var propsProperty = returnStmt.argument.properties.find(function (p) {
|
|
676
|
+
var _a, _b;
|
|
677
|
+
return p.type === 'ObjectProperty' &&
|
|
678
|
+
(((_a = p.key) === null || _a === void 0 ? void 0 : _a.name) === 'props' ||
|
|
679
|
+
((_b = p.key) === null || _b === void 0 ? void 0 : _b.value) === 'props');
|
|
680
|
+
});
|
|
681
|
+
if (!propsProperty || propsProperty.value.type !== 'ObjectExpression') {
|
|
682
|
+
return;
|
|
683
|
+
}
|
|
684
|
+
var propsObj = propsProperty.value;
|
|
685
|
+
// Find the first data prop (non-spread, non-string-keyed) as the source entity.
|
|
686
|
+
// Exclude spread elements and meta spreads that the data-source plugin adds.
|
|
687
|
+
var firstDataProp = propsObj.properties.find(function (p) { var _a; return p.type === 'ObjectProperty' && ((_a = p.key) === null || _a === void 0 ? void 0 : _a.name) !== undefined; });
|
|
688
|
+
if (!firstDataProp) {
|
|
689
|
+
return;
|
|
690
|
+
}
|
|
691
|
+
var addedSeoFields = new Set();
|
|
692
|
+
for (var _i = 0, seoRefPaths_1 = seoRefPaths; _i < seoRefPaths_1.length; _i++) {
|
|
693
|
+
var refPath = seoRefPaths_1[_i];
|
|
694
|
+
var fieldName = refPath[refPath.length - 1];
|
|
695
|
+
if (addedSeoFields.has(fieldName)) {
|
|
696
|
+
continue;
|
|
697
|
+
}
|
|
698
|
+
addedSeoFields.add(fieldName);
|
|
699
|
+
var memberExpr = types.cloneNode(firstDataProp.value, true);
|
|
700
|
+
// If the prop value is an array (no index access), get the first element
|
|
701
|
+
var valueStr = JSON.stringify(firstDataProp.value);
|
|
702
|
+
var hasIndexAccess = valueStr.includes('"computed":true');
|
|
703
|
+
if (!hasIndexAccess) {
|
|
704
|
+
memberExpr = types.optionalMemberExpression(memberExpr, types.numericLiteral(0), true, true);
|
|
705
|
+
}
|
|
706
|
+
for (var _a = 0, refPath_1 = refPath; _a < refPath_1.length; _a++) {
|
|
707
|
+
var segment = refPath_1[_a];
|
|
708
|
+
memberExpr = types.optionalMemberExpression(memberExpr, types.identifier(segment), false, true);
|
|
709
|
+
}
|
|
710
|
+
var seoValue = types.logicalExpression('??', memberExpr, types.stringLiteral(''));
|
|
711
|
+
propsObj.properties.push(types.objectProperty(types.identifier(fieldName), seoValue));
|
|
712
|
+
}
|
|
713
|
+
}
|
|
714
|
+
catch (_b) {
|
|
715
|
+
// If AST manipulation fails, skip SEO prop injection silently
|
|
716
|
+
}
|
|
717
|
+
}
|
|
615
718
|
// Helper function to stringify complex params (sorts, filters) in DataProvider components
|
|
616
719
|
function stringifyComplexParamsInDataProviders(componentChunk) {
|
|
617
720
|
if (!componentChunk || !componentChunk.content) {
|