@teleporthq/teleport-plugin-next-data-source 0.43.64 → 0.43.66

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.
Files changed (35) hide show
  1. package/__tests__/collection-path.test.ts +191 -0
  2. package/__tests__/count-collection-path.test.ts +59 -0
  3. package/dist/cjs/count-fetchers.d.ts.map +1 -1
  4. package/dist/cjs/count-fetchers.js +1 -1
  5. package/dist/cjs/count-fetchers.js.map +1 -1
  6. package/dist/cjs/fetchers/javascript.d.ts.map +1 -1
  7. package/dist/cjs/fetchers/javascript.js +2 -2
  8. package/dist/cjs/fetchers/javascript.js.map +1 -1
  9. package/dist/cjs/fetchers/rest-api.d.ts.map +1 -1
  10. package/dist/cjs/fetchers/rest-api.js +11 -3
  11. package/dist/cjs/fetchers/rest-api.js.map +1 -1
  12. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  13. package/dist/cjs/utils.d.ts +15 -0
  14. package/dist/cjs/utils.d.ts.map +1 -1
  15. package/dist/cjs/utils.js +19 -1
  16. package/dist/cjs/utils.js.map +1 -1
  17. package/dist/esm/count-fetchers.d.ts.map +1 -1
  18. package/dist/esm/count-fetchers.js +1 -1
  19. package/dist/esm/count-fetchers.js.map +1 -1
  20. package/dist/esm/fetchers/javascript.d.ts.map +1 -1
  21. package/dist/esm/fetchers/javascript.js +3 -3
  22. package/dist/esm/fetchers/javascript.js.map +1 -1
  23. package/dist/esm/fetchers/rest-api.d.ts.map +1 -1
  24. package/dist/esm/fetchers/rest-api.js +12 -4
  25. package/dist/esm/fetchers/rest-api.js.map +1 -1
  26. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  27. package/dist/esm/utils.d.ts +15 -0
  28. package/dist/esm/utils.d.ts.map +1 -1
  29. package/dist/esm/utils.js +17 -0
  30. package/dist/esm/utils.js.map +1 -1
  31. package/package.json +5 -5
  32. package/src/count-fetchers.ts +6 -2
  33. package/src/fetchers/javascript.ts +11 -4
  34. package/src/fetchers/rest-api.ts +18 -1
  35. package/src/utils.ts +39 -0
@@ -0,0 +1,191 @@
1
+ import { generateRESTAPIFetcher } from '../src/fetchers/rest-api'
2
+ import { generateJavaScriptFetcher } from '../src/fetchers/javascript'
3
+
4
+ /**
5
+ * Runs a generated fetcher's handler and returns what it answered, so these
6
+ * assert on BEHAVIOUR rather than on the shape of the emitted source.
7
+ */
8
+ const runHandler = async (
9
+ code: string,
10
+ query: Record<string, unknown>,
11
+ fetchImpl?: () => Promise<unknown>
12
+ ) => {
13
+ const withoutImports = code.replace(/^import\s+.*?$/gm, '')
14
+ const factory = new Function(
15
+ 'fetch',
16
+ `${withoutImports.replace('export default async function handler', 'async function handler')}
17
+ return handler`
18
+ )
19
+
20
+ const handler = factory(
21
+ fetchImpl || (() => Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve([]) }))
22
+ )
23
+
24
+ let payload: Record<string, unknown> = {}
25
+ const res = {
26
+ status: () => res,
27
+ json: (data: Record<string, unknown>) => {
28
+ payload = data
29
+ return res
30
+ },
31
+ }
32
+
33
+ await handler({ query, body: undefined }, res)
34
+ return payload
35
+ }
36
+
37
+ const respondWith = (body: unknown) => () =>
38
+ Promise.resolve({ ok: true, status: 200, statusText: 'OK', json: () => Promise.resolve(body) })
39
+
40
+ describe('REST API fetcher — collection path', () => {
41
+ const baseConfig = { url: 'https://api.test/items', method: 'GET' }
42
+
43
+ it('returns a bare list unchanged when no path is configured', async () => {
44
+ const result = await runHandler(
45
+ generateRESTAPIFetcher(baseConfig),
46
+ {},
47
+ respondWith([{ id: 1 }, { id: 2 }])
48
+ )
49
+
50
+ expect(result.success).toBe(true)
51
+ expect(result.data).toEqual([{ id: 1 }, { id: 2 }])
52
+ })
53
+
54
+ it('leaves a wrapped payload alone when the request asks for no path', async () => {
55
+ const result = await runHandler(
56
+ generateRESTAPIFetcher(baseConfig),
57
+ {},
58
+ respondWith({ results: [{ id: 1 }] })
59
+ )
60
+
61
+ expect(result.data).toEqual({ results: [{ id: 1 }] })
62
+ })
63
+
64
+ it('unwraps using the list location the request carries', async () => {
65
+ const result = await runHandler(
66
+ generateRESTAPIFetcher(baseConfig),
67
+ { collectionPath: JSON.stringify(['results']) },
68
+ respondWith({ results: [{ id: 1 }, { id: 2 }] })
69
+ )
70
+
71
+ expect(result.data).toEqual([{ id: 1 }, { id: 2 }])
72
+ })
73
+
74
+ it('unwraps a nested list location', async () => {
75
+ const result = await runHandler(
76
+ generateRESTAPIFetcher(baseConfig),
77
+ { collectionPath: JSON.stringify(['response', 'items']) },
78
+ respondWith({ response: { items: [{ id: 1 }] } })
79
+ )
80
+
81
+ expect(result.data).toEqual([{ id: 1 }])
82
+ })
83
+
84
+ it('ignores a list location left on the config by an older build', async () => {
85
+ // The path belongs to the details page and travels per request. Baking a
86
+ // stale config value into the fetcher would unwrap for every caller,
87
+ // including the list bindings authored against the wrapped response.
88
+ const result = await runHandler(
89
+ generateRESTAPIFetcher({ ...baseConfig, collectionPath: ['results'] }),
90
+ {},
91
+ respondWith({ results: [{ id: 1 }] })
92
+ )
93
+
94
+ expect(result.data).toEqual({ results: [{ id: 1 }] })
95
+ })
96
+
97
+ it('falls back to the whole payload when the requested path no longer resolves', async () => {
98
+ const result = await runHandler(
99
+ generateRESTAPIFetcher(baseConfig),
100
+ { collectionPath: JSON.stringify(['results']) },
101
+ respondWith({ items: [{ id: 1 }] })
102
+ )
103
+
104
+ expect(result.data).toEqual({ items: [{ id: 1 }] })
105
+ })
106
+
107
+ it('applies filters and limits to an unwrapped list', async () => {
108
+ const result = await runHandler(
109
+ generateRESTAPIFetcher(baseConfig),
110
+ {
111
+ collectionPath: JSON.stringify(['results']),
112
+ filters: JSON.stringify([
113
+ { type: 'condition', source: 'slug', destination: 'b', operand: '=' },
114
+ ]),
115
+ limit: '1',
116
+ },
117
+ respondWith({ results: [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }] })
118
+ )
119
+
120
+ expect(result.data).toEqual([{ slug: 'b' }])
121
+ })
122
+
123
+ it('emits the same code whatever list location the config carries', () => {
124
+ expect(generateRESTAPIFetcher(baseConfig)).toEqual(
125
+ generateRESTAPIFetcher({ ...baseConfig, collectionPath: ['results'] })
126
+ )
127
+ })
128
+ })
129
+
130
+ describe('REST API fetcher — configured request body', () => {
131
+ it('sends the configured body when the caller supplies none', async () => {
132
+ let sent: string | undefined
133
+ await runHandler(
134
+ generateRESTAPIFetcher({
135
+ url: 'https://api.test/search',
136
+ method: 'POST',
137
+ bodyType: 'json',
138
+ body: '{"pageSize":50}',
139
+ }),
140
+ {},
141
+ (...args: unknown[]) => {
142
+ sent = (args[1] as { body?: string })?.body
143
+ return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve([]) })
144
+ }
145
+ )
146
+
147
+ expect(sent).toBe('{"pageSize":50}')
148
+ })
149
+
150
+ it('sends nothing when no body is configured, exactly as before', async () => {
151
+ let sent: string | undefined = 'untouched'
152
+ await runHandler(
153
+ generateRESTAPIFetcher({ url: 'https://api.test/search', method: 'POST' }),
154
+ {},
155
+ (...args: unknown[]) => {
156
+ sent = (args[1] as { body?: string })?.body
157
+ return Promise.resolve({ ok: true, status: 200, json: () => Promise.resolve([]) })
158
+ }
159
+ )
160
+
161
+ expect(sent).toBeUndefined()
162
+ })
163
+ })
164
+
165
+ describe('JavaScript fetcher — collection path', () => {
166
+ it('returns a bare list unchanged', async () => {
167
+ const result = await runHandler(
168
+ generateJavaScriptFetcher({ code: '[{ "id": 1 }, { "id": 2 }]' }),
169
+ {}
170
+ )
171
+
172
+ expect(result.data).toEqual([{ id: 1 }, { id: 2 }])
173
+ })
174
+
175
+ it('unwraps using the list location the request carries', async () => {
176
+ const result = await runHandler(
177
+ generateJavaScriptFetcher({ code: '({ "items": [{ "id": 1 }] })' }),
178
+ {
179
+ collectionPath: JSON.stringify(['items']),
180
+ }
181
+ )
182
+
183
+ expect(result.data).toEqual([{ id: 1 }])
184
+ })
185
+
186
+ it('emits the same code whatever list location the config carries', () => {
187
+ expect(generateJavaScriptFetcher({ code: '[]' })).toEqual(
188
+ generateJavaScriptFetcher({ code: '[]', collectionPath: ['items'] })
189
+ )
190
+ })
191
+ })
@@ -0,0 +1,59 @@
1
+ import { generateRESTAPIFetcher } from '../src/fetchers/rest-api'
2
+ import { generateCountFetcher } from '../src/count-fetchers'
3
+
4
+ /**
5
+ * Counting re-runs the fetch handler and measures its result, so it depends on
6
+ * the same `collectionPath` the fetch does. Dropping it on the way through left
7
+ * the handler holding the wrapper object — not an array — and the count came
8
+ * back 0 for a list that plainly had rows.
9
+ */
10
+ const runCount = async (query: Record<string, unknown>, body: unknown) => {
11
+ const source = `${generateRESTAPIFetcher({ url: 'https://api.test/items', method: 'GET' })}
12
+ ${generateCountFetcher({ type: 'rest-api', config: {} } as never, 'data')}`
13
+
14
+ const withoutImports = source.replace(/^import\s+.*?$/gm, '')
15
+ const factory = new Function(
16
+ 'fetch',
17
+ `${withoutImports.replace('export default async function handler', 'async function handler')}
18
+ return getCount`
19
+ )
20
+
21
+ const getCount = factory(() =>
22
+ Promise.resolve({ ok: true, status: 200, statusText: 'OK', json: () => Promise.resolve(body) })
23
+ )
24
+
25
+ let payload: Record<string, unknown> = {}
26
+ const res = {
27
+ status: () => res,
28
+ json: (data: Record<string, unknown>) => {
29
+ payload = data
30
+ return res
31
+ },
32
+ }
33
+
34
+ await getCount({ query }, res)
35
+ return payload
36
+ }
37
+
38
+ const WRAPPED = { categories: [{ slug: 'a' }, { slug: 'b' }, { slug: 'c' }] }
39
+
40
+ describe('REST count fetcher — collection path', () => {
41
+ it('counts the records the path points at', async () => {
42
+ const result = await runCount({ collectionPath: JSON.stringify(['categories']) }, WRAPPED)
43
+
44
+ expect(result.success).toBe(true)
45
+ expect(result.count).toBe(3)
46
+ })
47
+
48
+ it('counts a bare list with no path, exactly as before', async () => {
49
+ const result = await runCount({}, [{ slug: 'a' }, { slug: 'b' }])
50
+
51
+ expect(result.count).toBe(2)
52
+ })
53
+
54
+ it('still reports 0 for a payload that is not a list and has no path', async () => {
55
+ const result = await runCount({}, WRAPPED)
56
+
57
+ expect(result.count).toBe(0)
58
+ })
59
+ })
@@ -1 +1 @@
1
- {"version":3,"file":"count-fetchers.d.ts","sourceRoot":"","sources":["../../src/count-fetchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAE3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,GAC7B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAiF1F"}
1
+ {"version":3,"file":"count-fetchers.d.ts","sourceRoot":"","sources":["../../src/count-fetchers.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAE3D,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,yBAAyB,EAAE,MAAM,kBAAkB,CAAA;AAC5D,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,2BAA2B,EAAE,MAAM,oBAAoB,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAClE,OAAO,EAAE,8BAA8B,EAAE,MAAM,uBAAuB,CAAA;AACtE,OAAO,EAAE,uBAAuB,EAAE,MAAM,qBAAqB,CAAA;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,qBAAqB,CAAA;AAElE,OAAO,EACL,8BAA8B,EAC9B,yBAAyB,EACzB,2BAA2B,EAC3B,2BAA2B,EAC3B,4BAA4B,EAC5B,8BAA8B,EAC9B,uBAAuB,EACvB,4BAA4B,GAC7B,CAAA;AAED,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAqF1F"}
@@ -43,7 +43,7 @@ function generateCountFetcher(dataSource, tableName) {
43
43
  case 'csv-file':
44
44
  return (0, csv_file_1.generateCSVCountFetcher)(config);
45
45
  default:
46
- return "\nasync function getCount(req, res) {\n try {\n const { query, queryColumns, filters } = req.query\n const fakeReq = { query: { query, queryColumns, filters }, method: 'GET' }\n let result = null\n let statusCode = 200\n \n const fakeRes = {\n status: (code) => {\n statusCode = code\n return fakeRes\n },\n json: (data) => {\n result = data\n return fakeRes\n },\n }\n \n await handler(fakeReq, fakeRes)\n \n if (statusCode !== 200 || !result || !result.success) {\n return res.status(500).json({\n success: false,\n error: 'Failed to get data for counting',\n timestamp: Date.now()\n })\n }\n \n const count = Array.isArray(result.data) ? result.data.length : 0\n \n return res.status(200).json({\n success: true,\n count: count,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Error getting count:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to get count',\n timestamp: Date.now()\n })\n }\n}\n";
46
+ return "\nasync function getCount(req, res) {\n try {\n // `collectionPath` has to travel with the rest: this counts by re-running\n // the fetch handler and measuring its result, and without the path that\n // handler gets the wrapper object rather than the records, which is not an\n // array \u2014 so the count below would report 0 for a list that clearly has rows.\n const { query, queryColumns, filters, collectionPath } = req.query\n const fakeReq = { query: { query, queryColumns, filters, collectionPath }, method: 'GET' }\n let result = null\n let statusCode = 200\n \n const fakeRes = {\n status: (code) => {\n statusCode = code\n return fakeRes\n },\n json: (data) => {\n result = data\n return fakeRes\n },\n }\n \n await handler(fakeReq, fakeRes)\n \n if (statusCode !== 200 || !result || !result.success) {\n return res.status(500).json({\n success: false,\n error: 'Failed to get data for counting',\n timestamp: Date.now()\n })\n }\n \n const count = Array.isArray(result.data) ? result.data.length : 0\n \n return res.status(200).json({\n success: true,\n count: count,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Error getting count:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to get count',\n timestamp: Date.now()\n })\n }\n}\n";
47
47
  }
48
48
  }
49
49
  exports.generateCountFetcher = generateCountFetcher;
@@ -1 +1 @@
1
- {"version":3,"file":"count-fetchers.js","sourceRoot":"","sources":["../../src/count-fetchers.ts"],"names":[],"mappings":";;;AACA,+DAA2E;AAC3E,oDAAsE;AAUpE,+GAVO,2CAA8B,OAUP;AAThC,0CAA4D;AAU1D,0GAVO,iCAAyB,OAUP;AAT3B,8CAAgE;AAU9D,4GAVO,qCAA2B,OAUP;AAT7B,8CAAgE;AAU9D,4GAVO,qCAA2B,OAUP;AAT7B,gDAAkE;AAUhE,6GAVO,uCAA4B,OAUP;AAT9B,oDAAsE;AAUpE,+GAVO,2CAA8B,OAUP;AAThC,gDAA6D;AAU3D,wGAVO,kCAAuB,OAUP;AATzB,gDAAkE;AAUhE,6GAVO,uCAA4B,OAUP;AAG9B,SAAgB,oBAAoB,CAAC,UAA0B,EAAE,SAAiB;IACxE,IAAA,IAAI,GAAa,UAAU,KAAvB,EAAE,MAAM,GAAK,UAAU,OAAf,CAAe;IAEnC,QAAQ,IAAI,EAAE;QACZ,KAAK,UAAU;YACb,OAAO,IAAA,uCAA4B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAExD,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,IAAA,2CAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAE1D,KAAK,OAAO,CAAC;QACb,KAAK,MAAM;YACT,OAAO,IAAA,iCAAyB,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAErD,KAAK,SAAS;YACZ,OAAO,IAAA,qCAA2B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAEvD,KAAK,SAAS;YACZ,OAAO,IAAA,qCAA2B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAEvD,KAAK,UAAU;YACb,IAAI,IAAA,yDAAkC,EAAC,MAAM,CAAC,EAAE;gBAC9C,OAAO,IAAA,2CAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;aACzD;YACD,OAAO,IAAA,uCAA4B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAExD,KAAK,YAAY;YACf,OAAO,IAAA,2CAA8B,EAAC,MAAM,CAAC,CAAA;QAE/C,KAAK,UAAU;YACb,OAAO,IAAA,kCAAuB,EAAC,MAAM,CAAC,CAAA;QAExC;YACE,OAAO,knCA6CZ,CAAA;KACE;AACH,CAAC;AAjFD,oDAiFC"}
1
+ {"version":3,"file":"count-fetchers.js","sourceRoot":"","sources":["../../src/count-fetchers.ts"],"names":[],"mappings":";;;AACA,+DAA2E;AAC3E,oDAAsE;AAUpE,+GAVO,2CAA8B,OAUP;AAThC,0CAA4D;AAU1D,0GAVO,iCAAyB,OAUP;AAT3B,8CAAgE;AAU9D,4GAVO,qCAA2B,OAUP;AAT7B,8CAAgE;AAU9D,4GAVO,qCAA2B,OAUP;AAT7B,gDAAkE;AAUhE,6GAVO,uCAA4B,OAUP;AAT9B,oDAAsE;AAUpE,+GAVO,2CAA8B,OAUP;AAThC,gDAA6D;AAU3D,wGAVO,kCAAuB,OAUP;AATzB,gDAAkE;AAUhE,6GAVO,uCAA4B,OAUP;AAG9B,SAAgB,oBAAoB,CAAC,UAA0B,EAAE,SAAiB;IACxE,IAAA,IAAI,GAAa,UAAU,KAAvB,EAAE,MAAM,GAAK,UAAU,OAAf,CAAe;IAEnC,QAAQ,IAAI,EAAE;QACZ,KAAK,UAAU;YACb,OAAO,IAAA,uCAA4B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAExD,KAAK,YAAY,CAAC;QAClB,KAAK,aAAa;YAChB,OAAO,IAAA,2CAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAE1D,KAAK,OAAO,CAAC;QACb,KAAK,MAAM;YACT,OAAO,IAAA,iCAAyB,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAErD,KAAK,SAAS;YACZ,OAAO,IAAA,qCAA2B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAEvD,KAAK,SAAS;YACZ,OAAO,IAAA,qCAA2B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAEvD,KAAK,UAAU;YACb,IAAI,IAAA,yDAAkC,EAAC,MAAM,CAAC,EAAE;gBAC9C,OAAO,IAAA,2CAA8B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;aACzD;YACD,OAAO,IAAA,uCAA4B,EAAC,MAAM,EAAE,SAAS,CAAC,CAAA;QAExD,KAAK,YAAY;YACf,OAAO,IAAA,2CAA8B,EAAC,MAAM,CAAC,CAAA;QAE/C,KAAK,UAAU;YACb,OAAO,IAAA,kCAAuB,EAAC,MAAM,CAAC,CAAA;QAExC;YACE,OAAO,09CAiDZ,CAAA;KACE;AACH,CAAC;AArFD,oDAqFC"}
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../../src/fetchers/javascript.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,wBAAwB,WAC3B,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CA2BpC,CAAA;AAMD,eAAO,MAAM,yBAAyB,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MAqK3E,CAAA;AAGD,eAAO,MAAM,8BAA8B,YAAa,GAAG,KAAG,MA+C7D,CAAA"}
1
+ {"version":3,"file":"javascript.d.ts","sourceRoot":"","sources":["../../../src/fetchers/javascript.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,wBAAwB,WAC3B,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CA2BpC,CAAA;AAMD,eAAO,MAAM,yBAAyB,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MAwK3E,CAAA;AAGD,eAAO,MAAM,8BAA8B,YAAa,GAAG,KAAG,MAkD7D,CAAA"}
@@ -30,12 +30,12 @@ var validateJavaScriptConfig = function (config) {
30
30
  exports.validateJavaScriptConfig = validateJavaScriptConfig;
31
31
  var generateJavaScriptFetcher = function (config) {
32
32
  var jsConfig = config;
33
- return "".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, utils_1.generateSortFilterHelperCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\nexport default async function handler(req, res) {\n try {\n const { limit, offset, page, perPage, query, queryColumns, sortBy, sortOrder, filters, sorts } = req.query\n \n const code = ").concat(JSON.stringify(jsConfig.code), "\n const executeCode = new Function('return ' + code)\n let data = executeCode()\n \n if (Array.isArray(data)) {\n if (query && query.trim()) {\n const searchQuery = query.toLowerCase()\n \n if (queryColumns) {\n try {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n data = data.filter(item => {\n return columns.some(col => {\n const value = getNestedValue(item, col)\n if (value === null || value === undefined) return false\n return String(value).toLowerCase().includes(searchQuery)\n })\n })\n } catch (err) {\n console.error('Error parsing queryColumns:', err)\n }\n } else {\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 }\n \n if (filters) {\n try {\n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n \n if (filterTree) {\n data = data.filter((item) =>\n evaluateFilterTree(filterTree, (condition) => {\n const value = getNestedValue(item, condition.source)\n const target = condition.destination\n const operand = condition.operand\n \n if (Array.isArray(target)) {\n if (operand === '!=') {\n return !target.includes(value)\n }\n return target.includes(value)\n }\n \n return compareValues(value, target, operand)\n })\n )\n }\n } catch (err) {\n console.error('Error parsing filters:', err)\n }\n }\n \n if (sorts) {\n try {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n data.sort((a, b) => {\n for (const sort of parsedSorts) {\n if (!sort.field) continue\n const aVal = getNestedValue(a, sort.field)\n const bVal = getNestedValue(b, sort.field)\n const sortOrderValue = (sort.order || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n if (comparison !== 0) return comparison * sortOrderValue\n }\n return 0\n })\n }\n } catch (err) {\n console.error('Error parsing sorts:', err)\n }\n } else if (sortBy && sortBy.trim()) {\n data.sort((a, b) => {\n const aVal = getNestedValue(a, sortBy)\n const bVal = getNestedValue(b, sortBy)\n const sortOrderValue = (sortOrder || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n return comparison * sortOrderValue\n })\n }\n \n const limitValue = limit || perPage\n const pageValue = page ? Math.max(1, parseInt(page)) : undefined\n const offsetValue = offset !== undefined ? Math.max(0, parseInt(offset)) : (pageValue && perPage ? (pageValue - 1) * Math.max(1, parseInt(perPage)) : 0)\n \n if (limitValue) {\n const limitInt = Math.max(1, parseInt(limitValue))\n data = data.slice(offsetValue, offsetValue + limitInt)\n } else if (offsetValue > 0) {\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('JavaScript execution error:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to execute code',\n timestamp: Date.now()\n })\n }\n}\n");
33
+ return "".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, utils_1.generateSortFilterHelperCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\n").concat((0, utils_1.generateCollectionPathHelperCode)(), "\n\nexport default async function handler(req, res) {\n try {\n const { limit, offset, page, perPage, query, queryColumns, sortBy, sortOrder, filters, sorts, collectionPath } = req.query\n \n const code = ").concat(JSON.stringify(jsConfig.code), "\n const executeCode = new Function('return ' + code)\n let data = resolveCollectionPath(executeCode(), collectionPath)\n \n if (Array.isArray(data)) {\n if (query && query.trim()) {\n const searchQuery = query.toLowerCase()\n \n if (queryColumns) {\n try {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n data = data.filter(item => {\n return columns.some(col => {\n const value = getNestedValue(item, col)\n if (value === null || value === undefined) return false\n return String(value).toLowerCase().includes(searchQuery)\n })\n })\n } catch (err) {\n console.error('Error parsing queryColumns:', err)\n }\n } else {\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 }\n \n if (filters) {\n try {\n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n \n if (filterTree) {\n data = data.filter((item) =>\n evaluateFilterTree(filterTree, (condition) => {\n const value = getNestedValue(item, condition.source)\n const target = condition.destination\n const operand = condition.operand\n \n if (Array.isArray(target)) {\n if (operand === '!=') {\n return !target.includes(value)\n }\n return target.includes(value)\n }\n \n return compareValues(value, target, operand)\n })\n )\n }\n } catch (err) {\n console.error('Error parsing filters:', err)\n }\n }\n \n if (sorts) {\n try {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n data.sort((a, b) => {\n for (const sort of parsedSorts) {\n if (!sort.field) continue\n const aVal = getNestedValue(a, sort.field)\n const bVal = getNestedValue(b, sort.field)\n const sortOrderValue = (sort.order || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n if (comparison !== 0) return comparison * sortOrderValue\n }\n return 0\n })\n }\n } catch (err) {\n console.error('Error parsing sorts:', err)\n }\n } else if (sortBy && sortBy.trim()) {\n data.sort((a, b) => {\n const aVal = getNestedValue(a, sortBy)\n const bVal = getNestedValue(b, sortBy)\n const sortOrderValue = (sortOrder || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n return comparison * sortOrderValue\n })\n }\n \n const limitValue = limit || perPage\n const pageValue = page ? Math.max(1, parseInt(page)) : undefined\n const offsetValue = offset !== undefined ? Math.max(0, parseInt(offset)) : (pageValue && perPage ? (pageValue - 1) * Math.max(1, parseInt(perPage)) : 0)\n \n if (limitValue) {\n const limitInt = Math.max(1, parseInt(limitValue))\n data = data.slice(offsetValue, offsetValue + limitInt)\n } else if (offsetValue > 0) {\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('JavaScript execution error:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to execute code',\n timestamp: Date.now()\n })\n }\n}\n");
34
34
  };
35
35
  exports.generateJavaScriptFetcher = generateJavaScriptFetcher;
36
36
  // tslint:disable-next-line:variable-name
37
37
  var generateJavaScriptCountFetcher = function (_config) {
38
- return "\nasync function getCount(req, res) {\n try {\n const { query, queryColumns } = req.query\n const fakeReq = { query: { query, queryColumns }, method: 'GET' }\n let result = null\n let statusCode = 200\n \n const fakeRes = {\n status: (code) => {\n statusCode = code\n return fakeRes\n },\n json: (data) => {\n result = data\n return fakeRes\n },\n }\n \n await handler(fakeReq, fakeRes)\n \n if (statusCode !== 200 || !result || !result.success) {\n return res.status(500).json({\n success: false,\n error: 'Failed to get data for counting',\n timestamp: Date.now()\n })\n }\n \n const count = Array.isArray(result.data) ? result.data.length : 0\n \n return res.status(200).json({\n success: true,\n count: count,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Error getting count:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to get count',\n timestamp: Date.now()\n })\n }\n}\n";
38
+ return "\nasync function getCount(req, res) {\n try {\n // See the REST count fetcher: this counts by re-running the fetch handler,\n // so `collectionPath` has to reach it or the handler measures the wrapper\n // object instead of the records and the count comes back 0.\n const { query, queryColumns, collectionPath } = req.query\n const fakeReq = { query: { query, queryColumns, collectionPath }, method: 'GET' }\n let result = null\n let statusCode = 200\n \n const fakeRes = {\n status: (code) => {\n statusCode = code\n return fakeRes\n },\n json: (data) => {\n result = data\n return fakeRes\n },\n }\n \n await handler(fakeReq, fakeRes)\n \n if (statusCode !== 200 || !result || !result.success) {\n return res.status(500).json({\n success: false,\n error: 'Failed to get data for counting',\n timestamp: Date.now()\n })\n }\n \n const count = Array.isArray(result.data) ? result.data.length : 0\n \n return res.status(200).json({\n success: true,\n count: count,\n timestamp: Date.now()\n })\n } catch (error) {\n console.error('Error getting count:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to get count',\n timestamp: Date.now()\n })\n }\n}\n";
39
39
  };
40
40
  exports.generateJavaScriptCountFetcher = generateJavaScriptCountFetcher;
41
41
  //# sourceMappingURL=javascript.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/fetchers/javascript.ts"],"names":[],"mappings":";;;AAAA,kCAKiB;AAEV,IAAM,wBAAwB,GAAG,UACtC,MAA+B;IAE/B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAA;KAClE;IAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAA;KAChE;IAED,IAAM,iBAAiB,GAAG;QACxB,eAAe;QACf,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,YAAY;QACZ,WAAW;QACX,cAAc;KACf,CAAA;IAED,KAAsB,UAAiB,EAAjB,uCAAiB,EAAjB,+BAAiB,EAAjB,IAAiB,EAAE;QAApC,IAAM,OAAO,0BAAA;QAChB,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAC7B,OAAO,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAA;YAC9F,MAAK;SACN;KACF;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC,CAAA;AA7BY,QAAA,wBAAwB,4BA6BpC;AAMM,IAAM,yBAAyB,GAAG,UAAC,MAA+B;IACvE,IAAM,QAAQ,GAAG,MAA0B,CAAA;IAC3C,OAAO,UAAG,IAAA,iCAAyB,GAAE,iBAErC,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,oCAA4B,GAAE,iBAE9B,IAAA,qCAA6B,GAAE,oNAMd,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,sgLAsJ/C,CAAA;AACD,CAAC,CAAA;AArKY,QAAA,yBAAyB,6BAqKrC;AAED,yCAAyC;AAClC,IAAM,8BAA8B,GAAG,UAAC,OAAY;IACzD,OAAO,gmCA6CR,CAAA;AACD,CAAC,CAAA;AA/CY,QAAA,8BAA8B,kCA+C1C"}
1
+ {"version":3,"file":"javascript.js","sourceRoot":"","sources":["../../../src/fetchers/javascript.ts"],"names":[],"mappings":";;;AAAA,kCAMiB;AAEV,IAAM,wBAAwB,GAAG,UACtC,MAA+B;IAE/B,IAAI,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE;QACzC,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,+BAA+B,EAAE,CAAA;KAClE;IAED,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,OAAO,MAAM,CAAC,IAAI,KAAK,QAAQ,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAChF,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,6BAA6B,EAAE,CAAA;KAChE;IAED,IAAM,iBAAiB,GAAG;QACxB,eAAe;QACf,YAAY;QACZ,YAAY;QACZ,gBAAgB;QAChB,YAAY;QACZ,WAAW;QACX,cAAc;KACf,CAAA;IAED,KAAsB,UAAiB,EAAjB,uCAAiB,EAAjB,+BAAiB,EAAjB,IAAiB,EAAE;QAApC,IAAM,OAAO,0BAAA;QAChB,IAAI,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;YAC7B,OAAO,CAAC,IAAI,CAAC,gFAAgF,CAAC,CAAA;YAC9F,MAAK;SACN;KACF;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC,CAAA;AA7BY,QAAA,wBAAwB,4BA6BpC;AAMM,IAAM,yBAAyB,GAAG,UAAC,MAA+B;IACvE,IAAM,QAAQ,GAAG,MAA0B,CAAA;IAE3C,OAAO,UAAG,IAAA,iCAAyB,GAAE,iBAErC,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,oCAA4B,GAAE,iBAE9B,IAAA,qCAA6B,GAAE,iBAE/B,IAAA,wCAAgC,GAAE,oOAMjB,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,6iLAsJ/C,CAAA;AACD,CAAC,CAAA;AAxKY,QAAA,yBAAyB,6BAwKrC;AAED,yCAAyC;AAClC,IAAM,8BAA8B,GAAG,UAAC,OAAY;IACzD,OAAO,m2CAgDR,CAAA;AACD,CAAC,CAAA;AAlDY,QAAA,8BAA8B,kCAkD1C"}
@@ -1 +1 @@
1
- {"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../../src/fetchers/rest-api.ts"],"names":[],"mappings":"AAOA,eAAO,MAAM,qBAAqB,WACxB,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CA0BpC,CAAA;AA2CD,eAAO,MAAM,sBAAsB,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MA0MxE,CAAA"}
1
+ {"version":3,"file":"rest-api.d.ts","sourceRoot":"","sources":["../../../src/fetchers/rest-api.ts"],"names":[],"mappings":"AAQA,eAAO,MAAM,qBAAqB,WACxB,OAAO,MAAM,EAAE,OAAO,CAAC,KAC9B;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CA0BpC,CAAA;AA4CD,eAAO,MAAM,sBAAsB,WAAY,OAAO,MAAM,EAAE,OAAO,CAAC,KAAG,MAyNxE,CAAA"}
@@ -49,11 +49,19 @@ var generateAuthCode = function (authorization) {
49
49
  var generateRESTAPIFetcher = function (config) {
50
50
  var restConfig = config;
51
51
  var authCode = generateAuthCode(restConfig.authorization || {});
52
- return "import fetch from 'node-fetch'\n\n".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, utils_1.generateSortFilterHelperCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\nexport default async function handler(req, res) {\n try {\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset } = req.query\n \n const url = ").concat(JSON.stringify(restConfig.url), "\n const method = ").concat(JSON.stringify(restConfig.method || 'GET'), "\n \n const headers = ").concat(JSON.stringify(restConfig.headers || {}), "\n ").concat(authCode, "\n \n const options = {\n method,\n headers\n }\n \n ").concat(restConfig.method === 'POST' || restConfig.method === 'PUT' || restConfig.method === 'PATCH'
52
+ return "import fetch from 'node-fetch'\n\n".concat((0, utils_1.generateSafeJSONParseCode)(), "\n\n").concat((0, utils_1.generateDateFormatterCode)(), "\n\n").concat((0, utils_1.generateSortFilterHelperCode)(), "\n\n").concat((0, utils_1.generateFilterTreeHelpersCode)(), "\n\n").concat((0, utils_1.generateCollectionPathHelperCode)(), "\n\nexport default async function handler(req, res) {\n try {\n const { query, queryColumns, limit, page, perPage, sortBy, sortOrder, filters, sorts, offset, collectionPath } = req.query\n \n const url = ").concat(JSON.stringify(restConfig.url), "\n const method = ").concat(JSON.stringify(restConfig.method || 'GET'), "\n \n const headers = ").concat(JSON.stringify(restConfig.headers || {}), "\n ").concat(authCode, "\n \n const options = {\n method,\n headers\n }\n \n ").concat(restConfig.method === 'POST' || restConfig.method === 'PUT' || restConfig.method === 'PATCH'
53
53
  ? "\n if (req.body) {\n options.body = ".concat(restConfig.bodyType === 'json' || !restConfig.bodyType
54
54
  ? 'JSON.stringify(req.body)'
55
- : 'req.body', "\n }\n ")
56
- : '', "\n \n const response = await fetch(url, options)\n \n if (!response.ok) {\n return res.status(response.status).json({\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n timestamp: Date.now()\n })\n }\n \n let data = await response.json()\n \n if (Array.isArray(data)) {\n if (query && query.trim()) {\n const searchQuery = query.toLowerCase()\n \n if (queryColumns) {\n try {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n data = data.filter((item) => {\n return columns.some((col) => {\n const value = getNestedValue(item, col)\n if (value === null || value === undefined) return false\n return String(value).toLowerCase().includes(searchQuery)\n })\n })\n } catch (err) {\n console.error('Error parsing queryColumns:', err)\n }\n } else {\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 }\n \n if (filters) {\n try {\n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n \n if (filterTree) {\n data = data.filter((item) =>\n evaluateFilterTree(filterTree, (condition) => {\n const value = getNestedValue(item, condition.source)\n const target = condition.destination\n const operand = condition.operand\n \n if (Array.isArray(target)) {\n if (operand === '!=') {\n return !target.includes(value)\n }\n return target.includes(value)\n }\n \n return compareValues(value, target, operand)\n })\n )\n }\n } catch (err) {\n console.error('Error parsing filters:', err)\n }\n }\n \n if (sorts) {\n try {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n data.sort((a, b) => {\n for (const sort of parsedSorts) {\n if (!sort.field) continue\n const aVal = getNestedValue(a, sort.field)\n const bVal = getNestedValue(b, sort.field)\n const sortOrderValue = (sort.order || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n if (comparison !== 0) return comparison * sortOrderValue\n }\n return 0\n })\n }\n } catch (err) {\n console.error('Error parsing sorts:', err)\n }\n } else if (sortBy && sortBy.trim()) {\n data.sort((a, b) => {\n const aVal = getNestedValue(a, sortBy)\n const bVal = getNestedValue(b, sortBy)\n const sortOrderValue = (sortOrder || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n return comparison * sortOrderValue\n })\n }\n \n const limitValue = limit || perPage\n const pageValue = page ? Math.max(1, parseInt(page)) : undefined\n const offsetValue = offset !== undefined ? Math.max(0, parseInt(offset)) : (pageValue && perPage ? (pageValue - 1) * Math.max(1, parseInt(perPage)) : 0)\n \n if (limitValue) {\n const limitInt = Math.max(1, parseInt(limitValue))\n data = data.slice(offsetValue, offsetValue + limitInt)\n } else if (offsetValue > 0) {\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('REST API fetch error:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to fetch data',\n timestamp: Date.now()\n })\n }\n}\n");
55
+ : 'req.body', "\n }").concat(
56
+ // A server-side call (getStaticProps -> fetchData -> handler) has no
57
+ // request body, so without this the configured body was silently dropped
58
+ // and the endpoint was called with none — while the editor, which always
59
+ // sends it, showed the rows the body produces. Only fills the gap: a
60
+ // caller that DID supply a body still wins, above.
61
+ restConfig.body
62
+ ? " else {\n options.body = ".concat(JSON.stringify(restConfig.body), "\n }")
63
+ : '', "\n ")
64
+ : '', "\n \n const response = await fetch(url, options)\n \n if (!response.ok) {\n return res.status(response.status).json({\n success: false,\n error: `HTTP ${response.status}: ${response.statusText}`,\n timestamp: Date.now()\n })\n }\n \n let data = await response.json()\n \n data = resolveCollectionPath(data, collectionPath)\n \n if (Array.isArray(data)) {\n if (query && query.trim()) {\n const searchQuery = query.toLowerCase()\n \n if (queryColumns) {\n try {\n const parsed = safeJSONParse(queryColumns)\n const columns = Array.isArray(parsed) ? parsed : [parsed]\n data = data.filter((item) => {\n return columns.some((col) => {\n const value = getNestedValue(item, col)\n if (value === null || value === undefined) return false\n return String(value).toLowerCase().includes(searchQuery)\n })\n })\n } catch (err) {\n console.error('Error parsing queryColumns:', err)\n }\n } else {\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 }\n \n if (filters) {\n try {\n const filterTree = normalizeFilterTree(safeJSONParse(filters))\n \n if (filterTree) {\n data = data.filter((item) =>\n evaluateFilterTree(filterTree, (condition) => {\n const value = getNestedValue(item, condition.source)\n const target = condition.destination\n const operand = condition.operand\n \n if (Array.isArray(target)) {\n if (operand === '!=') {\n return !target.includes(value)\n }\n return target.includes(value)\n }\n \n return compareValues(value, target, operand)\n })\n )\n }\n } catch (err) {\n console.error('Error parsing filters:', err)\n }\n }\n \n if (sorts) {\n try {\n const parsedSorts = safeJSONParse(sorts)\n if (Array.isArray(parsedSorts) && parsedSorts.length > 0) {\n data.sort((a, b) => {\n for (const sort of parsedSorts) {\n if (!sort.field) continue\n const aVal = getNestedValue(a, sort.field)\n const bVal = getNestedValue(b, sort.field)\n const sortOrderValue = (sort.order || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n if (comparison !== 0) return comparison * sortOrderValue\n }\n return 0\n })\n }\n } catch (err) {\n console.error('Error parsing sorts:', err)\n }\n } else if (sortBy && sortBy.trim()) {\n data.sort((a, b) => {\n const aVal = getNestedValue(a, sortBy)\n const bVal = getNestedValue(b, sortBy)\n const sortOrderValue = (sortOrder || '').toLowerCase().startsWith('desc') ? -1 : 1\n \n let comparison = 0\n if (aVal === null || aVal === undefined) {\n comparison = bVal === null || bVal === undefined ? 0 : -1\n } else if (bVal === null || bVal === undefined) {\n comparison = 1\n } else if (typeof aVal === 'number' && typeof bVal === 'number') {\n comparison = aVal - bVal\n } else if (aVal instanceof Date && bVal instanceof Date) {\n comparison = aVal.getTime() - bVal.getTime()\n } else {\n const aStr = String(aVal)\n const bStr = String(bVal)\n if (aStr < bStr) comparison = -1\n else if (aStr > bStr) comparison = 1\n }\n \n return comparison * sortOrderValue\n })\n }\n \n const limitValue = limit || perPage\n const pageValue = page ? Math.max(1, parseInt(page)) : undefined\n const offsetValue = offset !== undefined ? Math.max(0, parseInt(offset)) : (pageValue && perPage ? (pageValue - 1) * Math.max(1, parseInt(perPage)) : 0)\n \n if (limitValue) {\n const limitInt = Math.max(1, parseInt(limitValue))\n data = data.slice(offsetValue, offsetValue + limitInt)\n } else if (offsetValue > 0) {\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('REST API fetch error:', error)\n return res.status(500).json({\n success: false,\n error: error.message || 'Failed to fetch data',\n timestamp: Date.now()\n })\n }\n}\n");
57
65
  };
58
66
  exports.generateRESTAPIFetcher = generateRESTAPIFetcher;
59
67
  //# sourceMappingURL=rest-api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"rest-api.js","sourceRoot":"","sources":["../../../src/fetchers/rest-api.ts"],"names":[],"mappings":";;;AAAA,kCAKiB;AAEV,IAAM,qBAAqB,GAAG,UACnC,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,GAAG,IAAI,OAAO,MAAM,CAAC,GAAG,KAAK,QAAQ,IAAI,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,KAAK,EAAE,EAAE;QAC7E,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,iBAAiB,EAAE,CAAA;KACpD;IAED,IAAI;QACF,IAAM,GAAG,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAA;QAC/B,IAAI,CAAC,CAAC,OAAO,EAAE,QAAQ,CAAC,CAAC,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YAC/C,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qCAAqC,EAAE,CAAA;SACxE;KACF;IAAC,WAAM;QACN,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,oBAAoB,EAAE,CAAA;KACvD;IAED,IAAI,MAAM,CAAC,MAAM,EAAE;QACjB,IAAM,YAAY,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAA;QAC9D,IAAI,OAAO,MAAM,CAAC,MAAM,KAAK,QAAQ,IAAI,CAAC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,EAAE;YAC5F,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,qBAAqB,EAAE,CAAA;SACxD;KACF;IAED,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;AAC1B,CAAC,CAAA;AA5BY,QAAA,qBAAqB,yBA4BjC;AAaD,IAAM,gBAAgB,GAAG,UAAC,aAA4B;IACpD,IAAI,CAAC,aAAa,IAAI,aAAa,CAAC,IAAI,KAAK,MAAM,EAAE;QACnD,OAAO,EAAE,CAAA;KACV;IAEO,IAAA,IAAI,GAAkB,aAAa,KAA/B,EAAE,WAAW,GAAK,aAAa,YAAlB,CAAkB;IAE3C,QAAQ,IAAI,EAAE;QACZ,KAAK,SAAS;YACZ,OAAO,6CAAsC,WAAW,CAAC,MAAM,MAAG,CAAA;QACpE,KAAK,cAAc,CAAC;QACpB,KAAK,YAAY;YACf,OAAO,6CAAsC,WAAW,CAAC,KAAK,MAAG,CAAA;QACnE,KAAK,YAAY;YACf,OAAO,6DAAsD,WAAW,CAAC,QAAQ,cAAI,WAAW,CAAC,QAAQ,0BAAuB,CAAA;QAClI,KAAK,QAAQ;YACX,OAAO,6CAAsC,WAAW,CAAC,YAAY,MAAG,CAAA;QAC1E;YACE,OAAO,EAAE,CAAA;KACZ;AACH,CAAC,CAAA;AAUM,IAAM,sBAAsB,GAAG,UAAC,MAA+B;IACpE,IAAM,UAAU,GAAG,MAAuB,CAAA;IAC1C,IAAM,QAAQ,GAAG,gBAAgB,CAAC,UAAU,CAAC,aAAa,IAAI,EAAE,CAAC,CAAA;IAEjE,OAAO,4CAEP,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,iCAAyB,GAAE,iBAE3B,IAAA,oCAA4B,GAAE,iBAE9B,IAAA,qCAA6B,GAAE,mNAMf,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,GAAG,CAAC,kCAC3B,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,MAAM,IAAI,KAAK,CAAC,yCAEzC,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC,OAAO,IAAI,EAAE,CAAC,mBACxD,QAAQ,2FAQR,UAAU,CAAC,MAAM,KAAK,MAAM,IAAI,UAAU,CAAC,MAAM,KAAK,KAAK,IAAI,UAAU,CAAC,MAAM,KAAK,OAAO;QAC1F,CAAC,CAAC,sDAGF,UAAU,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ;YACpD,CAAC,CAAC,0BAA0B;YAC5B,CAAC,CAAC,UAAU,kBAGjB;QACG,CAAC,CAAC,EAAE,4uLAiKX,CAAA;AACD,CAAC,CAAA;AA1MY,QAAA,sBAAsB,0BA0MlC"}
1
+ {"version":3,"file":"rest-api.js","sourceRoot":"","sources":["../../../src/fetchers/rest-api.ts"],"names":[],"mappings":"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"}