@teleporthq/teleport-plugin-next-data-source 0.43.54 → 0.43.57

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 (102) hide show
  1. package/__tests__/array-mapper-cache-wiring.test.ts +425 -0
  2. package/__tests__/data-source-cache-wrapping.test.ts +152 -0
  3. package/__tests__/ecommerce-product-storefront-tax.test.ts +118 -0
  4. package/__tests__/ecommerce-product-variant-availability.test.ts +264 -0
  5. package/dist/cjs/cache/ast.d.ts +71 -0
  6. package/dist/cjs/cache/ast.d.ts.map +1 -0
  7. package/dist/cjs/cache/ast.js +229 -0
  8. package/dist/cjs/cache/ast.js.map +1 -0
  9. package/dist/cjs/cache/config.d.ts +22 -0
  10. package/dist/cjs/cache/config.d.ts.map +1 -0
  11. package/dist/cjs/cache/config.js +67 -0
  12. package/dist/cjs/cache/config.js.map +1 -0
  13. package/dist/cjs/cache/types.d.ts +31 -0
  14. package/dist/cjs/cache/types.d.ts.map +1 -0
  15. package/dist/cjs/cache/types.js +3 -0
  16. package/dist/cjs/cache/types.js.map +1 -0
  17. package/dist/cjs/data-source-fetchers.d.ts +5 -3
  18. package/dist/cjs/data-source-fetchers.d.ts.map +1 -1
  19. package/dist/cjs/data-source-fetchers.js +51 -8
  20. package/dist/cjs/data-source-fetchers.js.map +1 -1
  21. package/dist/cjs/fetchers/teleport.d.ts +2 -2
  22. package/dist/cjs/fetchers/teleport.d.ts.map +1 -1
  23. package/dist/cjs/fetchers/teleport.js +3 -2
  24. package/dist/cjs/fetchers/teleport.js.map +1 -1
  25. package/dist/cjs/index.d.ts +2 -0
  26. package/dist/cjs/index.d.ts.map +1 -1
  27. package/dist/cjs/index.js +14 -9
  28. package/dist/cjs/index.js.map +1 -1
  29. package/dist/cjs/loading-state.d.ts.map +1 -1
  30. package/dist/cjs/loading-state.js +74 -2
  31. package/dist/cjs/loading-state.js.map +1 -1
  32. package/dist/cjs/pagination-plugin.d.ts.map +1 -1
  33. package/dist/cjs/pagination-plugin.js +204 -64
  34. package/dist/cjs/pagination-plugin.js.map +1 -1
  35. package/dist/cjs/transformations/ecommerce-product.d.ts +15 -1
  36. package/dist/cjs/transformations/ecommerce-product.d.ts.map +1 -1
  37. package/dist/cjs/transformations/ecommerce-product.js +7 -3
  38. package/dist/cjs/transformations/ecommerce-product.js.map +1 -1
  39. package/dist/cjs/transformations/index.d.ts +13 -2
  40. package/dist/cjs/transformations/index.d.ts.map +1 -1
  41. package/dist/cjs/transformations/index.js +33 -5
  42. package/dist/cjs/transformations/index.js.map +1 -1
  43. package/dist/cjs/tsconfig.tsbuildinfo +1 -1
  44. package/dist/cjs/utils.d.ts +4 -3
  45. package/dist/cjs/utils.d.ts.map +1 -1
  46. package/dist/cjs/utils.js +6 -4
  47. package/dist/cjs/utils.js.map +1 -1
  48. package/dist/esm/cache/ast.d.ts +71 -0
  49. package/dist/esm/cache/ast.d.ts.map +1 -0
  50. package/dist/esm/cache/ast.js +196 -0
  51. package/dist/esm/cache/ast.js.map +1 -0
  52. package/dist/esm/cache/config.d.ts +22 -0
  53. package/dist/esm/cache/config.d.ts.map +1 -0
  54. package/dist/esm/cache/config.js +62 -0
  55. package/dist/esm/cache/config.js.map +1 -0
  56. package/dist/esm/cache/types.d.ts +31 -0
  57. package/dist/esm/cache/types.d.ts.map +1 -0
  58. package/dist/esm/cache/types.js +2 -0
  59. package/dist/esm/cache/types.js.map +1 -0
  60. package/dist/esm/data-source-fetchers.d.ts +5 -3
  61. package/dist/esm/data-source-fetchers.d.ts.map +1 -1
  62. package/dist/esm/data-source-fetchers.js +51 -8
  63. package/dist/esm/data-source-fetchers.js.map +1 -1
  64. package/dist/esm/fetchers/teleport.d.ts +2 -2
  65. package/dist/esm/fetchers/teleport.d.ts.map +1 -1
  66. package/dist/esm/fetchers/teleport.js +3 -2
  67. package/dist/esm/fetchers/teleport.js.map +1 -1
  68. package/dist/esm/index.d.ts +2 -0
  69. package/dist/esm/index.d.ts.map +1 -1
  70. package/dist/esm/index.js +12 -8
  71. package/dist/esm/index.js.map +1 -1
  72. package/dist/esm/loading-state.d.ts.map +1 -1
  73. package/dist/esm/loading-state.js +74 -2
  74. package/dist/esm/loading-state.js.map +1 -1
  75. package/dist/esm/pagination-plugin.d.ts.map +1 -1
  76. package/dist/esm/pagination-plugin.js +205 -65
  77. package/dist/esm/pagination-plugin.js.map +1 -1
  78. package/dist/esm/transformations/ecommerce-product.d.ts +15 -1
  79. package/dist/esm/transformations/ecommerce-product.d.ts.map +1 -1
  80. package/dist/esm/transformations/ecommerce-product.js +7 -3
  81. package/dist/esm/transformations/ecommerce-product.js.map +1 -1
  82. package/dist/esm/transformations/index.d.ts +13 -2
  83. package/dist/esm/transformations/index.d.ts.map +1 -1
  84. package/dist/esm/transformations/index.js +32 -5
  85. package/dist/esm/transformations/index.js.map +1 -1
  86. package/dist/esm/tsconfig.tsbuildinfo +1 -1
  87. package/dist/esm/utils.d.ts +4 -3
  88. package/dist/esm/utils.d.ts.map +1 -1
  89. package/dist/esm/utils.js +6 -4
  90. package/dist/esm/utils.js.map +1 -1
  91. package/package.json +5 -5
  92. package/src/cache/ast.ts +265 -0
  93. package/src/cache/config.ts +79 -0
  94. package/src/cache/types.ts +31 -0
  95. package/src/data-source-fetchers.ts +66 -12
  96. package/src/fetchers/teleport.ts +3 -3
  97. package/src/index.ts +10 -4
  98. package/src/loading-state.ts +65 -2
  99. package/src/pagination-plugin.ts +315 -116
  100. package/src/transformations/ecommerce-product.ts +107 -11
  101. package/src/transformations/index.ts +48 -7
  102. package/src/utils.ts +10 -5
@@ -0,0 +1,264 @@
1
+ import { generateEcommerceProductTransformationCode } from '../src/transformations/ecommerce-product'
2
+ import { generateSharedTransformationCode } from '../src/transformations/shared-utils'
3
+ import { getTransformWrapperCode } from '../src/transformations'
4
+
5
+ /**
6
+ * A product whose variant combinations are ALL out of stock — or whose axes have
7
+ * no combinations behind them at all — must reach the storefront saying so, in
8
+ * two ways the picker and the buy button read directly:
9
+ *
10
+ * - every value carries `isDead: 'true'`, so the picker strikes them through;
11
+ * - `hasPurchasableVariant: 'false'`, so the Add to Cart button is replaced by
12
+ * the "select an available option" notice instead of adding a cart line with
13
+ * no variant at all (`data-default-variant-id` is empty in that state).
14
+ *
15
+ * The hinge is knowing the difference between "we looked and there are none" and
16
+ * "we could not look": `options.variantsByProductId` is NULL for the latter, and
17
+ * a null must stay permissive — a missing table or a failed query must never
18
+ * make a whole catalogue unbuyable.
19
+ */
20
+
21
+ const evalBuildProduct = (): ((r: unknown, o?: unknown) => Record<string, unknown>) => {
22
+ const code =
23
+ generateSharedTransformationCode() + '\n' + generateEcommerceProductTransformationCode()
24
+ return new Function(code + '\nreturn buildEcommerceProduct;')() as (
25
+ r: unknown,
26
+ o?: unknown
27
+ ) => Record<string, unknown>
28
+ }
29
+
30
+ type Axis = { key: string; values: Array<Record<string, unknown>> }
31
+
32
+ const buildEcommerceProduct = evalBuildProduct()
33
+
34
+ const SIZE_AXIS = JSON.stringify([
35
+ {
36
+ key: 'size',
37
+ name: 'Size',
38
+ type: 'text',
39
+ values: [
40
+ { value: 'xs', label: 'XS' },
41
+ { value: 's', label: 'S' },
42
+ ],
43
+ },
44
+ ])
45
+
46
+ const variantProduct = (overrides: Record<string, unknown> = {}) => ({
47
+ id: 'p1',
48
+ name: 'Tee',
49
+ slug: 'tee',
50
+ price: 20,
51
+ currency: 'USD',
52
+ variant_options: SIZE_AXIS,
53
+ ...overrides,
54
+ })
55
+
56
+ const values = (product: Record<string, unknown>): Array<Record<string, unknown>> =>
57
+ (product.variantOptions as Axis[])[0].values
58
+
59
+ describe('ecommerce product transform — variant availability', () => {
60
+ it('combinations UNKNOWN (no map at all): nothing dead, still purchasable', () => {
61
+ const product = buildEcommerceProduct(variantProduct())
62
+ expect(values(product).every((v) => v.isDead === 'false')).toBe(true)
63
+ expect(product.hasPurchasableVariant).toBe('true')
64
+ })
65
+
66
+ it('combinations UNKNOWN (the lookup failed → null map): unchanged', () => {
67
+ const product = buildEcommerceProduct(variantProduct(), { variantsByProductId: null })
68
+ expect(values(product).every((v) => v.isDead === 'false')).toBe(true)
69
+ expect(product.hasPurchasableVariant).toBe('true')
70
+ })
71
+
72
+ it('looked up and there are NO combinations: every value dead, not purchasable', () => {
73
+ const product = buildEcommerceProduct(variantProduct(), { variantsByProductId: {} })
74
+ expect(values(product).every((v) => v.isDead === 'true')).toBe(true)
75
+ expect(product.hasPurchasableVariant).toBe('false')
76
+ expect(product.defaultVariantId).toBe('')
77
+ })
78
+
79
+ it('every combination sold out: every value dead, not purchasable', () => {
80
+ const product = buildEcommerceProduct(variantProduct(), {
81
+ variantsByProductId: {
82
+ p1: [
83
+ { id: 'v-xs', options: { size: 'xs' }, quantity: 0 },
84
+ { id: 'v-s', options: { size: 's' }, quantity: 0 },
85
+ ],
86
+ },
87
+ })
88
+ expect(values(product).every((v) => v.isDead === 'true')).toBe(true)
89
+ expect(product.hasPurchasableVariant).toBe('false')
90
+ expect(product.defaultVariantId).toBe('')
91
+ })
92
+
93
+ it('one combination in stock: only the sold-out value is dead, and it is purchasable', () => {
94
+ const product = buildEcommerceProduct(variantProduct(), {
95
+ variantsByProductId: {
96
+ p1: [
97
+ { id: 'v-xs', options: { size: 'xs' }, quantity: 0 },
98
+ { id: 'v-s', options: { size: 's' }, quantity: 4 },
99
+ ],
100
+ },
101
+ })
102
+ expect(values(product)[0].isDead).toBe('true')
103
+ expect(values(product)[1].isDead).toBe('false')
104
+ expect(values(product)[1].isDefault).toBe('true')
105
+ expect(product.hasPurchasableVariant).toBe('true')
106
+ expect(product.defaultVariantId).toBe('v-s')
107
+ })
108
+
109
+ it('unlimited stock (null quantity) counts as in stock', () => {
110
+ const product = buildEcommerceProduct(variantProduct(), {
111
+ variantsByProductId: { p1: [{ id: 'v-xs', options: { size: 'xs' }, quantity: null }] },
112
+ })
113
+ expect(product.hasPurchasableVariant).toBe('true')
114
+ expect(values(product)[0].isDead).toBe('false')
115
+ // The value with no combination behind it is still dead.
116
+ expect(values(product)[1].isDead).toBe('true')
117
+ })
118
+
119
+ it('a FLAT product is always purchasable — outOfStock governs its stock', () => {
120
+ const flat = buildEcommerceProduct(
121
+ { id: 'f', name: 'Mug', slug: 'mug', price: 9, currency: 'USD', quantity: 0 },
122
+ { variantsByProductId: {} }
123
+ )
124
+ expect(flat.hasPurchasableVariant).toBe('true')
125
+ expect(flat.outOfStock).toBe('true')
126
+ })
127
+
128
+ it('always emits hasPurchasableVariant as a STRING (never boolean/undefined)', () => {
129
+ for (const options of [undefined, { variantsByProductId: null }, { variantsByProductId: {} }]) {
130
+ const product = buildEcommerceProduct(variantProduct(), options)
131
+ expect(typeof product.hasPurchasableVariant).toBe('string')
132
+ expect(['true', 'false']).toContain(product.hasPurchasableVariant)
133
+ }
134
+ })
135
+
136
+ it('a related product inherits the same known/unknown answer as its parent', () => {
137
+ const built = buildEcommerceProduct(variantProduct({ related_product_ids: '["p2"]' }), {
138
+ // Unknown for everybody — the nested build must NOT read this as "none".
139
+ variantsByProductId: null,
140
+ relatedProductsById: { p2: variantProduct({ id: 'p2', slug: 'p2' }) },
141
+ })
142
+ const related = (built.relatedProducts as Array<Record<string, unknown>>)[0]
143
+ expect(related.hasPurchasableVariant).toBe('true')
144
+ })
145
+ })
146
+
147
+ /**
148
+ * Runs the EMITTED `transformRecords` against a stub pg client, which is the only
149
+ * way to prove the wrapper's control flow — the order of the two lookups, and
150
+ * which ids reach the combinations query — rather than its text.
151
+ */
152
+ describe('transform wrapper — executed end to end', () => {
153
+ interface StubQuery {
154
+ sql: string
155
+ params: unknown[]
156
+ }
157
+
158
+ const runWrapper = async (
159
+ records: Array<Record<string, unknown>>,
160
+ rows: {
161
+ related?: Array<Record<string, unknown>>
162
+ variants?: Array<Record<string, unknown>>
163
+ failVariantsQuery?: boolean
164
+ }
165
+ ): Promise<{ out: Array<Record<string, unknown>>; queries: StubQuery[] }> => {
166
+ const bundle =
167
+ generateSharedTransformationCode() +
168
+ '\n' +
169
+ generateEcommerceProductTransformationCode() +
170
+ '\n' +
171
+ getTransformWrapperCode('teleport_products')
172
+ const transformRecords = new Function(bundle + '\nreturn transformRecords;')() as (
173
+ r: unknown,
174
+ getClient: unknown,
175
+ q: unknown
176
+ ) => Promise<Array<Record<string, unknown>>>
177
+
178
+ const queries: StubQuery[] = []
179
+ const query = async (
180
+ sql: string,
181
+ params: unknown[] = []
182
+ ): Promise<{ rows: Array<Record<string, unknown>> }> => {
183
+ queries.push({ sql, params })
184
+ if (sql.includes('teleport_assets')) {
185
+ return { rows: [] }
186
+ }
187
+ if (sql.includes('teleport_product_variants')) {
188
+ if (rows.failVariantsQuery) {
189
+ throw new Error('relation "teleport_product_variants" does not exist')
190
+ }
191
+ return { rows: rows.variants || [] }
192
+ }
193
+ if (sql.includes('teleport_products')) {
194
+ return { rows: rows.related || [] }
195
+ }
196
+ return { rows: [] }
197
+ }
198
+ const getClientFn = () => ({
199
+ connect: async (): Promise<void> => undefined,
200
+ end: async (): Promise<void> => undefined,
201
+ query,
202
+ })
203
+
204
+ const out = await transformRecords(records, getClientFn, {})
205
+ return { out, queries }
206
+ }
207
+
208
+ const variantQueryOf = (queries: StubQuery[]): StubQuery | undefined =>
209
+ queries.find((q) => q.sql.includes('teleport_product_variants'))
210
+
211
+ it("asks for the RELATED products' combinations in the same batched query", async () => {
212
+ const { out, queries } = await runWrapper([variantProduct({ related_product_ids: '["p2"]' })], {
213
+ related: [variantProduct({ id: 'p2', slug: 'p2' })],
214
+ variants: [
215
+ { id: 'v-p1', product_id: 'p1', options: { size: 's' }, quantity: 5 },
216
+ { id: 'v-p2', product_id: 'p2', options: { size: 'xs' }, quantity: 2 },
217
+ ],
218
+ })
219
+ // Both the page's own product AND the related one.
220
+ expect(variantQueryOf(queries)?.params[0]).toEqual(['p1', 'p2'])
221
+
222
+ const related = (out[0].relatedProducts as Array<Record<string, unknown>>)[0]
223
+ expect(related.hasPurchasableVariant).toBe('true')
224
+ expect(related.defaultVariantId).toBe('v-p2')
225
+ })
226
+
227
+ it('a FAILED combinations query leaves every product permissive, not unbuyable', async () => {
228
+ const { out, queries } = await runWrapper([variantProduct()], { failVariantsQuery: true })
229
+ expect(variantQueryOf(queries)).toBeTruthy()
230
+ expect(out[0].hasPurchasableVariant).toBe('true')
231
+ expect(values(out[0]).every((v) => v.isDead === 'false')).toBe(true)
232
+ })
233
+
234
+ it('a query that RAN and returned nothing marks the product unbuyable', async () => {
235
+ const { out } = await runWrapper([variantProduct()], { variants: [] })
236
+ expect(out[0].hasPurchasableVariant).toBe('false')
237
+ expect(values(out[0]).every((v) => v.isDead === 'true')).toBe(true)
238
+ })
239
+ })
240
+
241
+ describe('transform wrapper — the batched combinations query', () => {
242
+ const wrapper = getTransformWrapperCode('teleport_products')
243
+
244
+ it('starts the map at NULL so a failed lookup reads as unknown, not as none', () => {
245
+ expect(wrapper).toContain('var variantsByProductId = null')
246
+ })
247
+
248
+ it('resolves related items BEFORE variants, and asks for their combinations too', () => {
249
+ // The details page draws each related product as a real card with its own
250
+ // picker; fetching only the page's own ids left every one of them looking
251
+ // like a product with no combinations.
252
+ expect(wrapper.indexOf('relatedProductsById = await')).toBeGreaterThan(-1)
253
+ expect(wrapper.indexOf('relatedProductsById = await')).toBeLessThan(
254
+ wrapper.indexOf('getVariantsMap(')
255
+ )
256
+ expect(wrapper).toContain('__variantPids.push(__rrow.id)')
257
+ })
258
+
259
+ it('leaves the blog wrapper without any variant enrichment', () => {
260
+ const blog = getTransformWrapperCode('teleport_blog_posts')
261
+ expect(blog).not.toContain('getVariantsMap')
262
+ expect(blog).toContain('relatedPostsById')
263
+ })
264
+ })
@@ -0,0 +1,71 @@
1
+ import * as types from '@babel/types';
2
+ import { UIDLDependency } from '@teleporthq/teleport-types';
3
+ import { ResolvedDataSourceCache } from './types';
4
+ /** Identifiers the emitted page imports from `utils/tq-cache/client`. */
5
+ export declare const CACHE_CLIENT_IMPORTS: string[];
6
+ export declare const cachedValueVarFor: (index: number) => string;
7
+ /**
8
+ * Registers the client runtime's named imports on the page.
9
+ *
10
+ * Each identifier is its own dependency entry because that is how the
11
+ * import-statements plugin keys them; they share one path, so they collapse
12
+ * into a single `import { … } from '…/utils/tq-cache/client'`.
13
+ */
14
+ export declare const registerCacheClientImports: (dependencies: Record<string, UIDLDependency>, folderPath: string[] | undefined) => void;
15
+ /**
16
+ * The terminal `.then` of a cached fetch: record the version the server
17
+ * answered with (which purges the scope if it moved) and store the rows.
18
+ *
19
+ * `tqCacheSet` returns the value it was given, so the promise still resolves to
20
+ * exactly what the uncached chain resolved to — `response?.data`.
21
+ */
22
+ export declare const buildCacheStoreThen: (cache: ResolvedDataSourceCache) => types.ArrowFunctionExpression;
23
+ /** Wraps a network chain in the peek preamble, producing the cached body. */
24
+ export declare const buildCachedFetchBody: (networkChain: types.Expression, cache: ResolvedDataSourceCache) => types.BlockStatement;
25
+ /**
26
+ * Finds the `return <fetch(...)…>` statement inside a cached `fetchData` body.
27
+ *
28
+ * Shared with `loading-state` so both modules agree on what "the network chain"
29
+ * means: the body also contains an early `return Promise.resolve(hit)`, and
30
+ * attaching in-flight bookkeeping to THAT would flip the loading flag on every
31
+ * cache hit — the exact flash this feature exists to remove.
32
+ */
33
+ export declare const findCachedFetchNetworkChain: (body: types.BlockStatement) => {
34
+ statement: types.ReturnStatement;
35
+ index: number;
36
+ } | undefined;
37
+ /**
38
+ * Hoists a cached provider's `params` into a component const and adds the
39
+ * synchronous cache peek beside it.
40
+ *
41
+ * The peek is what removes the loading flash on a page or search change: those
42
+ * change the provider's `key`, so it REMOUNTS with `data: undefined` and paints
43
+ * `renderLoading()` before any promise — even an already-resolved one — can
44
+ * resume. Feeding a hit into `initialData` makes the provider skip its first
45
+ * fetch entirely and paint the cached rows on the very first frame.
46
+ *
47
+ * `sticky` is set because this value is handed to a mounted provider: once it
48
+ * has been, TTL expiry must not flip it back to `undefined`, or the list would
49
+ * blank out without refetching (its `params` never changed).
50
+ *
51
+ * Reference identity comes from the runtime's own map, not from this `useMemo`
52
+ * — the memo only keeps the peek from re-running on unrelated renders.
53
+ */
54
+ export declare const buildCachedParamsDeclarations: (params: {
55
+ index: number;
56
+ paramsMemo: types.Expression;
57
+ cache: ResolvedDataSourceCache;
58
+ }) => {
59
+ declarations: types.Statement[];
60
+ paramsIdentifier: string;
61
+ cachedIdentifier: string;
62
+ };
63
+ /**
64
+ * `useEffect(() => { tqMarkHydrated(); tqCacheRevalidate([...]) }, [])`
65
+ *
66
+ * One effect per page, covering every scope on it in a single request. Flipping
67
+ * the hydration latch here rather than at import time is what keeps the first
68
+ * client render byte-identical to the server render.
69
+ */
70
+ export declare const buildCacheHydrationEffect: (scopes: string[]) => types.Statement;
71
+ //# sourceMappingURL=ast.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.d.ts","sourceRoot":"","sources":["../../../src/cache/ast.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,cAAc,CAAA;AACrC,OAAO,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAEjD,yEAAyE;AACzE,eAAO,MAAM,oBAAoB,UAOhC,CAAA;AAMD,eAAO,MAAM,iBAAiB,UAAW,MAAM,KAAG,MAA8B,CAAA;AAEhF;;;;;;GAMG;AACH,eAAO,MAAM,0BAA0B,iBACvB,OAAO,MAAM,EAAE,cAAc,CAAC,cAChC,MAAM,EAAE,GAAG,SAAS,KAC/B,IAaF,CAAA;AAyCD;;;;;;GAMG;AACH,eAAO,MAAM,mBAAmB,UACvB,uBAAuB,KAC7B,MAAM,uBAkCR,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,oBAAoB,iBACjB,MAAM,UAAU,SACvB,uBAAuB,KAC7B,MAAM,cAIL,CAAA;AAEJ;;;;;;;GAOG;AACH,eAAO,MAAM,2BAA2B,SAChC,MAAM,cAAc,KACzB;IAAE,SAAS,EAAE,MAAM,eAAe,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,SAcxD,CAAA;AAkBD;;;;;;;;;;;;;;;;GAgBG;AACH,eAAO,MAAM,6BAA6B,WAAY;IACpD,KAAK,EAAE,MAAM,CAAA;IACb,UAAU,EAAE,MAAM,UAAU,CAAA;IAC5B,KAAK,EAAE,uBAAuB,CAAA;CAC/B;kBACe,MAAM,SAAS,EAAE;sBACb,MAAM;sBACN,MAAM;CAkCzB,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,yBAAyB,WAAY,MAAM,EAAE,KAAG,MAAM,SAgBhE,CAAA"}
@@ -0,0 +1,229 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
26
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
27
+ if (ar || !(i in from)) {
28
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
29
+ ar[i] = from[i];
30
+ }
31
+ }
32
+ return to.concat(ar || Array.prototype.slice.call(from));
33
+ };
34
+ Object.defineProperty(exports, "__esModule", { value: true });
35
+ exports.buildCacheHydrationEffect = exports.buildCachedParamsDeclarations = exports.findCachedFetchNetworkChain = exports.buildCachedFetchBody = exports.buildCacheStoreThen = exports.registerCacheClientImports = exports.cachedValueVarFor = exports.CACHE_CLIENT_IMPORTS = void 0;
36
+ var types = __importStar(require("@babel/types"));
37
+ /** Identifiers the emitted page imports from `utils/tq-cache/client`. */
38
+ exports.CACHE_CLIENT_IMPORTS = [
39
+ 'tqCacheKey',
40
+ 'tqCacheGet',
41
+ 'tqCacheSet',
42
+ 'tqCacheSetVersion',
43
+ 'tqMarkHydrated',
44
+ 'tqCacheRevalidate',
45
+ ];
46
+ /** Local identifiers used inside the generated `fetchData` body. */
47
+ var KEY_VAR = '__tqKey';
48
+ var HIT_VAR = '__tqHit';
49
+ var cachedValueVarFor = function (index) { return "ds_".concat(index, "_cached"); };
50
+ exports.cachedValueVarFor = cachedValueVarFor;
51
+ /**
52
+ * Registers the client runtime's named imports on the page.
53
+ *
54
+ * Each identifier is its own dependency entry because that is how the
55
+ * import-statements plugin keys them; they share one path, so they collapse
56
+ * into a single `import { … } from '…/utils/tq-cache/client'`.
57
+ */
58
+ var registerCacheClientImports = function (dependencies, folderPath) {
59
+ var depth = (folderPath ? folderPath.length : 0) + 1;
60
+ var path = "".concat('../'.repeat(depth), "utils/tq-cache/client");
61
+ exports.CACHE_CLIENT_IMPORTS.forEach(function (identifier) {
62
+ if (!dependencies[identifier]) {
63
+ dependencies[identifier] = {
64
+ type: 'local',
65
+ path: path,
66
+ meta: { namedImport: true },
67
+ };
68
+ }
69
+ });
70
+ };
71
+ exports.registerCacheClientImports = registerCacheClientImports;
72
+ /**
73
+ * `const __tqKey = tqCacheKey(params)` +
74
+ * `const __tqHit = tqCacheGet(SCOPE, __tqKey)` +
75
+ * `if (__tqHit !== undefined) return Promise.resolve(__tqHit)`
76
+ *
77
+ * The early return is what keeps a hit from ever touching the network — and,
78
+ * just as importantly, from raising the in-flight flag that would paint the
79
+ * loading slot. `loading-state` deliberately attaches its bookkeeping to the
80
+ * network chain BELOW this, never to the `Promise.resolve`.
81
+ */
82
+ var buildCachePeekPreamble = function (scope) { return [
83
+ types.variableDeclaration('const', [
84
+ types.variableDeclarator(types.identifier(KEY_VAR), types.callExpression(types.identifier('tqCacheKey'), [types.identifier('params')])),
85
+ ]),
86
+ types.variableDeclaration('const', [
87
+ types.variableDeclarator(types.identifier(HIT_VAR), types.callExpression(types.identifier('tqCacheGet'), [
88
+ types.stringLiteral(scope),
89
+ types.identifier(KEY_VAR),
90
+ ])),
91
+ ]),
92
+ types.ifStatement(types.binaryExpression('!==', types.identifier(HIT_VAR), types.identifier('undefined')), types.blockStatement([
93
+ types.returnStatement(types.callExpression(types.memberExpression(types.identifier('Promise'), types.identifier('resolve')), [types.identifier(HIT_VAR)])),
94
+ ])),
95
+ ]; };
96
+ /**
97
+ * The terminal `.then` of a cached fetch: record the version the server
98
+ * answered with (which purges the scope if it moved) and store the rows.
99
+ *
100
+ * `tqCacheSet` returns the value it was given, so the promise still resolves to
101
+ * exactly what the uncached chain resolved to — `response?.data`.
102
+ */
103
+ var buildCacheStoreThen = function (cache) {
104
+ var responseData = types.optionalMemberExpression(types.identifier('response'), types.identifier('data'), false, true);
105
+ var responseVersion = types.optionalMemberExpression(types.identifier('response'), types.identifier('version'), false, true);
106
+ return types.arrowFunctionExpression([types.identifier('response')], types.blockStatement([
107
+ types.expressionStatement(types.callExpression(types.identifier('tqCacheSetVersion'), [
108
+ types.stringLiteral(cache.scope),
109
+ types.cloneNode(responseVersion, true),
110
+ ])),
111
+ types.returnStatement(types.callExpression(types.identifier('tqCacheSet'), [
112
+ types.stringLiteral(cache.scope),
113
+ types.identifier(KEY_VAR),
114
+ responseData,
115
+ types.numericLiteral(cache.ttlSeconds),
116
+ types.cloneNode(responseVersion, true),
117
+ ])),
118
+ ]));
119
+ };
120
+ exports.buildCacheStoreThen = buildCacheStoreThen;
121
+ /** Wraps a network chain in the peek preamble, producing the cached body. */
122
+ var buildCachedFetchBody = function (networkChain, cache) {
123
+ return types.blockStatement(__spreadArray(__spreadArray([], buildCachePeekPreamble(cache.scope), true), [
124
+ types.returnStatement(networkChain),
125
+ ], false));
126
+ };
127
+ exports.buildCachedFetchBody = buildCachedFetchBody;
128
+ /**
129
+ * Finds the `return <fetch(...)…>` statement inside a cached `fetchData` body.
130
+ *
131
+ * Shared with `loading-state` so both modules agree on what "the network chain"
132
+ * means: the body also contains an early `return Promise.resolve(hit)`, and
133
+ * attaching in-flight bookkeeping to THAT would flip the loading flag on every
134
+ * cache hit — the exact flash this feature exists to remove.
135
+ */
136
+ var findCachedFetchNetworkChain = function (body) {
137
+ for (var index = body.body.length - 1; index >= 0; index--) {
138
+ var statement = body.body[index];
139
+ if (statement.type !== 'ReturnStatement' || !statement.argument) {
140
+ continue;
141
+ }
142
+ if (statement.argument.type === 'CallExpression' &&
143
+ callChainStartsWithFetch(statement.argument)) {
144
+ return { statement: statement, index: index };
145
+ }
146
+ }
147
+ return undefined;
148
+ };
149
+ exports.findCachedFetchNetworkChain = findCachedFetchNetworkChain;
150
+ var callChainStartsWithFetch = function (expression) {
151
+ var current = expression;
152
+ while (current.type === 'CallExpression') {
153
+ var callee = current.callee;
154
+ if (callee.type === 'Identifier' && callee.name === 'fetch') {
155
+ return true;
156
+ }
157
+ if (callee.type === 'MemberExpression') {
158
+ current = callee.object;
159
+ continue;
160
+ }
161
+ return false;
162
+ }
163
+ return false;
164
+ };
165
+ /**
166
+ * Hoists a cached provider's `params` into a component const and adds the
167
+ * synchronous cache peek beside it.
168
+ *
169
+ * The peek is what removes the loading flash on a page or search change: those
170
+ * change the provider's `key`, so it REMOUNTS with `data: undefined` and paints
171
+ * `renderLoading()` before any promise — even an already-resolved one — can
172
+ * resume. Feeding a hit into `initialData` makes the provider skip its first
173
+ * fetch entirely and paint the cached rows on the very first frame.
174
+ *
175
+ * `sticky` is set because this value is handed to a mounted provider: once it
176
+ * has been, TTL expiry must not flip it back to `undefined`, or the list would
177
+ * blank out without refetching (its `params` never changed).
178
+ *
179
+ * Reference identity comes from the runtime's own map, not from this `useMemo`
180
+ * — the memo only keeps the peek from re-running on unrelated renders.
181
+ */
182
+ var buildCachedParamsDeclarations = function (params) {
183
+ var paramsIdentifier = "ds_".concat(params.index, "_params");
184
+ var cachedIdentifier = (0, exports.cachedValueVarFor)(params.index);
185
+ return {
186
+ paramsIdentifier: paramsIdentifier,
187
+ cachedIdentifier: cachedIdentifier,
188
+ declarations: [
189
+ types.variableDeclaration('const', [
190
+ types.variableDeclarator(types.identifier(paramsIdentifier), params.paramsMemo),
191
+ ]),
192
+ types.variableDeclaration('const', [
193
+ types.variableDeclarator(types.identifier(cachedIdentifier), types.callExpression(types.identifier('useMemo'), [
194
+ types.arrowFunctionExpression([], types.callExpression(types.identifier('tqCacheGet'), [
195
+ types.stringLiteral(params.cache.scope),
196
+ types.callExpression(types.identifier('tqCacheKey'), [
197
+ types.identifier(paramsIdentifier),
198
+ ]),
199
+ types.objectExpression([
200
+ types.objectProperty(types.identifier('sticky'), types.booleanLiteral(true)),
201
+ ]),
202
+ ])),
203
+ types.arrayExpression([types.identifier(paramsIdentifier)]),
204
+ ])),
205
+ ]),
206
+ ],
207
+ };
208
+ };
209
+ exports.buildCachedParamsDeclarations = buildCachedParamsDeclarations;
210
+ /**
211
+ * `useEffect(() => { tqMarkHydrated(); tqCacheRevalidate([...]) }, [])`
212
+ *
213
+ * One effect per page, covering every scope on it in a single request. Flipping
214
+ * the hydration latch here rather than at import time is what keeps the first
215
+ * client render byte-identical to the server render.
216
+ */
217
+ var buildCacheHydrationEffect = function (scopes) {
218
+ return types.expressionStatement(types.callExpression(types.identifier('useEffect'), [
219
+ types.arrowFunctionExpression([], types.blockStatement([
220
+ types.expressionStatement(types.callExpression(types.identifier('tqMarkHydrated'), [])),
221
+ types.expressionStatement(types.callExpression(types.identifier('tqCacheRevalidate'), [
222
+ types.arrayExpression(scopes.map(function (scope) { return types.stringLiteral(scope); })),
223
+ ])),
224
+ ])),
225
+ types.arrayExpression([]),
226
+ ]));
227
+ };
228
+ exports.buildCacheHydrationEffect = buildCacheHydrationEffect;
229
+ //# sourceMappingURL=ast.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ast.js","sourceRoot":"","sources":["../../../src/cache/ast.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { UIDLDataCacheConfig } from '@teleporthq/teleport-types';
2
+ import { DataSourceServerCacheOptions, ResolvedDataSourceCache } from './types';
3
+ /**
4
+ * Reads the `cache` block off a `cms-list-repeater`.
5
+ *
6
+ * Returns `undefined` — meaning "emit exactly what this generator emitted
7
+ * before caching existed" — for anything that is off, incomplete, or caches
8
+ * into neither layer.
9
+ */
10
+ export declare const resolveCacheFromRepeaterContent: (cache: UIDLDataCacheConfig | undefined, resourceDefinition: {
11
+ dataSourceId?: string;
12
+ tableName?: string;
13
+ } | undefined) => ResolvedDataSourceCache | undefined;
14
+ /**
15
+ * Folds several mappers' requests for the same generated file into one.
16
+ *
17
+ * Enabled if ANY mapper wants it, but with the SHORTEST requested TTL and the
18
+ * shortest shared-cache window — a mapper that asked for fresher data must
19
+ * never be made staler by a sibling that asked for less.
20
+ */
21
+ export declare const mergeServerCacheOptions: (entries: DataSourceServerCacheOptions[]) => DataSourceServerCacheOptions | undefined;
22
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../../src/cache/config.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,mBAAmB,EAAE,MAAM,4BAA4B,CAAA;AAChE,OAAO,EAAE,4BAA4B,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAE/E;;;;;;GAMG;AACH,eAAO,MAAM,+BAA+B,UACnC,mBAAmB,GAAG,SAAS,sBAClB;IAAE,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,KAC5E,uBAAuB,GAAG,SAoC5B,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,uBAAuB,YACzB,4BAA4B,EAAE,KACtC,4BAA4B,GAAG,SAiBjC,CAAA"}