@teleporthq/teleport-plugin-next-static-props 0.44.0 → 0.44.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/__tests__/visitor-read.test.ts +157 -0
- package/dist/cjs/index.d.ts.map +1 -1
- package/dist/cjs/index.js +19 -5
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/tsconfig.tsbuildinfo +1 -1
- package/dist/cjs/utils.d.ts +1 -1
- package/dist/cjs/utils.d.ts.map +1 -1
- package/dist/cjs/utils.js +35 -6
- package/dist/cjs/utils.js.map +1 -1
- package/dist/esm/index.d.ts.map +1 -1
- package/dist/esm/index.js +20 -6
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/dist/esm/utils.d.ts +1 -1
- package/dist/esm/utils.d.ts.map +1 -1
- package/dist/esm/utils.js +35 -6
- package/dist/esm/utils.js.map +1 -1
- package/package.json +3 -3
- package/src/index.ts +35 -3
- package/src/utils.ts +56 -3
package/src/index.ts
CHANGED
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
FileType,
|
|
6
6
|
TeleportError,
|
|
7
7
|
} from '@teleporthq/teleport-types'
|
|
8
|
-
import { StringUtils, GenericUtils } from '@teleporthq/teleport-shared'
|
|
8
|
+
import { StringUtils, GenericUtils, TableAccess } from '@teleporthq/teleport-shared'
|
|
9
9
|
import { RouteUtils } from '@teleporthq/teleport-plugin-common'
|
|
10
10
|
import { generateInitialPropsAST } from './utils'
|
|
11
11
|
|
|
@@ -13,7 +13,17 @@ interface StaticPropsPluginConfig {
|
|
|
13
13
|
componentChunkName?: string
|
|
14
14
|
}
|
|
15
15
|
|
|
16
|
-
const {
|
|
16
|
+
const {
|
|
17
|
+
isDynamicRoute,
|
|
18
|
+
pageDataReadArguments,
|
|
19
|
+
pageDataReadsAsStore,
|
|
20
|
+
pageHasSameTableMutationWorkflow,
|
|
21
|
+
pageReadsProtectedTable,
|
|
22
|
+
} = RouteUtils
|
|
23
|
+
|
|
24
|
+
// The data sources whose read routes guard their tables (see
|
|
25
|
+
// teleport-plugin-next-data-source `table-access-guard.ts`).
|
|
26
|
+
const GUARDED_SOURCE_TYPES = ['teleport', 'postgresql']
|
|
17
27
|
|
|
18
28
|
export const createStaticPropsPlugin: ComponentPluginFactory<StaticPropsPluginConfig> = (
|
|
19
29
|
config
|
|
@@ -50,6 +60,10 @@ export const createStaticPropsPlugin: ComponentPluginFactory<StaticPropsPluginCo
|
|
|
50
60
|
Name of the function that is being imported
|
|
51
61
|
*/
|
|
52
62
|
let resourceImportName
|
|
63
|
+
// The page's row is what it renders, so it is read as a visitor is served
|
|
64
|
+
// it — unless only the store's trusted readers can open the page.
|
|
65
|
+
const readsAsVisitor = !pageDataReadsAsStore(uidl, options.auth)
|
|
66
|
+
let entityReadable = true
|
|
53
67
|
|
|
54
68
|
if (isLocalResource) {
|
|
55
69
|
const usedResource = resources.items?.[resource.id]
|
|
@@ -63,6 +77,20 @@ export const createStaticPropsPlugin: ComponentPluginFactory<StaticPropsPluginCo
|
|
|
63
77
|
StringUtils.camelCaseToDashCase(usedResource.name + 'Resource')
|
|
64
78
|
)
|
|
65
79
|
|
|
80
|
+
// A visitor is served no row of an order or a gift card, so a page that
|
|
81
|
+
// is not the admin's renders without one rather than carry a row read as
|
|
82
|
+
// the store. A member's page reads their public profile only (see
|
|
83
|
+
// `TableAccess.PUBLIC_PROFILE_COLUMNS`): read as the store, it put any
|
|
84
|
+
// member's whole account in the page data of whoever opened `/profile/<id>`.
|
|
85
|
+
const tableName = usedResource.params?.tableName?.content
|
|
86
|
+
const sourceType = usedResource.params?.dataSourceType?.content
|
|
87
|
+
entityReadable = !(
|
|
88
|
+
readsAsVisitor &&
|
|
89
|
+
typeof tableName === 'string' &&
|
|
90
|
+
GUARDED_SOURCE_TYPES.indexOf(String(sourceType)) !== -1 &&
|
|
91
|
+
TableAccess.pageDataReadsNoRowOf(tableName)
|
|
92
|
+
)
|
|
93
|
+
|
|
66
94
|
dependencies[resourceImportName] = {
|
|
67
95
|
type: 'local',
|
|
68
96
|
path: `${GenericUtils.generatePageDependenciesPrefix({
|
|
@@ -83,7 +111,11 @@ export const createStaticPropsPlugin: ComponentPluginFactory<StaticPropsPluginCo
|
|
|
83
111
|
resourceImportName,
|
|
84
112
|
resources.cache,
|
|
85
113
|
options.skipI18n,
|
|
86
|
-
useServerSideProps
|
|
114
|
+
useServerSideProps,
|
|
115
|
+
// A resource the project generated forwards it to the data-source module;
|
|
116
|
+
// another package's function takes its own arguments.
|
|
117
|
+
() => (isLocalResource ? pageDataReadArguments(uidl, options.auth) : []),
|
|
118
|
+
entityReadable
|
|
87
119
|
)
|
|
88
120
|
|
|
89
121
|
// NOTE: the chunk is always registered under the 'getStaticProps' name
|
package/src/utils.ts
CHANGED
|
@@ -19,7 +19,11 @@ export const generateInitialPropsAST = (
|
|
|
19
19
|
* auth-gated per request, so there is no real CDN-caching upside being
|
|
20
20
|
* traded away. See `createStaticPropsPlugin` for the selection logic.
|
|
21
21
|
*/
|
|
22
|
-
useServerSideProps?: boolean
|
|
22
|
+
useServerSideProps?: boolean,
|
|
23
|
+
/** What the page's read hands the resource after its params (`{ as: 'visitor' }`). */
|
|
24
|
+
readArguments: () => types.Expression[] = () => [],
|
|
25
|
+
/** False when the page's reader is served no row of the table: it renders without one. */
|
|
26
|
+
entityReadable: boolean = true
|
|
23
27
|
) => {
|
|
24
28
|
// Destructure params from context so expr-type resource params can reference `params` directly
|
|
25
29
|
const paramsDestructureAST = types.variableDeclaration('const', [
|
|
@@ -51,7 +55,9 @@ export const generateInitialPropsAST = (
|
|
|
51
55
|
resourceImportName,
|
|
52
56
|
revalidateSeconds,
|
|
53
57
|
skipI18n,
|
|
54
|
-
useServerSideProps
|
|
58
|
+
useServerSideProps,
|
|
59
|
+
readArguments,
|
|
60
|
+
entityReadable
|
|
55
61
|
),
|
|
56
62
|
]),
|
|
57
63
|
types.catchClause(
|
|
@@ -138,7 +144,9 @@ const computePropsAST = (
|
|
|
138
144
|
resourceImportName: string,
|
|
139
145
|
revalidateSeconds: number | null,
|
|
140
146
|
skipI18n?: boolean,
|
|
141
|
-
useServerSideProps?: boolean
|
|
147
|
+
useServerSideProps?: boolean,
|
|
148
|
+
readArguments: () => types.Expression[] = () => [],
|
|
149
|
+
entityReadable: boolean = true
|
|
142
150
|
) => {
|
|
143
151
|
const funcParams: types.ObjectProperty[] = Object.keys(
|
|
144
152
|
initialPropsData.resource?.params || {}
|
|
@@ -218,6 +226,7 @@ const computePropsAST = (
|
|
|
218
226
|
: types.cloneNode(param, true)
|
|
219
227
|
),
|
|
220
228
|
]),
|
|
229
|
+
...readArguments(),
|
|
221
230
|
])
|
|
222
231
|
)
|
|
223
232
|
|
|
@@ -288,6 +297,10 @@ const computePropsAST = (
|
|
|
288
297
|
)
|
|
289
298
|
)
|
|
290
299
|
|
|
300
|
+
if (!entityReadable) {
|
|
301
|
+
return [buildUnreadableEntityReturnAST(initialPropsData, revalidateProperty)]
|
|
302
|
+
}
|
|
303
|
+
|
|
291
304
|
return [
|
|
292
305
|
declarationAST,
|
|
293
306
|
notFoundAST,
|
|
@@ -297,6 +310,46 @@ const computePropsAST = (
|
|
|
297
310
|
]
|
|
298
311
|
}
|
|
299
312
|
|
|
313
|
+
/**
|
|
314
|
+
* The page, without its row: `{ props: { ...context?.params, <exposeAs>: null } }`.
|
|
315
|
+
*
|
|
316
|
+
* For a page whose reader is served no row of the table it shows (an order, a
|
|
317
|
+
* gift card — see `TableAccess.pageDataReadsNoRowOf`). Reading it as the
|
|
318
|
+
* store put another member's row in the page data of whoever opened the
|
|
319
|
+
* address; reading it as the visitor is always refused, which would 404 the
|
|
320
|
+
* page whatever else it shows.
|
|
321
|
+
*/
|
|
322
|
+
const buildUnreadableEntityReturnAST = (
|
|
323
|
+
initialPropsData: UIDLInitialPropsData,
|
|
324
|
+
revalidateProperty: () => types.ObjectProperty | null
|
|
325
|
+
): types.ReturnStatement =>
|
|
326
|
+
types.returnStatement(
|
|
327
|
+
types.objectExpression(
|
|
328
|
+
[
|
|
329
|
+
types.objectProperty(
|
|
330
|
+
types.identifier('props'),
|
|
331
|
+
types.objectExpression([
|
|
332
|
+
types.spreadElement(
|
|
333
|
+
types.optionalMemberExpression(
|
|
334
|
+
types.identifier('context'),
|
|
335
|
+
types.identifier('params'),
|
|
336
|
+
false,
|
|
337
|
+
true
|
|
338
|
+
)
|
|
339
|
+
),
|
|
340
|
+
types.objectProperty(
|
|
341
|
+
types.identifier(
|
|
342
|
+
StringUtils.createStateOrPropStoringValue(initialPropsData.exposeAs.name)
|
|
343
|
+
),
|
|
344
|
+
types.nullLiteral()
|
|
345
|
+
),
|
|
346
|
+
])
|
|
347
|
+
),
|
|
348
|
+
revalidateProperty(),
|
|
349
|
+
].filter(Boolean)
|
|
350
|
+
)
|
|
351
|
+
)
|
|
352
|
+
|
|
300
353
|
/**
|
|
301
354
|
* A page that shows a SUBSET of a table's rows (`redirect.unlessFieldEquals`)
|
|
302
355
|
* and names the filter selecting its own rows (`redirect.ownRowsFilter`): two
|