@teleporthq/teleport-plugin-next-data-source 0.40.15
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/ARRAY_MAPPER_PAGINATION.md +1128 -0
- package/LICENSE +21 -0
- package/README.md +40 -0
- package/SEARCH_IMPLEMENTATION_SUMMARY.md +983 -0
- package/__tests__/fetchers.test.ts +545 -0
- package/__tests__/integration.test.ts +561 -0
- package/__tests__/mocks.ts +241 -0
- package/__tests__/pagination.test.ts +31 -0
- package/__tests__/plugin.test.ts +577 -0
- package/__tests__/utils.test.ts +430 -0
- package/__tests__/validation.test.ts +348 -0
- package/dist/cjs/array-mapper-pagination.d.ts +32 -0
- package/dist/cjs/array-mapper-pagination.d.ts.map +1 -0
- package/dist/cjs/array-mapper-pagination.js +77 -0
- package/dist/cjs/array-mapper-pagination.js.map +1 -0
- package/dist/cjs/count-fetchers.d.ts +12 -0
- package/dist/cjs/count-fetchers.d.ts.map +1 -0
- package/dist/cjs/count-fetchers.js +46 -0
- package/dist/cjs/count-fetchers.js.map +1 -0
- package/dist/cjs/data-source-fetchers.d.ts +14 -0
- package/dist/cjs/data-source-fetchers.d.ts.map +1 -0
- package/dist/cjs/data-source-fetchers.js +185 -0
- package/dist/cjs/data-source-fetchers.js.map +1 -0
- package/dist/cjs/fetchers/airtable.d.ts +6 -0
- package/dist/cjs/fetchers/airtable.d.ts.map +1 -0
- package/dist/cjs/fetchers/airtable.js +27 -0
- package/dist/cjs/fetchers/airtable.js.map +1 -0
- package/dist/cjs/fetchers/clickhouse.d.ts +6 -0
- package/dist/cjs/fetchers/clickhouse.d.ts.map +1 -0
- package/dist/cjs/fetchers/clickhouse.js +29 -0
- package/dist/cjs/fetchers/clickhouse.js.map +1 -0
- package/dist/cjs/fetchers/csv-file.d.ts +7 -0
- package/dist/cjs/fetchers/csv-file.d.ts.map +1 -0
- package/dist/cjs/fetchers/csv-file.js +36 -0
- package/dist/cjs/fetchers/csv-file.js.map +1 -0
- package/dist/cjs/fetchers/firestore.d.ts +6 -0
- package/dist/cjs/fetchers/firestore.d.ts.map +1 -0
- package/dist/cjs/fetchers/firestore.js +35 -0
- package/dist/cjs/fetchers/firestore.js.map +1 -0
- package/dist/cjs/fetchers/google-sheets.d.ts +6 -0
- package/dist/cjs/fetchers/google-sheets.d.ts.map +1 -0
- package/dist/cjs/fetchers/google-sheets.js +30 -0
- package/dist/cjs/fetchers/google-sheets.js.map +1 -0
- package/dist/cjs/fetchers/index.d.ts +17 -0
- package/dist/cjs/fetchers/index.d.ts.map +1 -0
- package/dist/cjs/fetchers/index.js +56 -0
- package/dist/cjs/fetchers/index.js.map +1 -0
- package/dist/cjs/fetchers/javascript.d.ts +7 -0
- package/dist/cjs/fetchers/javascript.d.ts.map +1 -0
- package/dist/cjs/fetchers/javascript.js +40 -0
- package/dist/cjs/fetchers/javascript.js.map +1 -0
- package/dist/cjs/fetchers/mariadb.d.ts +3 -0
- package/dist/cjs/fetchers/mariadb.d.ts.map +1 -0
- package/dist/cjs/fetchers/mariadb.js +23 -0
- package/dist/cjs/fetchers/mariadb.js.map +1 -0
- package/dist/cjs/fetchers/mongodb.d.ts +7 -0
- package/dist/cjs/fetchers/mongodb.d.ts.map +1 -0
- package/dist/cjs/fetchers/mongodb.js +52 -0
- package/dist/cjs/fetchers/mongodb.js.map +1 -0
- package/dist/cjs/fetchers/mysql.d.ts +3 -0
- package/dist/cjs/fetchers/mysql.d.ts.map +1 -0
- package/dist/cjs/fetchers/mysql.js +30 -0
- package/dist/cjs/fetchers/mysql.js.map +1 -0
- package/dist/cjs/fetchers/postgresql.d.ts +3 -0
- package/dist/cjs/fetchers/postgresql.d.ts.map +1 -0
- package/dist/cjs/fetchers/postgresql.js +25 -0
- package/dist/cjs/fetchers/postgresql.js.map +1 -0
- package/dist/cjs/fetchers/redis.d.ts +6 -0
- package/dist/cjs/fetchers/redis.d.ts.map +1 -0
- package/dist/cjs/fetchers/redis.js +46 -0
- package/dist/cjs/fetchers/redis.js.map +1 -0
- package/dist/cjs/fetchers/redshift.d.ts +2 -0
- package/dist/cjs/fetchers/redshift.d.ts.map +1 -0
- package/dist/cjs/fetchers/redshift.js +24 -0
- package/dist/cjs/fetchers/redshift.js.map +1 -0
- package/dist/cjs/fetchers/rest-api.d.ts +6 -0
- package/dist/cjs/fetchers/rest-api.d.ts.map +1 -0
- package/dist/cjs/fetchers/rest-api.js +58 -0
- package/dist/cjs/fetchers/rest-api.js.map +1 -0
- package/dist/cjs/fetchers/static-collection.d.ts +7 -0
- package/dist/cjs/fetchers/static-collection.d.ts.map +1 -0
- package/dist/cjs/fetchers/static-collection.js +24 -0
- package/dist/cjs/fetchers/static-collection.js.map +1 -0
- package/dist/cjs/fetchers/supabase.d.ts +7 -0
- package/dist/cjs/fetchers/supabase.d.ts.map +1 -0
- package/dist/cjs/fetchers/supabase.js +42 -0
- package/dist/cjs/fetchers/supabase.js.map +1 -0
- package/dist/cjs/fetchers/turso.d.ts +6 -0
- package/dist/cjs/fetchers/turso.d.ts.map +1 -0
- package/dist/cjs/fetchers/turso.js +25 -0
- package/dist/cjs/fetchers/turso.js.map +1 -0
- package/dist/cjs/index.d.ts +9 -0
- package/dist/cjs/index.d.ts.map +1 -0
- package/dist/cjs/index.js +325 -0
- package/dist/cjs/index.js.map +1 -0
- package/dist/cjs/pagination-plugin.d.ts +5 -0
- package/dist/cjs/pagination-plugin.d.ts.map +1 -0
- package/dist/cjs/pagination-plugin.js +1484 -0
- package/dist/cjs/pagination-plugin.js.map +1 -0
- package/dist/cjs/pagination-with-count.d.ts +6 -0
- package/dist/cjs/pagination-with-count.d.ts.map +1 -0
- package/dist/cjs/pagination-with-count.js +63 -0
- package/dist/cjs/pagination-with-count.js.map +1 -0
- package/dist/cjs/tsconfig.tsbuildinfo +1 -0
- package/dist/cjs/utils.d.ts +31 -0
- package/dist/cjs/utils.d.ts.map +1 -0
- package/dist/cjs/utils.js +763 -0
- package/dist/cjs/utils.js.map +1 -0
- package/dist/cjs/validation.d.ts +5 -0
- package/dist/cjs/validation.d.ts.map +1 -0
- package/dist/cjs/validation.js +29 -0
- package/dist/cjs/validation.js.map +1 -0
- package/dist/esm/array-mapper-pagination.d.ts +32 -0
- package/dist/esm/array-mapper-pagination.d.ts.map +1 -0
- package/dist/esm/array-mapper-pagination.js +72 -0
- package/dist/esm/array-mapper-pagination.js.map +1 -0
- package/dist/esm/count-fetchers.d.ts +12 -0
- package/dist/esm/count-fetchers.d.ts.map +1 -0
- package/dist/esm/count-fetchers.js +35 -0
- package/dist/esm/count-fetchers.js.map +1 -0
- package/dist/esm/data-source-fetchers.d.ts +14 -0
- package/dist/esm/data-source-fetchers.d.ts.map +1 -0
- package/dist/esm/data-source-fetchers.js +179 -0
- package/dist/esm/data-source-fetchers.js.map +1 -0
- package/dist/esm/fetchers/airtable.d.ts +6 -0
- package/dist/esm/fetchers/airtable.d.ts.map +1 -0
- package/dist/esm/fetchers/airtable.js +22 -0
- package/dist/esm/fetchers/airtable.js.map +1 -0
- package/dist/esm/fetchers/clickhouse.d.ts +6 -0
- package/dist/esm/fetchers/clickhouse.d.ts.map +1 -0
- package/dist/esm/fetchers/clickhouse.js +24 -0
- package/dist/esm/fetchers/clickhouse.js.map +1 -0
- package/dist/esm/fetchers/csv-file.d.ts +7 -0
- package/dist/esm/fetchers/csv-file.d.ts.map +1 -0
- package/dist/esm/fetchers/csv-file.js +30 -0
- package/dist/esm/fetchers/csv-file.js.map +1 -0
- package/dist/esm/fetchers/firestore.d.ts +6 -0
- package/dist/esm/fetchers/firestore.d.ts.map +1 -0
- package/dist/esm/fetchers/firestore.js +30 -0
- package/dist/esm/fetchers/firestore.js.map +1 -0
- package/dist/esm/fetchers/google-sheets.d.ts +6 -0
- package/dist/esm/fetchers/google-sheets.d.ts.map +1 -0
- package/dist/esm/fetchers/google-sheets.js +25 -0
- package/dist/esm/fetchers/google-sheets.js.map +1 -0
- package/dist/esm/fetchers/index.d.ts +17 -0
- package/dist/esm/fetchers/index.d.ts.map +1 -0
- package/dist/esm/fetchers/index.js +17 -0
- package/dist/esm/fetchers/index.js.map +1 -0
- package/dist/esm/fetchers/javascript.d.ts +7 -0
- package/dist/esm/fetchers/javascript.d.ts.map +1 -0
- package/dist/esm/fetchers/javascript.js +34 -0
- package/dist/esm/fetchers/javascript.js.map +1 -0
- package/dist/esm/fetchers/mariadb.d.ts +3 -0
- package/dist/esm/fetchers/mariadb.d.ts.map +1 -0
- package/dist/esm/fetchers/mariadb.js +18 -0
- package/dist/esm/fetchers/mariadb.js.map +1 -0
- package/dist/esm/fetchers/mongodb.d.ts +7 -0
- package/dist/esm/fetchers/mongodb.d.ts.map +1 -0
- package/dist/esm/fetchers/mongodb.js +46 -0
- package/dist/esm/fetchers/mongodb.js.map +1 -0
- package/dist/esm/fetchers/mysql.d.ts +3 -0
- package/dist/esm/fetchers/mysql.d.ts.map +1 -0
- package/dist/esm/fetchers/mysql.js +25 -0
- package/dist/esm/fetchers/mysql.js.map +1 -0
- package/dist/esm/fetchers/postgresql.d.ts +3 -0
- package/dist/esm/fetchers/postgresql.d.ts.map +1 -0
- package/dist/esm/fetchers/postgresql.js +20 -0
- package/dist/esm/fetchers/postgresql.js.map +1 -0
- package/dist/esm/fetchers/redis.d.ts +6 -0
- package/dist/esm/fetchers/redis.d.ts.map +1 -0
- package/dist/esm/fetchers/redis.js +41 -0
- package/dist/esm/fetchers/redis.js.map +1 -0
- package/dist/esm/fetchers/redshift.d.ts +2 -0
- package/dist/esm/fetchers/redshift.d.ts.map +1 -0
- package/dist/esm/fetchers/redshift.js +20 -0
- package/dist/esm/fetchers/redshift.js.map +1 -0
- package/dist/esm/fetchers/rest-api.d.ts +6 -0
- package/dist/esm/fetchers/rest-api.d.ts.map +1 -0
- package/dist/esm/fetchers/rest-api.js +53 -0
- package/dist/esm/fetchers/rest-api.js.map +1 -0
- package/dist/esm/fetchers/static-collection.d.ts +7 -0
- package/dist/esm/fetchers/static-collection.d.ts.map +1 -0
- package/dist/esm/fetchers/static-collection.js +18 -0
- package/dist/esm/fetchers/static-collection.js.map +1 -0
- package/dist/esm/fetchers/supabase.d.ts +7 -0
- package/dist/esm/fetchers/supabase.d.ts.map +1 -0
- package/dist/esm/fetchers/supabase.js +36 -0
- package/dist/esm/fetchers/supabase.js.map +1 -0
- package/dist/esm/fetchers/turso.d.ts +6 -0
- package/dist/esm/fetchers/turso.d.ts.map +1 -0
- package/dist/esm/fetchers/turso.js +20 -0
- package/dist/esm/fetchers/turso.js.map +1 -0
- package/dist/esm/index.d.ts +9 -0
- package/dist/esm/index.d.ts.map +1 -0
- package/dist/esm/index.js +306 -0
- package/dist/esm/index.js.map +1 -0
- package/dist/esm/pagination-plugin.d.ts +5 -0
- package/dist/esm/pagination-plugin.d.ts.map +1 -0
- package/dist/esm/pagination-plugin.js +1457 -0
- package/dist/esm/pagination-plugin.js.map +1 -0
- package/dist/esm/pagination-with-count.d.ts +6 -0
- package/dist/esm/pagination-with-count.d.ts.map +1 -0
- package/dist/esm/pagination-with-count.js +34 -0
- package/dist/esm/pagination-with-count.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -0
- package/dist/esm/utils.d.ts +31 -0
- package/dist/esm/utils.d.ts.map +1 -0
- package/dist/esm/utils.js +722 -0
- package/dist/esm/utils.js.map +1 -0
- package/dist/esm/validation.d.ts +5 -0
- package/dist/esm/validation.d.ts.map +1 -0
- package/dist/esm/validation.js +25 -0
- package/dist/esm/validation.js.map +1 -0
- package/package.json +33 -0
- package/src/array-mapper-pagination.ts +113 -0
- package/src/count-fetchers.ts +99 -0
- package/src/data-source-fetchers.ts +313 -0
- package/src/fetchers/airtable.ts +153 -0
- package/src/fetchers/clickhouse.ts +127 -0
- package/src/fetchers/csv-file.ts +163 -0
- package/src/fetchers/firestore.ts +138 -0
- package/src/fetchers/google-sheets.ts +189 -0
- package/src/fetchers/index.ts +32 -0
- package/src/fetchers/javascript.ts +150 -0
- package/src/fetchers/mariadb.ts +230 -0
- package/src/fetchers/mongodb.ts +239 -0
- package/src/fetchers/mysql.ts +237 -0
- package/src/fetchers/postgresql.ts +247 -0
- package/src/fetchers/redis.ts +152 -0
- package/src/fetchers/redshift.ts +138 -0
- package/src/fetchers/rest-api.ts +148 -0
- package/src/fetchers/static-collection.ts +149 -0
- package/src/fetchers/supabase.ts +246 -0
- package/src/fetchers/turso.ts +131 -0
- package/src/index.ts +352 -0
- package/src/pagination-plugin.ts +2335 -0
- package/src/pagination-with-count.ts +89 -0
- package/src/utils.ts +1013 -0
- package/src/validation.ts +32 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,561 @@
|
|
|
1
|
+
import {
|
|
2
|
+
extractDataSourceIntoNextAPIFolder,
|
|
3
|
+
extractDataSourceIntoGetStaticProps,
|
|
4
|
+
} from '../src/utils'
|
|
5
|
+
import * as types from '@babel/types'
|
|
6
|
+
import { FileType } from '@teleporthq/teleport-types'
|
|
7
|
+
import {
|
|
8
|
+
createPostgreSQLDataSource,
|
|
9
|
+
createJavaScriptDataSource,
|
|
10
|
+
createDataSourceNode,
|
|
11
|
+
createComponentChunk,
|
|
12
|
+
createMockJSXElementWithResourceDef,
|
|
13
|
+
} from './mocks'
|
|
14
|
+
|
|
15
|
+
describe('extractDataSourceIntoNextAPIFolder', () => {
|
|
16
|
+
it('creates API route file with correct structure', () => {
|
|
17
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
18
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
19
|
+
|
|
20
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-test', 'users')
|
|
21
|
+
const componentChunk = createComponentChunk()
|
|
22
|
+
componentChunk.meta!.nodesLookup = { 'ds-test': jsxElement }
|
|
23
|
+
componentChunk.content = jsxElement
|
|
24
|
+
|
|
25
|
+
const extractedResources: Record<string, any> = {}
|
|
26
|
+
|
|
27
|
+
extractDataSourceIntoNextAPIFolder(
|
|
28
|
+
node,
|
|
29
|
+
{ 'ds-test': dataSource },
|
|
30
|
+
componentChunk,
|
|
31
|
+
extractedResources
|
|
32
|
+
)
|
|
33
|
+
|
|
34
|
+
const apiFiles = Object.keys(extractedResources).filter((key) => key.startsWith('api/'))
|
|
35
|
+
expect(apiFiles.length).toBeGreaterThan(0)
|
|
36
|
+
|
|
37
|
+
const apiFile = extractedResources[apiFiles[0]]
|
|
38
|
+
expect(apiFile.fileType).toBe(FileType.JS)
|
|
39
|
+
expect(apiFile.path).toContain('api')
|
|
40
|
+
expect(apiFile.content).toContain('export default')
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
it('adds fetchData attribute to JSX element', () => {
|
|
44
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
45
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
46
|
+
|
|
47
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-test', 'users')
|
|
48
|
+
const componentChunk = createComponentChunk()
|
|
49
|
+
componentChunk.meta!.nodesLookup = { 'ds-test': jsxElement }
|
|
50
|
+
componentChunk.content = jsxElement
|
|
51
|
+
|
|
52
|
+
const extractedResources: Record<string, any> = {}
|
|
53
|
+
|
|
54
|
+
extractDataSourceIntoNextAPIFolder(
|
|
55
|
+
node,
|
|
56
|
+
{ 'ds-test': dataSource },
|
|
57
|
+
componentChunk,
|
|
58
|
+
extractedResources
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
const fetchDataAttr = jsxElement.openingElement.attributes.find(
|
|
62
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'fetchData'
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
expect(fetchDataAttr).toBeDefined()
|
|
66
|
+
})
|
|
67
|
+
|
|
68
|
+
it('handles resource params in fetch URL', () => {
|
|
69
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
70
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql', true)
|
|
71
|
+
|
|
72
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-test', 'users')
|
|
73
|
+
const componentChunk = createComponentChunk()
|
|
74
|
+
componentChunk.meta!.nodesLookup = { 'ds-test': jsxElement }
|
|
75
|
+
componentChunk.content = jsxElement
|
|
76
|
+
|
|
77
|
+
const extractedResources: Record<string, any> = {}
|
|
78
|
+
|
|
79
|
+
extractDataSourceIntoNextAPIFolder(
|
|
80
|
+
node,
|
|
81
|
+
{ 'ds-test': dataSource },
|
|
82
|
+
componentChunk,
|
|
83
|
+
extractedResources
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
const fetchDataAttr = jsxElement.openingElement.attributes.find(
|
|
87
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'fetchData'
|
|
88
|
+
) as types.JSXAttribute
|
|
89
|
+
|
|
90
|
+
expect(fetchDataAttr).toBeDefined()
|
|
91
|
+
const arrowFunc = (fetchDataAttr.value as types.JSXExpressionContainer)
|
|
92
|
+
.expression as types.ArrowFunctionExpression
|
|
93
|
+
expect(arrowFunc.params.length).toBeGreaterThan(0)
|
|
94
|
+
})
|
|
95
|
+
|
|
96
|
+
it('re-uses existing utils file for API route', () => {
|
|
97
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
98
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
99
|
+
|
|
100
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-test', 'users')
|
|
101
|
+
const componentChunk = createComponentChunk()
|
|
102
|
+
componentChunk.meta!.nodesLookup = { 'ds-test': jsxElement }
|
|
103
|
+
componentChunk.content = jsxElement
|
|
104
|
+
|
|
105
|
+
const extractedResources = {
|
|
106
|
+
'utils/postgresql-users-ds-test': {
|
|
107
|
+
fileName: 'postgresql-users-ds-test',
|
|
108
|
+
fileType: FileType.JS,
|
|
109
|
+
path: ['utils', 'data-sources'],
|
|
110
|
+
content: 'existing content',
|
|
111
|
+
},
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
extractDataSourceIntoNextAPIFolder(
|
|
115
|
+
node,
|
|
116
|
+
{ 'ds-test': dataSource },
|
|
117
|
+
componentChunk,
|
|
118
|
+
extractedResources
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const apiFile = Object.values(extractedResources).find((file: any) =>
|
|
122
|
+
file.path?.includes('api')
|
|
123
|
+
) as any
|
|
124
|
+
|
|
125
|
+
expect(apiFile).toBeDefined()
|
|
126
|
+
expect(apiFile.content).toContain('import dataSourceModule')
|
|
127
|
+
})
|
|
128
|
+
|
|
129
|
+
it('handles invalid node content gracefully', () => {
|
|
130
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
131
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
132
|
+
delete (node.content as any).resourceDefinition
|
|
133
|
+
|
|
134
|
+
const componentChunk = createComponentChunk()
|
|
135
|
+
const extractedResources: Record<string, any> = {}
|
|
136
|
+
|
|
137
|
+
expect(() => {
|
|
138
|
+
extractDataSourceIntoNextAPIFolder(
|
|
139
|
+
node,
|
|
140
|
+
{ 'ds-test': dataSource },
|
|
141
|
+
componentChunk,
|
|
142
|
+
extractedResources
|
|
143
|
+
)
|
|
144
|
+
}).not.toThrow()
|
|
145
|
+
|
|
146
|
+
expect(Object.keys(extractedResources)).toHaveLength(0)
|
|
147
|
+
})
|
|
148
|
+
|
|
149
|
+
it('handles missing data source gracefully', () => {
|
|
150
|
+
const node = createDataSourceNode('ds-missing', 'users', 'postgresql')
|
|
151
|
+
|
|
152
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-missing', 'users')
|
|
153
|
+
const componentChunk = createComponentChunk()
|
|
154
|
+
componentChunk.meta!.nodesLookup = { 'ds-missing': jsxElement }
|
|
155
|
+
componentChunk.content = jsxElement
|
|
156
|
+
|
|
157
|
+
const extractedResources: Record<string, any> = {}
|
|
158
|
+
|
|
159
|
+
expect(() => {
|
|
160
|
+
extractDataSourceIntoNextAPIFolder(node, {}, componentChunk, extractedResources)
|
|
161
|
+
}).not.toThrow()
|
|
162
|
+
|
|
163
|
+
expect(Object.keys(extractedResources)).toHaveLength(0)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
it('handles JSX element not found gracefully', () => {
|
|
167
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
168
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
169
|
+
|
|
170
|
+
const componentChunk = createComponentChunk()
|
|
171
|
+
componentChunk.meta!.nodesLookup = {}
|
|
172
|
+
|
|
173
|
+
const extractedResources: Record<string, any> = {}
|
|
174
|
+
|
|
175
|
+
expect(() => {
|
|
176
|
+
extractDataSourceIntoNextAPIFolder(
|
|
177
|
+
node,
|
|
178
|
+
{ 'ds-test': dataSource },
|
|
179
|
+
componentChunk,
|
|
180
|
+
extractedResources
|
|
181
|
+
)
|
|
182
|
+
}).not.toThrow()
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
it('skips nodes that already have fetchData attribute', () => {
|
|
186
|
+
const dataSource = createPostgreSQLDataSource('ds-test')
|
|
187
|
+
const node = createDataSourceNode('ds-test', 'users', 'postgresql')
|
|
188
|
+
|
|
189
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-test', 'users')
|
|
190
|
+
jsxElement.openingElement.attributes.push(
|
|
191
|
+
types.jsxAttribute(
|
|
192
|
+
types.jsxIdentifier('fetchData'),
|
|
193
|
+
types.jsxExpressionContainer(types.arrowFunctionExpression([], types.blockStatement([])))
|
|
194
|
+
)
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
const componentChunk = createComponentChunk()
|
|
198
|
+
componentChunk.meta!.nodesLookup = { 'ds-test': jsxElement }
|
|
199
|
+
componentChunk.content = jsxElement
|
|
200
|
+
|
|
201
|
+
const extractedResources: Record<string, any> = {}
|
|
202
|
+
const initialAttrCount = jsxElement.openingElement.attributes.length
|
|
203
|
+
|
|
204
|
+
extractDataSourceIntoNextAPIFolder(
|
|
205
|
+
node,
|
|
206
|
+
{ 'ds-test': dataSource },
|
|
207
|
+
componentChunk,
|
|
208
|
+
extractedResources
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
expect(jsxElement.openingElement.attributes.length).toBe(initialAttrCount)
|
|
212
|
+
expect(Object.keys(extractedResources)).toHaveLength(0)
|
|
213
|
+
})
|
|
214
|
+
})
|
|
215
|
+
|
|
216
|
+
describe('extractDataSourceIntoGetStaticProps', () => {
|
|
217
|
+
it('creates utils file and getStaticProps chunk', () => {
|
|
218
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
219
|
+
const node = createDataSourceNode('ds-js', 'data', 'javascript', false)
|
|
220
|
+
|
|
221
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
222
|
+
const componentChunk = createComponentChunk()
|
|
223
|
+
componentChunk.meta!.nodesLookup = { 'ds-js': jsxElement }
|
|
224
|
+
// Wrap in AST structure so traverseAST can find it
|
|
225
|
+
componentChunk.content = types.arrowFunctionExpression(
|
|
226
|
+
[],
|
|
227
|
+
types.blockStatement([types.returnStatement(jsxElement)])
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
const extractedResources: Record<string, any> = {}
|
|
231
|
+
const chunks: any[] = []
|
|
232
|
+
const dependencies: Record<string, any> = {}
|
|
233
|
+
|
|
234
|
+
const result = extractDataSourceIntoGetStaticProps(
|
|
235
|
+
node,
|
|
236
|
+
{ 'ds-js': dataSource },
|
|
237
|
+
componentChunk,
|
|
238
|
+
null,
|
|
239
|
+
chunks,
|
|
240
|
+
extractedResources,
|
|
241
|
+
dependencies
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
expect(result.success).toBe(true)
|
|
245
|
+
expect(result.chunk).toBeDefined()
|
|
246
|
+
|
|
247
|
+
const utilsFiles = Object.keys(extractedResources).filter((key) => key.startsWith('utils/'))
|
|
248
|
+
expect(utilsFiles.length).toBeGreaterThan(0)
|
|
249
|
+
|
|
250
|
+
expect(Object.keys(dependencies).length).toBeGreaterThan(0)
|
|
251
|
+
})
|
|
252
|
+
|
|
253
|
+
it('adds initialData to all matching JSX elements', () => {
|
|
254
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
255
|
+
const node = createDataSourceNode('ds-js', 'data', 'javascript', false)
|
|
256
|
+
|
|
257
|
+
const jsxElement1 = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
258
|
+
const jsxElement2 = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
259
|
+
|
|
260
|
+
const componentChunk = createComponentChunk()
|
|
261
|
+
componentChunk.content = types.jsxFragment(
|
|
262
|
+
types.jsxOpeningFragment(),
|
|
263
|
+
types.jsxClosingFragment(),
|
|
264
|
+
[jsxElement1, jsxElement2]
|
|
265
|
+
)
|
|
266
|
+
|
|
267
|
+
const extractedResources: Record<string, any> = {}
|
|
268
|
+
const chunks: any[] = []
|
|
269
|
+
const dependencies: Record<string, any> = {}
|
|
270
|
+
|
|
271
|
+
extractDataSourceIntoGetStaticProps(
|
|
272
|
+
node,
|
|
273
|
+
{ 'ds-js': dataSource },
|
|
274
|
+
componentChunk,
|
|
275
|
+
null,
|
|
276
|
+
chunks,
|
|
277
|
+
extractedResources,
|
|
278
|
+
dependencies
|
|
279
|
+
)
|
|
280
|
+
|
|
281
|
+
const hasInitialData1 = jsxElement1.openingElement.attributes.some(
|
|
282
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'initialData'
|
|
283
|
+
)
|
|
284
|
+
const hasInitialData2 = jsxElement2.openingElement.attributes.some(
|
|
285
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'initialData'
|
|
286
|
+
)
|
|
287
|
+
|
|
288
|
+
expect(hasInitialData1).toBe(true)
|
|
289
|
+
expect(hasInitialData2).toBe(true)
|
|
290
|
+
})
|
|
291
|
+
|
|
292
|
+
it('updates existing getStaticProps chunk', () => {
|
|
293
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
294
|
+
const node = createDataSourceNode('ds-js', 'data', 'javascript', false)
|
|
295
|
+
|
|
296
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
297
|
+
const componentChunk = createComponentChunk()
|
|
298
|
+
componentChunk.meta!.nodesLookup = { 'ds-js': jsxElement }
|
|
299
|
+
// Wrap in AST structure so traverseAST can find it
|
|
300
|
+
componentChunk.content = types.arrowFunctionExpression(
|
|
301
|
+
[],
|
|
302
|
+
types.blockStatement([types.returnStatement(jsxElement)])
|
|
303
|
+
)
|
|
304
|
+
|
|
305
|
+
const tryBlock = types.tryStatement(
|
|
306
|
+
types.blockStatement([
|
|
307
|
+
types.returnStatement(
|
|
308
|
+
types.objectExpression([
|
|
309
|
+
types.objectProperty(types.identifier('props'), types.objectExpression([])),
|
|
310
|
+
types.objectProperty(types.identifier('revalidate'), types.numericLiteral(1)),
|
|
311
|
+
])
|
|
312
|
+
),
|
|
313
|
+
]),
|
|
314
|
+
types.catchClause(
|
|
315
|
+
types.identifier('error'),
|
|
316
|
+
types.blockStatement([
|
|
317
|
+
types.returnStatement(
|
|
318
|
+
types.objectExpression([
|
|
319
|
+
types.objectProperty(types.identifier('props'), types.objectExpression([])),
|
|
320
|
+
])
|
|
321
|
+
),
|
|
322
|
+
])
|
|
323
|
+
)
|
|
324
|
+
)
|
|
325
|
+
|
|
326
|
+
const existingChunk = {
|
|
327
|
+
name: 'getStaticProps',
|
|
328
|
+
type: 'ast' as const,
|
|
329
|
+
fileType: FileType.JS,
|
|
330
|
+
content: types.exportNamedDeclaration(
|
|
331
|
+
types.functionDeclaration(
|
|
332
|
+
types.identifier('getStaticProps'),
|
|
333
|
+
[types.identifier('context')],
|
|
334
|
+
types.blockStatement([tryBlock]),
|
|
335
|
+
false,
|
|
336
|
+
true
|
|
337
|
+
)
|
|
338
|
+
),
|
|
339
|
+
linkAfter: ['jsx-component'],
|
|
340
|
+
meta: {},
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
const extractedResources: Record<string, any> = {}
|
|
344
|
+
const chunks: any[] = []
|
|
345
|
+
const dependencies: Record<string, any> = {}
|
|
346
|
+
|
|
347
|
+
const result = extractDataSourceIntoGetStaticProps(
|
|
348
|
+
node,
|
|
349
|
+
{ 'ds-js': dataSource },
|
|
350
|
+
componentChunk,
|
|
351
|
+
existingChunk,
|
|
352
|
+
chunks,
|
|
353
|
+
extractedResources,
|
|
354
|
+
dependencies
|
|
355
|
+
)
|
|
356
|
+
|
|
357
|
+
expect(result.success).toBe(true)
|
|
358
|
+
expect(result.chunk).toBe(existingChunk)
|
|
359
|
+
})
|
|
360
|
+
|
|
361
|
+
it('handles parallel fetch with multiple data sources', () => {
|
|
362
|
+
const dataSource1 = createJavaScriptDataSource('ds-js-1')
|
|
363
|
+
const dataSource2 = createJavaScriptDataSource('ds-js-2')
|
|
364
|
+
|
|
365
|
+
const node1 = createDataSourceNode('ds-js-1', 'data1', 'javascript', false)
|
|
366
|
+
const node2 = createDataSourceNode('ds-js-2', 'data2', 'javascript', false)
|
|
367
|
+
|
|
368
|
+
const jsxElement1 = createMockJSXElementWithResourceDef('ds-js-1', 'data1', 'javascript')
|
|
369
|
+
const jsxElement2 = createMockJSXElementWithResourceDef('ds-js-2', 'data2', 'javascript')
|
|
370
|
+
|
|
371
|
+
const componentChunk = createComponentChunk()
|
|
372
|
+
componentChunk.content = types.jsxFragment(
|
|
373
|
+
types.jsxOpeningFragment(),
|
|
374
|
+
types.jsxClosingFragment(),
|
|
375
|
+
[jsxElement1, jsxElement2]
|
|
376
|
+
)
|
|
377
|
+
|
|
378
|
+
const extractedResources: Record<string, any> = {}
|
|
379
|
+
const chunks: any[] = []
|
|
380
|
+
const dependencies: Record<string, any> = {}
|
|
381
|
+
|
|
382
|
+
extractDataSourceIntoGetStaticProps(
|
|
383
|
+
node1,
|
|
384
|
+
{ 'ds-js-1': dataSource1, 'ds-js-2': dataSource2 },
|
|
385
|
+
componentChunk,
|
|
386
|
+
null,
|
|
387
|
+
chunks,
|
|
388
|
+
extractedResources,
|
|
389
|
+
dependencies
|
|
390
|
+
)
|
|
391
|
+
|
|
392
|
+
const getStaticPropsChunk = chunks.find((c) => c.name === 'getStaticProps')
|
|
393
|
+
|
|
394
|
+
extractDataSourceIntoGetStaticProps(
|
|
395
|
+
node2,
|
|
396
|
+
{ 'ds-js-1': dataSource1, 'ds-js-2': dataSource2 },
|
|
397
|
+
componentChunk,
|
|
398
|
+
getStaticPropsChunk,
|
|
399
|
+
chunks,
|
|
400
|
+
extractedResources,
|
|
401
|
+
dependencies
|
|
402
|
+
)
|
|
403
|
+
|
|
404
|
+
expect(getStaticPropsChunk.meta.parallelFetchData).toBeDefined()
|
|
405
|
+
expect(getStaticPropsChunk.meta.parallelFetchData.names.length).toBeGreaterThanOrEqual(2)
|
|
406
|
+
})
|
|
407
|
+
|
|
408
|
+
it('renames children to renderSuccess for SSR', () => {
|
|
409
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
410
|
+
const node = createDataSourceNode('ds-js', 'data', 'javascript', false)
|
|
411
|
+
|
|
412
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
413
|
+
const initialAttrCount = jsxElement.openingElement.attributes.length
|
|
414
|
+
jsxElement.openingElement.attributes.push(
|
|
415
|
+
types.jsxAttribute(
|
|
416
|
+
types.jsxIdentifier('children'),
|
|
417
|
+
types.jsxExpressionContainer(types.arrowFunctionExpression([], types.blockStatement([])))
|
|
418
|
+
)
|
|
419
|
+
)
|
|
420
|
+
|
|
421
|
+
const componentChunk = createComponentChunk()
|
|
422
|
+
componentChunk.meta!.nodesLookup = { 'ds-js': jsxElement }
|
|
423
|
+
// Wrap in AST structure so traverseAST can find it
|
|
424
|
+
componentChunk.content = types.arrowFunctionExpression(
|
|
425
|
+
[],
|
|
426
|
+
types.blockStatement([types.returnStatement(jsxElement)])
|
|
427
|
+
)
|
|
428
|
+
|
|
429
|
+
const extractedResources: Record<string, any> = {}
|
|
430
|
+
const chunks: any[] = []
|
|
431
|
+
const dependencies: Record<string, any> = {}
|
|
432
|
+
|
|
433
|
+
extractDataSourceIntoGetStaticProps(
|
|
434
|
+
node,
|
|
435
|
+
{ 'ds-js': dataSource },
|
|
436
|
+
componentChunk,
|
|
437
|
+
null,
|
|
438
|
+
chunks,
|
|
439
|
+
extractedResources,
|
|
440
|
+
dependencies
|
|
441
|
+
)
|
|
442
|
+
|
|
443
|
+
const hasChildren = jsxElement.openingElement.attributes.some(
|
|
444
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'children'
|
|
445
|
+
)
|
|
446
|
+
const hasRenderSuccess = jsxElement.openingElement.attributes.some(
|
|
447
|
+
(attr) => (attr as types.JSXAttribute).name?.name === 'renderSuccess'
|
|
448
|
+
)
|
|
449
|
+
|
|
450
|
+
// Should have renamed children to renderSuccess
|
|
451
|
+
expect(hasChildren).toBe(false)
|
|
452
|
+
expect(hasRenderSuccess).toBe(true)
|
|
453
|
+
// Should have added initialData and persistDataDuringLoading
|
|
454
|
+
expect(jsxElement.openingElement.attributes.length).toBeGreaterThan(initialAttrCount)
|
|
455
|
+
})
|
|
456
|
+
|
|
457
|
+
it('handles invalid resource definition gracefully', () => {
|
|
458
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
459
|
+
const node = createDataSourceNode('ds-js', '', 'javascript', false)
|
|
460
|
+
delete (node.content as any).resourceDefinition
|
|
461
|
+
|
|
462
|
+
const componentChunk = createComponentChunk()
|
|
463
|
+
const extractedResources: Record<string, any> = {}
|
|
464
|
+
const chunks: any[] = []
|
|
465
|
+
const dependencies: Record<string, any> = {}
|
|
466
|
+
|
|
467
|
+
const result = extractDataSourceIntoGetStaticProps(
|
|
468
|
+
node,
|
|
469
|
+
{ 'ds-js': dataSource },
|
|
470
|
+
componentChunk,
|
|
471
|
+
null,
|
|
472
|
+
chunks,
|
|
473
|
+
extractedResources,
|
|
474
|
+
dependencies
|
|
475
|
+
)
|
|
476
|
+
|
|
477
|
+
expect(result.success).toBe(false)
|
|
478
|
+
})
|
|
479
|
+
|
|
480
|
+
it('handles missing data source gracefully', () => {
|
|
481
|
+
const node = createDataSourceNode('ds-missing', '', 'javascript', false)
|
|
482
|
+
|
|
483
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-missing', '', 'javascript')
|
|
484
|
+
const componentChunk = createComponentChunk()
|
|
485
|
+
componentChunk.meta!.nodesLookup = { 'ds-missing': jsxElement }
|
|
486
|
+
componentChunk.content = jsxElement
|
|
487
|
+
|
|
488
|
+
const extractedResources: Record<string, any> = {}
|
|
489
|
+
const chunks: any[] = []
|
|
490
|
+
const dependencies: Record<string, any> = {}
|
|
491
|
+
|
|
492
|
+
const result = extractDataSourceIntoGetStaticProps(
|
|
493
|
+
node,
|
|
494
|
+
{},
|
|
495
|
+
componentChunk,
|
|
496
|
+
null,
|
|
497
|
+
chunks,
|
|
498
|
+
extractedResources,
|
|
499
|
+
dependencies
|
|
500
|
+
)
|
|
501
|
+
|
|
502
|
+
expect(result.success).toBe(false)
|
|
503
|
+
})
|
|
504
|
+
|
|
505
|
+
it('does not duplicate prop in return object', () => {
|
|
506
|
+
const dataSource = createJavaScriptDataSource('ds-js')
|
|
507
|
+
const node = createDataSourceNode('ds-js', 'data', 'javascript', false)
|
|
508
|
+
|
|
509
|
+
const jsxElement = createMockJSXElementWithResourceDef('ds-js', 'data', 'javascript')
|
|
510
|
+
const componentChunk = createComponentChunk()
|
|
511
|
+
componentChunk.content = jsxElement
|
|
512
|
+
|
|
513
|
+
const extractedResources: Record<string, any> = {}
|
|
514
|
+
const chunks: any[] = []
|
|
515
|
+
const dependencies: Record<string, any> = {}
|
|
516
|
+
|
|
517
|
+
extractDataSourceIntoGetStaticProps(
|
|
518
|
+
node,
|
|
519
|
+
{ 'ds-js': dataSource },
|
|
520
|
+
componentChunk,
|
|
521
|
+
null,
|
|
522
|
+
chunks,
|
|
523
|
+
extractedResources,
|
|
524
|
+
dependencies
|
|
525
|
+
)
|
|
526
|
+
|
|
527
|
+
const getStaticPropsChunk = chunks.find((c) => c.name === 'getStaticProps')
|
|
528
|
+
|
|
529
|
+
extractDataSourceIntoGetStaticProps(
|
|
530
|
+
node,
|
|
531
|
+
{ 'ds-js': dataSource },
|
|
532
|
+
componentChunk,
|
|
533
|
+
getStaticPropsChunk,
|
|
534
|
+
chunks,
|
|
535
|
+
extractedResources,
|
|
536
|
+
dependencies
|
|
537
|
+
)
|
|
538
|
+
|
|
539
|
+
const declaration = (getStaticPropsChunk.content as types.ExportNamedDeclaration)
|
|
540
|
+
.declaration as types.FunctionDeclaration
|
|
541
|
+
const tryBlock = declaration.body.body[0] as types.TryStatement
|
|
542
|
+
const returnStmt = tryBlock.block.body.find(
|
|
543
|
+
(stmt) => stmt.type === 'ReturnStatement'
|
|
544
|
+
) as types.ReturnStatement
|
|
545
|
+
const returnObj = returnStmt.argument as types.ObjectExpression
|
|
546
|
+
const propsObj = (
|
|
547
|
+
returnObj.properties.find(
|
|
548
|
+
(p) =>
|
|
549
|
+
(p as types.ObjectProperty).key.type === 'Identifier' &&
|
|
550
|
+
((p as types.ObjectProperty).key as types.Identifier).name === 'props'
|
|
551
|
+
) as types.ObjectProperty
|
|
552
|
+
).value as types.ObjectExpression
|
|
553
|
+
|
|
554
|
+
const propNames = propsObj.properties.map(
|
|
555
|
+
(p) => ((p as types.ObjectProperty).key as types.Identifier).name
|
|
556
|
+
)
|
|
557
|
+
const uniquePropNames = new Set(propNames)
|
|
558
|
+
|
|
559
|
+
expect(propNames.length).toBe(uniquePropNames.size)
|
|
560
|
+
})
|
|
561
|
+
})
|