@teleporthq/teleport-plugin-next-data-source 0.42.8 → 0.42.10
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__/csv-header-detection.test.ts +212 -0
- package/__tests__/validation.test.ts +33 -2
- package/dist/cjs/data-source-fetchers.d.ts +2 -2
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
- package/dist/cjs/data-source-fetchers.js +30 -7
- 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 +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 +23 -3
- 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 +6 -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 +3 -3
- package/dist/cjs/fetchers/mariadb.js.map +1 -1
- package/dist/cjs/fetchers/mongodb.d.ts +1 -1
- package/dist/cjs/fetchers/mongodb.d.ts.map +1 -1
- package/dist/cjs/fetchers/mongodb.js +11 -3
- 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 +3 -3
- 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 +2 -2
- 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 +2 -2
- 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/fetchers/utils/header-detection.d.ts +2 -0
- package/dist/cjs/fetchers/utils/header-detection.d.ts.map +1 -0
- package/dist/cjs/fetchers/utils/header-detection.js +8 -0
- package/dist/cjs/fetchers/utils/header-detection.js.map +1 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +168 -4
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/pagination-plugin.d.ts.map +1 -1
- package/dist/cjs/pagination-plugin.js +320 -65
- package/dist/cjs/pagination-plugin.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +3 -0
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +218 -46
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/data-source-fetchers.d.ts +2 -2
- package/dist/esm/data-source-fetchers.d.ts.map +1 -1
- package/dist/esm/data-source-fetchers.js +29 -6
- 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 +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 +23 -3
- 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 +6 -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 +4 -4
- package/dist/esm/fetchers/mariadb.js.map +1 -1
- package/dist/esm/fetchers/mongodb.d.ts +1 -1
- package/dist/esm/fetchers/mongodb.d.ts.map +1 -1
- package/dist/esm/fetchers/mongodb.js +12 -4
- 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 +4 -4
- 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 +3 -3
- 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 +3 -3
- 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/fetchers/utils/header-detection.d.ts +2 -0
- package/dist/esm/fetchers/utils/header-detection.d.ts.map +1 -0
- package/dist/esm/fetchers/utils/header-detection.js +4 -0
- package/dist/esm/fetchers/utils/header-detection.js.map +1 -0
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +169 -5
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/pagination-plugin.d.ts.map +1 -1
- package/dist/esm/pagination-plugin.js +320 -65
- package/dist/esm/pagination-plugin.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +3 -0
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +214 -45
- package/dist/esm/utils.js.map +1 -1
- package/package.json +2 -2
- package/src/data-source-fetchers.ts +29 -13
- package/src/fetchers/airtable.ts +81 -31
- package/src/fetchers/clickhouse.ts +88 -19
- package/src/fetchers/csv-file.ts +256 -27
- package/src/fetchers/firestore.ts +65 -13
- package/src/fetchers/google-sheets.ts +243 -26
- package/src/fetchers/javascript.ts +106 -23
- package/src/fetchers/mariadb.ts +85 -26
- package/src/fetchers/mongodb.ts +156 -37
- package/src/fetchers/mysql.ts +86 -26
- package/src/fetchers/postgresql.ts +89 -27
- package/src/fetchers/redis.ts +43 -5
- package/src/fetchers/redshift.ts +87 -18
- package/src/fetchers/rest-api.ts +105 -24
- package/src/fetchers/static-collection.ts +100 -18
- package/src/fetchers/supabase.ts +178 -54
- package/src/fetchers/turso.ts +87 -18
- package/src/fetchers/utils/header-detection.ts +200 -0
- package/src/index.ts +248 -2
- package/src/pagination-plugin.ts +708 -191
- package/src/utils.ts +374 -38
package/src/utils.ts
CHANGED
|
@@ -440,10 +440,10 @@ export default dataSourceModule.handler
|
|
|
440
440
|
return
|
|
441
441
|
}
|
|
442
442
|
|
|
443
|
-
// Generate fetcher code
|
|
443
|
+
// Generate fetcher code for API route (exports just the handler)
|
|
444
444
|
let fetcherCode: string
|
|
445
445
|
try {
|
|
446
|
-
fetcherCode = generateDataSourceFetcherWithCore(dataSource, tableName || '')
|
|
446
|
+
fetcherCode = generateDataSourceFetcherWithCore(dataSource, tableName || '', true)
|
|
447
447
|
} catch (error) {
|
|
448
448
|
return
|
|
449
449
|
}
|
|
@@ -510,6 +510,153 @@ export const replaceSecretReference = (
|
|
|
510
510
|
}
|
|
511
511
|
}
|
|
512
512
|
|
|
513
|
+
export const generateSafeJSONParseCode = (): string => {
|
|
514
|
+
return `const safeJSONParse = (value) => {
|
|
515
|
+
if (!value) return value
|
|
516
|
+
if (typeof value === 'object') return value
|
|
517
|
+
try {
|
|
518
|
+
return JSON.parse(value)
|
|
519
|
+
} catch (e) {
|
|
520
|
+
console.warn('Failed to parse JSON:', e)
|
|
521
|
+
return value
|
|
522
|
+
}
|
|
523
|
+
}`
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
export const generateDateFormatterCode = (): string => {
|
|
527
|
+
return `const formatDateValue = (date) => {
|
|
528
|
+
const options = {
|
|
529
|
+
year: 'numeric',
|
|
530
|
+
month: 'short',
|
|
531
|
+
day: 'numeric',
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
const timeOptions = {
|
|
535
|
+
hour: '2-digit',
|
|
536
|
+
minute: '2-digit',
|
|
537
|
+
}
|
|
538
|
+
|
|
539
|
+
const hasTime = date.getHours() !== 0 || date.getMinutes() !== 0 || date.getSeconds() !== 0
|
|
540
|
+
|
|
541
|
+
if (hasTime) {
|
|
542
|
+
return date.toLocaleString('en-US', { ...options, ...timeOptions })
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
return date.toLocaleDateString('en-US', options)
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const dateReplacer = (key, value) => {
|
|
549
|
+
if (value instanceof Date) {
|
|
550
|
+
return formatDateValue(value)
|
|
551
|
+
}
|
|
552
|
+
return value
|
|
553
|
+
}`
|
|
554
|
+
}
|
|
555
|
+
|
|
556
|
+
export const generateSortFilterHelperCode = (): string => {
|
|
557
|
+
return `function getNestedValue(obj, path) {
|
|
558
|
+
if (!obj || typeof obj !== 'object') return undefined
|
|
559
|
+
const keys = path.split('.')
|
|
560
|
+
let value = obj
|
|
561
|
+
for (const key of keys) {
|
|
562
|
+
if (value && typeof value === 'object' && key in value) {
|
|
563
|
+
value = value[key]
|
|
564
|
+
} else {
|
|
565
|
+
return undefined
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
return value
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
function compareValues(value, target, operand) {
|
|
572
|
+
if (value === null || value === undefined || target === null || target === undefined) {
|
|
573
|
+
switch (operand) {
|
|
574
|
+
case '=': return value == target
|
|
575
|
+
case '!=': return value != target
|
|
576
|
+
default: return false
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
|
|
580
|
+
if (typeof value === 'number' && typeof target === 'number') {
|
|
581
|
+
switch (operand) {
|
|
582
|
+
case '=': return value === target
|
|
583
|
+
case '!=': return value !== target
|
|
584
|
+
case '>': return value > target
|
|
585
|
+
case '>=': return value >= target
|
|
586
|
+
case '<': return value < target
|
|
587
|
+
case '<=': return value <= target
|
|
588
|
+
default: return true
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
|
|
592
|
+
if (typeof value === 'string' && typeof target === 'string') {
|
|
593
|
+
switch (operand) {
|
|
594
|
+
case '=': return value === target
|
|
595
|
+
case '!=': return value !== target
|
|
596
|
+
case '>': return value > target
|
|
597
|
+
case '>=': return value >= target
|
|
598
|
+
case '<': return value < target
|
|
599
|
+
case '<=': return value <= target
|
|
600
|
+
default: return true
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
const valueDate = value instanceof Date ? value : (typeof value === 'string' ? new Date(value) : null)
|
|
605
|
+
const targetDate = target instanceof Date ? target : (typeof target === 'string' ? new Date(target) : null)
|
|
606
|
+
if (valueDate && targetDate && !isNaN(valueDate.getTime()) && !isNaN(targetDate.getTime())) {
|
|
607
|
+
const valueTime = valueDate.getTime()
|
|
608
|
+
const targetTime = targetDate.getTime()
|
|
609
|
+
switch (operand) {
|
|
610
|
+
case '=': return valueTime === targetTime
|
|
611
|
+
case '!=': return valueTime !== targetTime
|
|
612
|
+
case '>': return valueTime > targetTime
|
|
613
|
+
case '>=': return valueTime >= targetTime
|
|
614
|
+
case '<': return valueTime < targetTime
|
|
615
|
+
case '<=': return valueTime <= targetTime
|
|
616
|
+
default: return true
|
|
617
|
+
}
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
if (Array.isArray(value) && Array.isArray(target)) {
|
|
621
|
+
switch (operand) {
|
|
622
|
+
case '=': return JSON.stringify(value) === JSON.stringify(target)
|
|
623
|
+
case '!=': return JSON.stringify(value) !== JSON.stringify(target)
|
|
624
|
+
case '>': return value.length > target.length
|
|
625
|
+
case '>=': return value.length >= target.length
|
|
626
|
+
case '<': return value.length < target.length
|
|
627
|
+
case '<=': return value.length <= target.length
|
|
628
|
+
default: return true
|
|
629
|
+
}
|
|
630
|
+
}
|
|
631
|
+
|
|
632
|
+
if (Array.isArray(value) && !Array.isArray(target)) {
|
|
633
|
+
switch (operand) {
|
|
634
|
+
case '=': return value.includes(target)
|
|
635
|
+
case '!=': return !value.includes(target)
|
|
636
|
+
default: return false
|
|
637
|
+
}
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
if (typeof value === 'object' && typeof target === 'object') {
|
|
641
|
+
switch (operand) {
|
|
642
|
+
case '=': return JSON.stringify(value) === JSON.stringify(target)
|
|
643
|
+
case '!=': return JSON.stringify(value) !== JSON.stringify(target)
|
|
644
|
+
default: return false
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
|
|
648
|
+
switch (operand) {
|
|
649
|
+
case '=': return value == target
|
|
650
|
+
case '!=': return value != target
|
|
651
|
+
case '>': return Number(value) > Number(target)
|
|
652
|
+
case '>=': return Number(value) >= Number(target)
|
|
653
|
+
case '<': return Number(value) < Number(target)
|
|
654
|
+
case '<=': return Number(value) <= Number(target)
|
|
655
|
+
default: return true
|
|
656
|
+
}
|
|
657
|
+
}`
|
|
658
|
+
}
|
|
659
|
+
|
|
513
660
|
export const sanitizeNumericParam = (value: unknown, defaultValue: number = 0): number => {
|
|
514
661
|
if (typeof value === 'number' && !isNaN(value) && isFinite(value)) {
|
|
515
662
|
return Math.max(0, Math.floor(value))
|
|
@@ -602,19 +749,42 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
602
749
|
return { success: false }
|
|
603
750
|
}
|
|
604
751
|
|
|
605
|
-
// Generate prop key
|
|
752
|
+
// Generate prop key using renderPropIdentifier and resource ID for uniqueness
|
|
753
|
+
// This ensures each DataProvider instance gets its own fetch and initialData even when
|
|
754
|
+
// multiple instances share the same renderPropIdentifier but have different params (sorts, filters)
|
|
755
|
+
const renderPropIdentifier = node.content?.renderPropIdentifier
|
|
756
|
+
// tslint:disable-next-line:no-any
|
|
757
|
+
const resourceId = (node.content?.resource as any)?.id
|
|
758
|
+
|
|
759
|
+
// Always generate a unique base key from dataSourceId and tableName
|
|
606
760
|
const sanitizedDsName = StringUtils.dashCaseToCamelCase(
|
|
607
761
|
sanitizeFileName(dataSource.name || dataSourceId)
|
|
608
762
|
)
|
|
609
763
|
const sanitizedTableName = StringUtils.dashCaseToCamelCase(
|
|
610
764
|
sanitizeFileName(tableName || 'data')
|
|
611
765
|
)
|
|
612
|
-
const
|
|
766
|
+
const baseKey = `${sanitizedDsName}_${sanitizedTableName}_data`
|
|
767
|
+
|
|
768
|
+
let propKey: string
|
|
769
|
+
if (renderPropIdentifier && resourceId) {
|
|
770
|
+
// Include resource ID to differentiate between same renderProp but different params
|
|
771
|
+
const sanitizedResourceId = StringUtils.dashCaseToCamelCase(
|
|
772
|
+
sanitizeFileName(resourceId).replace(/^TQ_/, '')
|
|
773
|
+
)
|
|
774
|
+
propKey = `${renderPropIdentifier}_${sanitizedResourceId}`
|
|
775
|
+
} else {
|
|
776
|
+
// Use base key for uniqueness (even if renderPropIdentifier exists, base key ensures uniqueness across different data sources)
|
|
777
|
+
propKey = baseKey
|
|
778
|
+
}
|
|
613
779
|
|
|
614
|
-
// Find
|
|
780
|
+
// Find matching JSX nodes for this data source
|
|
781
|
+
// Strategy depends on whether we have a unique resource ID:
|
|
782
|
+
// - With resource ID: each UIDL node updates ONE JSX element (unique data per element)
|
|
783
|
+
// - Without resource ID: one UIDL node can update ALL matching JSX elements (shared data)
|
|
784
|
+
const hasUniqueResourceId = !!resourceId
|
|
615
785
|
const matchingJsxNodes: types.JSXElement[] = []
|
|
616
786
|
|
|
617
|
-
// Helper function to recursively traverse the AST and find
|
|
787
|
+
// Helper function to recursively traverse the AST and find matching JSX elements
|
|
618
788
|
const traverseAST = (astNode: any) => {
|
|
619
789
|
if (!astNode || typeof astNode !== 'object') {
|
|
620
790
|
return
|
|
@@ -630,7 +800,25 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
630
800
|
(attr as types.JSXAttribute).name.name === 'resourceDefinition'
|
|
631
801
|
) as types.JSXAttribute | undefined
|
|
632
802
|
|
|
803
|
+
const nameAttr = attrs.find(
|
|
804
|
+
(attr) =>
|
|
805
|
+
(attr as any).type === 'JSXAttribute' &&
|
|
806
|
+
(attr as types.JSXAttribute).name.name === 'name'
|
|
807
|
+
) as types.JSXAttribute | undefined
|
|
808
|
+
|
|
809
|
+
const paramsAttr = attrs.find(
|
|
810
|
+
(attr) =>
|
|
811
|
+
(attr as any).type === 'JSXAttribute' &&
|
|
812
|
+
(attr as types.JSXAttribute).name.name === 'params'
|
|
813
|
+
) as types.JSXAttribute | undefined
|
|
814
|
+
|
|
815
|
+
// Check if this node already has initialData - if so, skip it
|
|
816
|
+
const hasInitialData = attrs.some(
|
|
817
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'initialData'
|
|
818
|
+
)
|
|
819
|
+
|
|
633
820
|
if (
|
|
821
|
+
!hasInitialData &&
|
|
634
822
|
resourceDefAttr &&
|
|
635
823
|
resourceDefAttr.value &&
|
|
636
824
|
resourceDefAttr.value.type === 'JSXExpressionContainer'
|
|
@@ -643,27 +831,131 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
643
831
|
// tslint:disable-next-line:no-any
|
|
644
832
|
const idValue = (idProp as any)?.value?.value
|
|
645
833
|
|
|
646
|
-
// Also check tableName to ensure we're matching the right data source
|
|
647
834
|
// tslint:disable-next-line:no-any
|
|
648
835
|
const tableNameProp = props.find((p: any) => p.key?.value === 'tableName')
|
|
649
836
|
// tslint:disable-next-line:no-any
|
|
650
837
|
const tableNameValue = (tableNameProp as any)?.value?.value
|
|
651
838
|
|
|
652
|
-
|
|
839
|
+
// Match by name attribute to ensure we get the right renderPropIdentifier
|
|
840
|
+
let nameMatches = true
|
|
841
|
+
if (renderPropIdentifier && nameAttr && nameAttr.value) {
|
|
842
|
+
nameMatches = false
|
|
843
|
+
if (nameAttr.value.type === 'StringLiteral') {
|
|
844
|
+
nameMatches = nameAttr.value.value === renderPropIdentifier
|
|
845
|
+
} else if (nameAttr.value.type === 'JSXExpressionContainer') {
|
|
846
|
+
const nameExpr = nameAttr.value.expression
|
|
847
|
+
if (nameExpr.type === 'StringLiteral') {
|
|
848
|
+
nameMatches = nameExpr.value === renderPropIdentifier
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
|
|
853
|
+
// Check if params match (for nodes with the same renderPropIdentifier but different params)
|
|
854
|
+
// We only compare simple numeric params that affect data fetching (limit, page, perPage)
|
|
855
|
+
// Other params like queryColumns are handled by pagination plugin and don't affect matching
|
|
856
|
+
// tslint:disable-next-line:no-any
|
|
857
|
+
const nodeResourceParams = (node.content as any).resource?.params || {}
|
|
858
|
+
let paramsMatch = true
|
|
859
|
+
|
|
860
|
+
// Extract numeric params from JSX that affect data fetching
|
|
861
|
+
const jsxLimitParams: Record<string, number | undefined> = {}
|
|
862
|
+
let jsxHasParams = false
|
|
863
|
+
|
|
864
|
+
if (
|
|
865
|
+
paramsAttr &&
|
|
866
|
+
paramsAttr.value &&
|
|
867
|
+
paramsAttr.value.type === 'JSXExpressionContainer'
|
|
868
|
+
) {
|
|
869
|
+
jsxHasParams = true
|
|
870
|
+
const paramsExpr = paramsAttr.value.expression
|
|
871
|
+
let objExpr: types.ObjectExpression | null = null
|
|
872
|
+
|
|
873
|
+
// Handle useMemo wrapper
|
|
874
|
+
if (
|
|
875
|
+
paramsExpr.type === 'CallExpression' &&
|
|
876
|
+
(paramsExpr.callee as any).name === 'useMemo'
|
|
877
|
+
) {
|
|
878
|
+
const memoArgs = paramsExpr.arguments
|
|
879
|
+
if (memoArgs.length > 0 && memoArgs[0].type === 'ArrowFunctionExpression') {
|
|
880
|
+
const arrowFunc = memoArgs[0] as types.ArrowFunctionExpression
|
|
881
|
+
if (arrowFunc.body.type === 'ObjectExpression') {
|
|
882
|
+
objExpr = arrowFunc.body as types.ObjectExpression
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
} else if (paramsExpr.type === 'ObjectExpression') {
|
|
886
|
+
// Direct object expression (before useMemo wrapping)
|
|
887
|
+
objExpr = paramsExpr as types.ObjectExpression
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
if (objExpr) {
|
|
891
|
+
objExpr.properties.forEach((prop: any) => {
|
|
892
|
+
if (prop.type === 'ObjectProperty') {
|
|
893
|
+
let key: string | undefined
|
|
894
|
+
if (prop.key.type === 'Identifier') {
|
|
895
|
+
key = prop.key.name
|
|
896
|
+
} else if (prop.key.type === 'StringLiteral') {
|
|
897
|
+
key = prop.key.value
|
|
898
|
+
}
|
|
899
|
+
|
|
900
|
+
// Only extract limit param - this is what differentiates data fetches
|
|
901
|
+
if (key === 'limit' && prop.value.type === 'NumericLiteral') {
|
|
902
|
+
jsxLimitParams[key] = prop.value.value
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
})
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
|
|
909
|
+
// Extract limit from resource params
|
|
910
|
+
const resourceLimit =
|
|
911
|
+
nodeResourceParams.limit?.type === 'static'
|
|
912
|
+
? nodeResourceParams.limit.content
|
|
913
|
+
: undefined
|
|
914
|
+
|
|
915
|
+
// Compare limit params - this determines if data fetches are equivalent
|
|
916
|
+
const jsxLimit = jsxLimitParams.limit
|
|
917
|
+
if (jsxLimit !== undefined || resourceLimit !== undefined) {
|
|
918
|
+
// If either has limit, both must have the same limit value
|
|
919
|
+
paramsMatch = jsxLimit === resourceLimit
|
|
920
|
+
} else if (!jsxHasParams && Object.keys(nodeResourceParams).length > 0) {
|
|
921
|
+
// JSX has no params but resource has params - check if resource only has non-limit params
|
|
922
|
+
// If resource has limit, no match; otherwise match
|
|
923
|
+
paramsMatch = resourceLimit === undefined
|
|
924
|
+
} else if (jsxHasParams && Object.keys(nodeResourceParams).length === 0) {
|
|
925
|
+
// JSX has params but resource doesn't - check if JSX only has non-limit params
|
|
926
|
+
// If JSX has limit, no match; otherwise match
|
|
927
|
+
paramsMatch = jsxLimit === undefined
|
|
928
|
+
}
|
|
929
|
+
// else: both don't have params or both have equivalent limit - match
|
|
930
|
+
|
|
931
|
+
// Collect matching nodes that don't have initialData yet and have matching params
|
|
932
|
+
if (
|
|
933
|
+
idValue === dataSourceId &&
|
|
934
|
+
tableNameValue === tableName &&
|
|
935
|
+
nameMatches &&
|
|
936
|
+
paramsMatch
|
|
937
|
+
) {
|
|
653
938
|
matchingJsxNodes.push(jsxElement)
|
|
939
|
+
// If we have a unique resource ID, stop after finding the first match
|
|
940
|
+
// Otherwise, collect all matching nodes
|
|
941
|
+
if (hasUniqueResourceId) {
|
|
942
|
+
return
|
|
943
|
+
}
|
|
654
944
|
}
|
|
655
945
|
}
|
|
656
946
|
}
|
|
657
947
|
}
|
|
658
948
|
|
|
659
|
-
// Recursively traverse all properties
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
949
|
+
// Recursively traverse all properties (unless we already found a match with unique resource ID)
|
|
950
|
+
if (!hasUniqueResourceId || matchingJsxNodes.length === 0) {
|
|
951
|
+
for (const key in astNode) {
|
|
952
|
+
if (astNode.hasOwnProperty(key)) {
|
|
953
|
+
const value = astNode[key]
|
|
954
|
+
if (Array.isArray(value)) {
|
|
955
|
+
value.forEach((item) => traverseAST(item))
|
|
956
|
+
} else if (typeof value === 'object') {
|
|
957
|
+
traverseAST(value)
|
|
958
|
+
}
|
|
667
959
|
}
|
|
668
960
|
}
|
|
669
961
|
}
|
|
@@ -672,12 +964,13 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
672
964
|
// Traverse the entire component AST content
|
|
673
965
|
traverseAST(componentChunk.content)
|
|
674
966
|
|
|
675
|
-
if
|
|
676
|
-
|
|
677
|
-
|
|
967
|
+
// Even if all JSX nodes already have initialData, we should still add the fetch to getStaticProps
|
|
968
|
+
// This handles cases where multiple data-source-list nodes share the same renderPropIdentifier
|
|
969
|
+
// but have different params (e.g., one with limit, one without)
|
|
970
|
+
const nodesToUpdate: types.JSXElement[] = matchingJsxNodes
|
|
678
971
|
|
|
679
|
-
// Update
|
|
680
|
-
for (const jsxNode of
|
|
972
|
+
// Update all target JSX nodes with initialData (only those that don't already have it)
|
|
973
|
+
for (const jsxNode of nodesToUpdate) {
|
|
681
974
|
// For SSR/SSG with initialData, rename 'children' to 'renderSuccess'
|
|
682
975
|
const childrenAttrIndex = jsxNode.openingElement.attributes.findIndex(
|
|
683
976
|
(attr) => (attr as types.JSXAttribute).name?.name === 'children'
|
|
@@ -717,6 +1010,7 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
717
1010
|
)
|
|
718
1011
|
jsxNode.openingElement.attributes.push(persistDataAttr)
|
|
719
1012
|
}
|
|
1013
|
+
// End of target node processing
|
|
720
1014
|
|
|
721
1015
|
// Generate safe file name for the fetcher
|
|
722
1016
|
const fileName = generateSafeFileName(dataSourceType, tableName || 'data', dataSourceId)
|
|
@@ -767,23 +1061,64 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
767
1061
|
let astValue: any
|
|
768
1062
|
|
|
769
1063
|
if (value.content === null || value.content === undefined) {
|
|
770
|
-
|
|
1064
|
+
// Skip null/undefined values entirely
|
|
1065
|
+
return
|
|
771
1066
|
} else if (Array.isArray(value.content)) {
|
|
772
|
-
//
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
if (typeof item === 'string') {
|
|
776
|
-
return types.stringLiteral(item)
|
|
777
|
-
}
|
|
778
|
-
if (typeof item === 'number') {
|
|
779
|
-
return types.numericLiteral(item)
|
|
780
|
-
}
|
|
781
|
-
if (typeof item === 'boolean') {
|
|
782
|
-
return types.booleanLiteral(item)
|
|
783
|
-
}
|
|
784
|
-
return types.nullLiteral()
|
|
785
|
-
})
|
|
1067
|
+
// Filter out null/undefined values from the array
|
|
1068
|
+
const validItems = value.content.filter(
|
|
1069
|
+
(item: any) => item !== null && item !== undefined
|
|
786
1070
|
)
|
|
1071
|
+
|
|
1072
|
+
// Skip the array entirely if it's empty or only had null values
|
|
1073
|
+
if (validItems.length === 0) {
|
|
1074
|
+
return
|
|
1075
|
+
}
|
|
1076
|
+
|
|
1077
|
+
// For sorts, filters, and queryColumns, stringify the array for consistency with API handler
|
|
1078
|
+
if (key === 'sorts' || key === 'filters' || key === 'queryColumns') {
|
|
1079
|
+
const arrayExpr = types.arrayExpression(
|
|
1080
|
+
validItems.map((item: any) => {
|
|
1081
|
+
if (typeof item === 'string') {
|
|
1082
|
+
return types.stringLiteral(item)
|
|
1083
|
+
}
|
|
1084
|
+
if (typeof item === 'number') {
|
|
1085
|
+
return types.numericLiteral(item)
|
|
1086
|
+
}
|
|
1087
|
+
if (typeof item === 'boolean') {
|
|
1088
|
+
return types.booleanLiteral(item)
|
|
1089
|
+
}
|
|
1090
|
+
if (typeof item === 'object' && item !== null) {
|
|
1091
|
+
return ASTUtils.objectToObjectExpression(item)
|
|
1092
|
+
}
|
|
1093
|
+
return types.nullLiteral()
|
|
1094
|
+
})
|
|
1095
|
+
)
|
|
1096
|
+
// Wrap in JSON.stringify()
|
|
1097
|
+
astValue = types.callExpression(
|
|
1098
|
+
types.memberExpression(types.identifier('JSON'), types.identifier('stringify')),
|
|
1099
|
+
[arrayExpr]
|
|
1100
|
+
)
|
|
1101
|
+
} else {
|
|
1102
|
+
// Handle other array values normally
|
|
1103
|
+
astValue = types.arrayExpression(
|
|
1104
|
+
validItems.map((item: any) => {
|
|
1105
|
+
if (typeof item === 'string') {
|
|
1106
|
+
return types.stringLiteral(item)
|
|
1107
|
+
}
|
|
1108
|
+
if (typeof item === 'number') {
|
|
1109
|
+
return types.numericLiteral(item)
|
|
1110
|
+
}
|
|
1111
|
+
if (typeof item === 'boolean') {
|
|
1112
|
+
return types.booleanLiteral(item)
|
|
1113
|
+
}
|
|
1114
|
+
if (typeof item === 'object' && item !== null) {
|
|
1115
|
+
// Handle object items (like sort/filter objects)
|
|
1116
|
+
return ASTUtils.objectToObjectExpression(item)
|
|
1117
|
+
}
|
|
1118
|
+
return types.nullLiteral()
|
|
1119
|
+
})
|
|
1120
|
+
)
|
|
1121
|
+
}
|
|
787
1122
|
} else if (typeof value.content === 'string') {
|
|
788
1123
|
astValue = types.stringLiteral(value.content)
|
|
789
1124
|
} else if (typeof value.content === 'number') {
|
|
@@ -791,7 +1126,8 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
791
1126
|
} else if (typeof value.content === 'boolean') {
|
|
792
1127
|
astValue = types.booleanLiteral(value.content)
|
|
793
1128
|
} else {
|
|
794
|
-
|
|
1129
|
+
// Skip other null-like values
|
|
1130
|
+
return
|
|
795
1131
|
}
|
|
796
1132
|
|
|
797
1133
|
paramsProperties.push(types.objectProperty(types.stringLiteral(key), astValue))
|
|
@@ -902,7 +1238,7 @@ export const extractDataSourceIntoGetStaticProps = (
|
|
|
902
1238
|
const propsValue = propsObject.value as types.ObjectExpression
|
|
903
1239
|
|
|
904
1240
|
// Check if propKey already exists in the parallel fetch metadata
|
|
905
|
-
const parallelFetchMeta = getStaticPropsChunk.meta?.
|
|
1241
|
+
const parallelFetchMeta = getStaticPropsChunk.meta?.parallelFetchData as
|
|
906
1242
|
| ParallelFetchMeta
|
|
907
1243
|
| undefined
|
|
908
1244
|
const existingInFetchMeta = parallelFetchMeta?.names.includes(propKey)
|