diff --git a/docs/components/Example.tsx b/docs/components/Example.tsx
index 78876293..d022a6af 100644
--- a/docs/components/Example.tsx
+++ b/docs/components/Example.tsx
@@ -22,7 +22,7 @@ function Timestamp({ children }: { children: TimestampType }) {
fontSize: '1.13em',
fontWeight: 'bold',
fontFamily: 'monospace',
- marginRight: 2
+ marginRight: 2,
}}
>
{children}
diff --git a/docs/headings.ts b/docs/headings.ts
index cdaa3584..769f7cd1 100644
--- a/docs/headings.ts
+++ b/docs/headings.ts
@@ -200,6 +200,11 @@ export const headings: HeadingDefinition[] = [
title: '`root`',
url: '/root',
},
+ {
+ level: 2,
+ title: '`shield`',
+ url: '/shield-config',
+ },
{
level: 4,
title: 'Plugins',
diff --git a/docs/pages/shield-config/+Page.mdx b/docs/pages/shield-config/+Page.mdx
new file mode 100644
index 00000000..8331b137
--- /dev/null
+++ b/docs/pages/shield-config/+Page.mdx
@@ -0,0 +1,19 @@
+import { Link, Warning } from '@brillout/docpress'
+import { ConfigWhereServer } from '../../components'
+
+**Environment**: server.
+**Default**: `false`.
+
+Whether to generate `shield()` in development.
+
+```js
+// Environment: server
+
+import { config } from 'telefunc'
+
+config.shield.dev = true
+```
+
+This can slow down development speed. Depending on your app and how fast your computer is, the decreased development speed can range from unnoticeable to significant.
+
+
diff --git a/docs/pages/shield/+Page.mdx b/docs/pages/shield/+Page.mdx
index aa4d0aaf..e93f590d 100644
--- a/docs/pages/shield/+Page.mdx
+++ b/docs/pages/shield/+Page.mdx
@@ -43,6 +43,10 @@ export async function hello({ name }: { name: string }) {
With Telefunc, not only can we seamlessly re-use types across our frontend and backend code, but we also get automatic type-safety at runtime. If we use a TypeScript ORM (e.g. [Prisma](https://www.prisma.io/)) or SQL builder (e.g. [Kysely](https://github.com/koskimas/kysely) and [others](https://github.com/stars/brillout/lists/sql)), then we get end-to-end type safety all the way from database to frontend.
+> For a faster development, Telefunc doesn't generate `shield()` and your telefunction arguments aren't validated during development.
+> Telefunc only generates `shield()` upon building your app for production.
+> You can enable the generation of `shield()` for development by setting `config.shield.dev` to `true`.
+
> Telefunc's automatic `shield()` generation only works for stacks that transpile server-side code (Next.js, Vite, Vike, SvelteKit, Nuxt, etc.).
>
> For stacks that don't transpile server-side code (e.g. React Native, CRA, Parcel), we need to define `shield()` manually ourselves: see .
diff --git a/telefunc/node/server/serverConfig.ts b/telefunc/node/server/serverConfig.ts
index f3b0cd2d..980528ae 100644
--- a/telefunc/node/server/serverConfig.ts
+++ b/telefunc/node/server/serverConfig.ts
@@ -21,8 +21,12 @@ type ConfigUser = {
telefuncFiles?: string[]
/** Your project root directory, e.g. `/home/alice/code/my-app/` */
root?: string
- /** Wether to disable ETag cache headers */
+ /** Whether to disable ETag cache headers */
disableEtag?: boolean
+ shield?: {
+ /** Whether to generate shield during development */
+ dev?: boolean
+ }
}
type ConfigResolved = {
telefuncUrl: string
@@ -30,6 +34,7 @@ type ConfigResolved = {
disableEtag: boolean
telefuncFiles: string[] | null
disableNamingConvention: boolean
+ shield: { dev: boolean }
}
const configUser: ConfigUser = new Proxy({}, { set: validateUserConfig })
@@ -38,6 +43,7 @@ function getServerConfig(): ConfigResolved {
return {
disableEtag: configUser.disableEtag ?? false,
disableNamingConvention: configUser.disableNamingConvention ?? false,
+ shield: { dev: configUser.shield?.dev ?? false },
telefuncUrl: configUser.telefuncUrl || '/_telefunc',
telefuncFiles: (() => {
if (configUser.telefuncFiles) {
@@ -68,7 +74,7 @@ function validateUserConfig(configUserUnwrapped: ConfigUser, prop: string, val:
)
configUserUnwrapped[prop] = val
} else if (prop === 'telefuncFiles') {
- const wrongType = '`config.telefuncFiles` should be a list of paths'
+ const wrongType = 'config.telefuncFiles should be a list of paths'
assertUsage(Array.isArray(val), wrongType)
val.forEach((val: unknown) => {
assertUsage(typeof val === 'string', wrongType)
@@ -80,7 +86,13 @@ function validateUserConfig(configUserUnwrapped: ConfigUser, prop: string, val:
assertUsage(typeof val === 'boolean', 'config.disableEtag should be a boolean')
configUserUnwrapped[prop] = val
} else if (prop === 'disableNamingConvention') {
- assertUsage(typeof val === 'boolean', '`config.disableNamingConvention` should be a boolean')
+ assertUsage(typeof val === 'boolean', 'config.disableNamingConvention should be a boolean')
+ configUserUnwrapped[prop] = val
+ } else if (prop === 'shield') {
+ assertUsage(typeof val === 'object' && val !== null, 'config.shield should be a object')
+ if ('dev' in val) {
+ assertUsage(typeof (val as { dev: unknown }).dev === 'boolean', 'config.shield.dev should be a boolean')
+ }
configUserUnwrapped[prop] = val
} else {
assertUsage(false, `Unknown config.${prop}`)
diff --git a/telefunc/node/server/shield/codegen/generateShield.ts b/telefunc/node/server/shield/codegen/generateShield.ts
index c235aafd..0f4c066a 100644
--- a/telefunc/node/server/shield/codegen/generateShield.ts
+++ b/telefunc/node/server/shield/codegen/generateShield.ts
@@ -84,7 +84,7 @@ function getProject(telefuncFilePath: string, telefuncFileCode: string, appRootD
path.dirname(telefuncFilePath),
`__telefunc_shieldGen_${path.basename(telefuncFilePath)}`,
)
- const shieldGenSource = project.createSourceFile(shieldGenFilePath)
+ const shieldGenSource = project.createSourceFile(shieldGenFilePath, undefined, { overwrite: true })
shieldGenSource.addImportDeclaration({
moduleSpecifier: getImportPath(shieldGenFilePath, typeToShieldFilePath),
namedImports: ['ShieldArrStr'],
diff --git a/telefunc/node/transformer/transformTelefuncFileServerSide.ts b/telefunc/node/transformer/transformTelefuncFileServerSide.ts
index 3ddc9e19..a44185ca 100644
--- a/telefunc/node/transformer/transformTelefuncFileServerSide.ts
+++ b/telefunc/node/transformer/transformTelefuncFileServerSide.ts
@@ -3,6 +3,7 @@ export { transformTelefuncFileServerSide }
import { getExportNames } from './getExportNames'
import { assertPosixPath } from './utils'
import { generateShield } from '../server/shield/codegen/generateShield'
+import { getServerConfig } from '../server/serverConfig'
async function transformTelefuncFileServerSide(
src: string,
@@ -17,7 +18,8 @@ async function transformTelefuncFileServerSide(
const exportNames = await getExportNames(src)
let code = decorateTelefunctions(exportNames, src, id.replace(appRootDir, ''), appRootDir, skipRegistration)
- if (id.endsWith('.ts') && !isDev) {
+ const config = getServerConfig()
+ if (id.endsWith('.ts') && (!isDev || config.shield.dev)) {
code = generateShield(code, id, appRootDir)
}