forked from nullstack/nullstack.github.io
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathserver-functions.html
More file actions
200 lines (163 loc) · 44.2 KB
/
server-functions.html
File metadata and controls
200 lines (163 loc) · 44.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="generator" content="Created with Nullstack - https://nullstack.app" />
<title>Server Functions - Nullstack</title>
<meta property="og:image" content="https://nullstack.app/image-1200x630.png">
<meta property="og:description" content="Server functions are specialized microservices that at transpile time are converted into API entry points">
<meta name="description" content="Server functions are specialized microservices that at transpile time are converted into API entry points">
<meta property="og:title" content="Server Functions - Nullstack">
<meta property="og:type" content="website">
<meta property="og:site_name" content="Nullstack">
<meta property="og:url" content="https://nullstack.app/server-functions">
<link rel="canonical" href="https://nullstack.app/server-functions">
<link rel="shortcut icon" href="/favicon-96x96.png" type="image/png">
<link rel="icon" href="/favicon-96x96.png" type="image/png">
<link rel="manifest" href="/manifest-9cdb5778f42a90a83e1427c9316c97d3.json" integrity="sha512-dZgijzedfi73kz1kWm59C1cCtmMc4h1r1cC/8LGrn8niVN5QOpk6VM3id275XMzw8LrPIohK8bk3c6V070nTMQ==">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="application-name" content="Nullstack">
<meta name="apple-mobile-web-app-title" content="Nullstack">
<meta name="msapplication-starturl" content="/">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="/client-9cdb5778f42a90a83e1427c9316c97d3.css" integrity="sha512-vAsFDGKdbOGUQaOLYLKiX8r3HWxKUnFNQey2a+9WANJhm1gKi2IrFswhS7QmzjtA8i9eMqiCe495kTyh3Jpnfg==" crossorigin="anonymous">
<link rel="apple-touch-icon" sizes="180x180" href="/icon-180x180.png">
<meta name="msapplication-TileColor" content="#2d3748">
<link rel="preconnect" href="https://www.googletagmanager.com"/><link rel="preload" href="/roboto-v20-latin-300.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/roboto-v20-latin-500.woff2" as="font" type="font/woff2" crossorigin/><link rel="preload" href="/crete-round-v9-latin-regular.woff2" as="font" type="font/woff2" crossorigin/>
</head>
<body>
<div id="application"><main class="light bgm1 cm3"><header class="x12 pftl bgm1 bs2"><div class="x xsb yy p5y"><div class="sm-x12 sm-xsb sm-p4x yy"><a title="Nullstack" href="/"><svg xmlns="http://www.w3.org/2000/svg" height="30" viewBox="0 0 511.5039 113.7368"><title> Nullstack <!--#--></title><path d="M13.2736,39.964H28.7009v9.8922a20.3919,20.3919,0,0,1,7.743-8.479,21.2792,21.2792,0,0,1,11.2172-3.0031q7.36,0,11.3349,4.1218t3.9745,11.6588a48.9655,48.9655,0,0,1-1.06,8.8913l-8.3025,42.8665H36.3556L44.187,65.7546a31.2306,31.2306,0,0,0,.5888-5.5939q0-7.6542-6.3593-7.6547a10.7348,10.7348,0,0,0-8.4791,4.3278q-3.5922,4.328-5.0639,12.0415l-7.1248,37.0372H.4961Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M81.4691,107.62q-7.2426,0-11.2466-4.1807t-4.004-11.8943a46.3965,46.3965,0,0,1,1.001-8.6557L75.64,39.964H92.7746L85.0609,80.24a29.8175,29.8175,0,0,0-.5888,5.5938q0,7.6551,6.4771,7.6548A10.3547,10.3547,0,0,0,99.2811,89.19q3.4446-4.2978,4.9756-12.0709L111.44,39.964h17.1348l-12.7775,65.9485H100.37V96.138a18.7565,18.7565,0,0,1-7.4781,8.3908A21.4849,21.4849,0,0,1,81.4691,107.62Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M150.2958,113.7368q-11.4821,0-16.7815-3.3563t-5.2995-10.5989a43.049,43.049,0,0,1,1.1188-8.3613l11.9532-56.6451H123.2687l2.532-13.2486h35.2118L146.2918,92.4213q-.1767.825-.3238,1.7371a10.5763,10.5763,0,0,0-.1473,1.6781q0,4.6521,8.2436,4.6517h16.3694l-2.65,13.2486Z" transform="translate(-0.4961)" fill="#d22365"></path><path d="M181.897,92.21q-11.4822,0-16.7816-3.3563T159.816,78.255a43.0455,43.0455,0,0,1,1.1187-8.3613l11.9532-56.6451H154.87L157.4018,0h35.2118L177.8929,70.8947q-.1765.8248-.3238,1.737a10.5766,10.5766,0,0,0-.1472,1.6782q0,4.6519,8.2435,4.6517h16.3694l-2.65,13.2486Z" transform="translate(-0.4961)" fill="#d22365"></path><path d="M228.3106,107.62a72.47,72.47,0,0,1-23.6119-4.1218l3.003-15.0739q10.5988,6.7717,21.6688,6.7715,6.4176,0,10.0983-2.2965a7.1387,7.1387,0,0,0,3.68-6.3593,4.4873,4.4873,0,0,0-1.8253-3.8273q-2.3556-1.884-9.5979-3.9452l-5.1817-1.4132q-13.8969-3.8271-13.8963-16.9582a18.9819,18.9819,0,0,1,8.0375-16.0455q8.0374-5.976,22.4637-5.9766a60.6829,60.6829,0,0,1,10.1573.8538,63.0434,63.0434,0,0,1,10.5105,2.797L260.8727,56.981a33.7,33.7,0,0,0-19.3724-6.3q-5.9478,0-9.3623,2.09a6.2659,6.2659,0,0,0-3.4152,5.5056,5.102,5.102,0,0,0,2.2375,4.2984q2.4731,1.7082,9.6568,3.7685l4.3573,1.2365q7.4775,2.12,10.9816,6.271t3.5035,10.805q0,10.7172-8.2436,16.84T228.3106,107.62Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M297.9546,106.2069q-11.3055,0-16.6932-3.3857t-5.3878-10.57a47.7847,47.7847,0,0,1,1.06-8.3613l5.9472-30.6778H265.9813l2.532-13.2486h16.8993l3.5918-18.7247h17.2527L302.6063,39.964h22.5521l-2.532,13.2486h-22.552l-6.1827,31.6788A20.2915,20.2915,0,0,0,293.48,88.13a3.9534,3.9534,0,0,0,1.9431,3.68q1.9433,1.1482,6.2416,1.1482h13.2486l-2.532,13.2486Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M338.2138,107.62q-9.4224,0-14.6029-5.1228-5.1828-5.1228-5.1816-14.25,0-12.2469,9.3034-18.99t26.2617-6.7421h11.3643l.4711-2.8852a3.6427,3.6427,0,0,1,.1177-.7066v-1.001A5.6271,5.6271,0,0,0,362.974,52.8q-2.9748-1.7666-8.5086-1.7665a41.5275,41.5275,0,0,0-10.8933,1.59,85.9338,85.9338,0,0,0-13.3074,5.0639l2.7675-14.7206a74.3941,74.3941,0,0,1,24.6129-4.5929q12.07,0,18.6363,4.6518,6.5643,4.652,6.5655,13.72a36.323,36.323,0,0,1-.4711,5.5939q-.4716,3.003-1.1188,5.9471l-7.2425,37.626H358.47v-7.36A26.3115,26.3115,0,0,1,338.2138,107.62Zm7.1837-11.8354q6.476,0,11.2466-5.6822t6.3-15.3978h-6.6537q-19.9029,0-19.9023,12.13a8.3352,8.3352,0,0,0,9.009,8.95Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M415.1828,107.62q-13.72,0-21.1683-7.4192t-7.4486-21.4333a42.63,42.63,0,0,1,5.005-20.8444,36.7663,36.7663,0,0,1,13.9257-14.338,40.3978,40.3978,0,0,1,20.7562-5.2111A39.0215,39.0215,0,0,1,445.8607,43.32l-3.1208,15.78a22.7112,22.7112,0,0,0-16.075-6.7126,21.2393,21.2393,0,0,0-11.8059,3.2974A22.52,22.52,0,0,0,406.88,64.783a29.416,29.416,0,0,0-2.8853,13.278q0,8.0083,3.4741,11.7765T417.95,93.606q8.8324,0,19.3724-6.1238l-3.2974,16.2516A45.998,45.998,0,0,1,415.1828,107.62Z" transform="translate(-0.4961)" fill="#2d3748"></path><path d="M458.1224,14.2911H475.375l-8.95,46.0463L490.2134,39.964H512L482.2643,64.5769l18.43,41.3356H482.382L469.31,75.058l-6.83,5.6527-4.8284,25.2018H440.3987Z" transform="translate(-0.4961)" fill="#2d3748"></path></svg></a><span class="yy md+off"><svg height="20" class="cm3" viewBox="0 0 512 512"><!----><!----><rect x="10" y="10" width="492" height="90.4043" rx="17.383" stroke-width="20" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" fill="none"></rect><rect x="10" y="411.5957" width="492" height="90.4043" rx="17.383" stroke-width="20" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" fill="none"></rect><rect x="10" y="210.7979" width="492" height="90.4043" rx="17.383" stroke-width="20" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" fill="none"></rect></svg></span></div><nav class="menu-links yy sm-p4 sm-off"><a href="/documentation" class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Documentation<!--#--> <!--#--></a><a href="/components" class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Components<!--#--> <!--#--></a><a href="/contributors" class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Contributors<!--#--> <!--#--></a><a href="https://github.com/nullstack/nullstack" target="_blank" rel="noopener" class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Source<!--#--> <!--#--></a><a href="/pt-br" class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Português<!--#--> <!--#--></a><button class="sm-x12 sm-bcm2b p2 fs4 ci1:h yy"> <!--#-->Night Mode<!--#--> <!--#--></button></nav><div class="sm-x12 sm-p4x sm-off"><a href="/getting-started" class="xx sm-x12 bci1 bgi1 bgm1:h cm1 ci1:h p4x p2y">Get Started<!--#--></a></div></div></header><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><!----><section class="x sm-p4x sm-p10y md+p20y"><h1 class="x12 sm-fs6 md+fs8 m6b"> <!--#-->Server Functions<!--#--> <!--#--></h1><article><p>Server functions are specialized microservices that at transpile time are converted into API entry points.</p>
<p>To flag a function as a server function, you must declare it as <code>static async</code>.</p>
<p>Being a static function means it has no access to the instance scope.</p>
<p>However, instead of calling the static version from the <em>class</em>, you must invoke it as an <em>instance</em> function.</p>
<p>Server functions can be called anytime in your code and are not limited to <a href="/server-side-rendering">prerender</a> steps.</p>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Component</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
context<span class="token punctuation">.</span>count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">async</span> <span class="token function">handleClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Component<span class="token punctuation">;</span>
</code></pre>
<blockquote>
<p>✨ Learn more about the <a href="/context">server context</a>.</p>
</blockquote>
<h2 id="client-behavior"><a href="#client-behavior">Client behavior</a></h2><p>When you call a server function from the client, the arguments will be serialized as JSON.</p>
<p>The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.</p>
<p>The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.</p>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Component</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">increment</span><span class="token punctuation">(</span><span class="token parameter">context</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
context<span class="token punctuation">.</span>count<span class="token operator">++</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> context<span class="token punctuation">.</span>count<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">async</span> <span class="token function">handleClick</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>count <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">increment</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Component<span class="token punctuation">;</span>
</code></pre>
<h2 id="server-behavior"><a href="#server-behavior">Server behavior</a></h2><p>Server functions will be used as local functions, simply aliasing the <em>instance</em> call to the <em>class</em> and merging the arguments with the server context.</p>
<h2 id="date-convenience"><a href="#date-convenience">Date Convenience</a></h2><p>Dates are serialized as UTC in JSON and deserialized back to <code>Date</code> objects.</p>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Component</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token keyword">async</span> <span class="token function">initiate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> date <span class="token operator">=</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> verified <span class="token operator">=</span> <span class="token keyword">this</span><span class="token punctuation">.</span><span class="token function">verifyDay</span><span class="token punctuation">(</span><span class="token punctuation">{</span>date<span class="token punctuation">}</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">verifyDay</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>date<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">return</span> date<span class="token punctuation">.</span><span class="token function">getDay</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">===</span> <span class="token keyword">new</span> <span class="token class-name">Date</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">getDay</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Component<span class="token punctuation">;</span>
</code></pre>
<h2 id="fetch-convenience"><a href="#fetch-convenience">Fetch Convenience</a></h2><p><code>fetch</code> is available in both server and client functions for the sake of isomorphy.</p>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Component</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token comment">// ...</span>
<span class="token keyword">async</span> <span class="token function">initiate</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> url <span class="token operator">=</span> <span class="token string">'https://api.github.com/repos/nullstack/nullstack/issues'</span><span class="token punctuation">;</span>
<span class="token keyword">const</span> response <span class="token operator">=</span> <span class="token keyword">await</span> <span class="token function">fetch</span><span class="token punctuation">(</span>url<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">this</span><span class="token punctuation">.</span>issues <span class="token operator">=</span> <span class="token keyword">await</span> response<span class="token punctuation">.</span><span class="token function">json</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Component<span class="token punctuation">;</span>
</code></pre>
<h2 id="server-only-imports"><a href="#server-only-imports">Server only imports</a></h2><p>Imported dependencies that are only used inside server functions will be excluded from the client bundle.</p>
<p>This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.</p>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>readFileSync<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'fs'</span><span class="token punctuation">;</span>
<span class="token keyword">import</span> <span class="token punctuation">{</span>Remarkable<span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'remarkable'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Application</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">getTasks</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">const</span> readme <span class="token operator">=</span> <span class="token function">readFileSync</span><span class="token punctuation">(</span><span class="token string">'README.md'</span><span class="token punctuation">,</span> <span class="token string">'utf-8'</span><span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> <span class="token keyword">new</span> <span class="token class-name">Remarkable</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">render</span><span class="token punctuation">(</span>readme<span class="token punctuation">)</span><span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Application<span class="token punctuation">;</span>
</code></pre>
<h2 id="security"><a href="#security">Security</a></h2><p>Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.</p>
<blockquote>
<p>🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.</p>
</blockquote>
<pre><code class="language-jsx"><span class="token keyword">import</span> Nullstack <span class="token keyword">from</span> <span class="token string">'nullstack'</span><span class="token punctuation">;</span>
<span class="token keyword">class</span> <span class="token class-name">Component</span> <span class="token keyword">extends</span> <span class="token class-name">Nullstack</span> <span class="token punctuation">{</span>
<span class="token keyword">static</span> <span class="token keyword">async</span> <span class="token function">getCount</span><span class="token punctuation">(</span><span class="token parameter"><span class="token punctuation">{</span>request<span class="token punctuation">,</span> count<span class="token punctuation">}</span></span><span class="token punctuation">)</span> <span class="token punctuation">{</span>
<span class="token keyword">if</span><span class="token punctuation">(</span><span class="token operator">!</span>request<span class="token punctuation">.</span>session<span class="token punctuation">.</span>user<span class="token punctuation">)</span> <span class="token keyword">return</span> <span class="token number">0</span><span class="token punctuation">;</span>
<span class="token keyword">return</span> count<span class="token punctuation">;</span>
<span class="token punctuation">}</span>
<span class="token comment">// ...</span>
<span class="token punctuation">}</span>
<span class="token keyword">export</span> <span class="token keyword">default</span> Component<span class="token punctuation">;</span>
</code></pre>
<blockquote>
<p>💡 Server functions are not exposed to the client.</p>
</blockquote>
<blockquote>
<p>✨ Learn more about the <a href="/njs-file-extension">NJS file extension</a>.</p>
</blockquote>
<h2 id="reserved-words"><a href="#reserved-words">Reserved words</a></h2><p>Server function names cannot collide with instance method names from the current class or its parent classes.</p>
<p>The following words cannot be used in server functions:</p>
<ul>
<li><code>prepare</code></li>
<li><code>initiate</code></li>
<li><code>hydrate</code></li>
<li><code>update</code></li>
<li><code>terminate</code></li>
</ul>
<p>Server functions named <code>start</code> will not generate an API endpoint and can only be called by other server functions.</p>
<h2 id="caveats"><a href="#caveats">Caveats</a></h2><p>Automatically generated API endpoints are not meant to be used by 3rd-party apps.</p>
<p>The URL and implementation may change between versions of Nullstack.</p>
<blockquote>
<p>✨ If you want to build an API, learn more about <a href="/server-request-and-response">how to create an API with Nullstack</a>.</p>
</blockquote>
<h2 id="next-step"><a href="#next-step">Next step</a></h2><p>⚔ Learn about the <a href="/context">context</a>.</p>
</article></section><!-- --><!-- --><!----><footer class="xx m20t"><div class="x xr md+bcm2t yy md+p10y prtl"><a href="/waifu"><img src="/nullachan.png" alt="Nulla-Chan" title="Nulla-Chan: Nullstack's official waifu" class="pabl sm-p2l" height="160" loading="lazy"/></a><nav class="xr sm-x4 yy"><a href="https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww" rel="noopener" target="_blank" class="sm-xr sm-m1y sm-x12 md+bci1 sm-bcm2t sm-p4t ci1 md+cm1:h md+bgi1:h p4x p2y md+m2x">YouTube<!--#--></a><a href="https://twitter.com/nullstackapp" rel="noopener" target="_blank" class="sm-xr sm-m1y sm-x12 md+bci1 sm-bcm2t sm-p4t ci1 md+cm1:h md+bgi1:h p4x p2y md+m2x">Twitter<!--#--></a><a href="https://github.com/nullstack" rel="noopener" target="_blank" class="sm-xr sm-m1y sm-x12 md+bci1 sm-bcm2t sm-p4t ci1 md+cm1:h md+bgi1:h p4x p2y md+m2x">GitHub<!--#--></a></nav></div></footer></main></div>
<script async>
window.page = {"image":"/image-1200x630.png","status":200,"title":"Server Functions - Nullstack","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"};
window.instances = {"application":{},"n-0-0-0":{"expanded":false,"locale":"en-US","i18n":{"home":{"title":"Nullstack","href":"/"},"links":[{"title":"Documentation","href":"/documentation"},{"title":"Components","href":"/components"},{"title":"Contributors","href":"/contributors"},{"title":"Source","href":"https://github.com/nullstack/nullstack","target":"_blank"},{"title":"Português","href":"/pt-br"}],"action":{"title":"Get Started","href":"/getting-started"},"mode":{"dark":"Night Mode","light":"Day Mode"}}},"n-0-0-0-0-0-0-1-0":{},"n-0-0-12":{"title":"Server Functions","html":"<p>Server functions are specialized microservices that at transpile time are converted into API entry points.</p>\n<p>To flag a function as a server function, you must declare it as <code>static async</code>.</p>\n<p>Being a static function means it has no access to the instance scope.</p>\n<p>However, instead of calling the static version from the <em>class</em>, you must invoke it as an <em>instance</em> function.</p>\n<p>Server functions can be called anytime in your code and are not limited to <a href=\"/server-side-rendering\">prerender</a> steps.</p>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token keyword\">static</span> <span class=\"token keyword\">async</span> <span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n context<span class=\"token punctuation\">.</span>count<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token keyword\">async</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">await</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Component<span class=\"token punctuation\">;</span>\n</code></pre>\n<blockquote>\n<p>✨ Learn more about the <a href=\"/context\">server context</a>.</p>\n</blockquote>\n<h2 id=\"client-behavior\"><a href=\"#client-behavior\">Client behavior</a></h2><p>When you call a server function from the client, the arguments will be serialized as JSON.</p>\n<p>The arguments will be posted against the automatically generated API and merged with the server context when it reaches the server.</p>\n<p>The return value of the server function will be serialized back to the client and can be seamlessly used as if it were a local function.</p>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token keyword\">static</span> <span class=\"token keyword\">async</span> <span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token parameter\">context</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n context<span class=\"token punctuation\">.</span>count<span class=\"token operator\">++</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> context<span class=\"token punctuation\">.</span>count<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token keyword\">async</span> <span class=\"token function\">handleClick</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>count <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">increment</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Component<span class=\"token punctuation\">;</span>\n</code></pre>\n<h2 id=\"server-behavior\"><a href=\"#server-behavior\">Server behavior</a></h2><p>Server functions will be used as local functions, simply aliasing the <em>instance</em> call to the <em>class</em> and merging the arguments with the server context.</p>\n<h2 id=\"date-convenience\"><a href=\"#date-convenience\">Date Convenience</a></h2><p>Dates are serialized as UTC in JSON and deserialized back to <code>Date</code> objects.</p>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token keyword\">async</span> <span class=\"token function\">initiate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">const</span> date <span class=\"token operator\">=</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">const</span> verified <span class=\"token operator\">=</span> <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span><span class=\"token function\">verifyDay</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">{</span>date<span class=\"token punctuation\">}</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token keyword\">static</span> <span class=\"token keyword\">async</span> <span class=\"token function\">verifyDay</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span>date<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">return</span> date<span class=\"token punctuation\">.</span><span class=\"token function\">getDay</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token operator\">===</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Date</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">getDay</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Component<span class=\"token punctuation\">;</span>\n</code></pre>\n<h2 id=\"fetch-convenience\"><a href=\"#fetch-convenience\">Fetch Convenience</a></h2><p><code>fetch</code> is available in both server and client functions for the sake of isomorphy.</p>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token comment\">// ...</span>\n\n <span class=\"token keyword\">async</span> <span class=\"token function\">initiate</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">const</span> url <span class=\"token operator\">=</span> <span class=\"token string\">'https://api.github.com/repos/nullstack/nullstack/issues'</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">const</span> response <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> <span class=\"token function\">fetch</span><span class=\"token punctuation\">(</span>url<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">this</span><span class=\"token punctuation\">.</span>issues <span class=\"token operator\">=</span> <span class=\"token keyword\">await</span> response<span class=\"token punctuation\">.</span><span class=\"token function\">json</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Component<span class=\"token punctuation\">;</span>\n</code></pre>\n<h2 id=\"server-only-imports\"><a href=\"#server-only-imports\">Server only imports</a></h2><p>Imported dependencies that are only used inside server functions will be excluded from the client bundle.</p>\n<p>This is useful for both accessing node.js exclusive modules and reducing the client bundle size by preprocessing data like markdown without having to expose the dependency to the end-user.</p>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span>readFileSync<span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'fs'</span><span class=\"token punctuation\">;</span>\n<span class=\"token keyword\">import</span> <span class=\"token punctuation\">{</span>Remarkable<span class=\"token punctuation\">}</span> <span class=\"token keyword\">from</span> <span class=\"token string\">'remarkable'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Application</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token keyword\">static</span> <span class=\"token keyword\">async</span> <span class=\"token function\">getTasks</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">const</span> readme <span class=\"token operator\">=</span> <span class=\"token function\">readFileSync</span><span class=\"token punctuation\">(</span><span class=\"token string\">'README.md'</span><span class=\"token punctuation\">,</span> <span class=\"token string\">'utf-8'</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> <span class=\"token keyword\">new</span> <span class=\"token class-name\">Remarkable</span><span class=\"token punctuation\">(</span><span class=\"token punctuation\">)</span><span class=\"token punctuation\">.</span><span class=\"token function\">render</span><span class=\"token punctuation\">(</span>readme<span class=\"token punctuation\">)</span><span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Application<span class=\"token punctuation\">;</span>\n</code></pre>\n<h2 id=\"security\"><a href=\"#security\">Security</a></h2><p>Keep in mind that every server function is similar to an Express route in API and must be coded without depending on view logic for security.</p>\n<blockquote>\n<p>🔒 Server functions with the name starting with "start" (and optionally followed by an uppercase letter) do not generate an API endpoint to avoid malicious context flooding.</p>\n</blockquote>\n<pre><code class=\"language-jsx\"><span class=\"token keyword\">import</span> Nullstack <span class=\"token keyword\">from</span> <span class=\"token string\">'nullstack'</span><span class=\"token punctuation\">;</span>\n\n<span class=\"token keyword\">class</span> <span class=\"token class-name\">Component</span> <span class=\"token keyword\">extends</span> <span class=\"token class-name\">Nullstack</span> <span class=\"token punctuation\">{</span>\n\n <span class=\"token keyword\">static</span> <span class=\"token keyword\">async</span> <span class=\"token function\">getCount</span><span class=\"token punctuation\">(</span><span class=\"token parameter\"><span class=\"token punctuation\">{</span>request<span class=\"token punctuation\">,</span> count<span class=\"token punctuation\">}</span></span><span class=\"token punctuation\">)</span> <span class=\"token punctuation\">{</span>\n <span class=\"token keyword\">if</span><span class=\"token punctuation\">(</span><span class=\"token operator\">!</span>request<span class=\"token punctuation\">.</span>session<span class=\"token punctuation\">.</span>user<span class=\"token punctuation\">)</span> <span class=\"token keyword\">return</span> <span class=\"token number\">0</span><span class=\"token punctuation\">;</span>\n <span class=\"token keyword\">return</span> count<span class=\"token punctuation\">;</span>\n <span class=\"token punctuation\">}</span>\n\n <span class=\"token comment\">// ...</span>\n\n<span class=\"token punctuation\">}</span>\n\n<span class=\"token keyword\">export</span> <span class=\"token keyword\">default</span> Component<span class=\"token punctuation\">;</span>\n</code></pre>\n<blockquote>\n<p>💡 Server functions are not exposed to the client.</p>\n</blockquote>\n<blockquote>\n<p>✨ Learn more about the <a href=\"/njs-file-extension\">NJS file extension</a>.</p>\n</blockquote>\n<h2 id=\"reserved-words\"><a href=\"#reserved-words\">Reserved words</a></h2><p>Server function names cannot collide with instance method names from the current class or its parent classes.</p>\n<p>The following words cannot be used in server functions:</p>\n<ul>\n<li><code>prepare</code></li>\n<li><code>initiate</code></li>\n<li><code>hydrate</code></li>\n<li><code>update</code></li>\n<li><code>terminate</code></li>\n</ul>\n<p>Server functions named <code>start</code> will not generate an API endpoint and can only be called by other server functions.</p>\n<h2 id=\"caveats\"><a href=\"#caveats\">Caveats</a></h2><p>Automatically generated API endpoints are not meant to be used by 3rd-party apps.</p>\n<p>The URL and implementation may change between versions of Nullstack.</p>\n<blockquote>\n<p>✨ If you want to build an API, learn more about <a href=\"/server-request-and-response\">how to create an API with Nullstack</a>.</p>\n</blockquote>\n<h2 id=\"next-step\"><a href=\"#next-step\">Next step</a></h2><p>⚔ Learn about the <a href=\"/context\">context</a>.</p>\n","description":"Server functions are specialized microservices that at transpile time are converted into API entry points"},"n-0-0-13":{},"n-0-0-15":{},"n-0-0-16":{"locale":"en-US","i18n":{"nullachan":{"alt":"Nulla-Chan","title":"Nulla-Chan: Nullstack's official waifu"},"links":[{"title":"YouTube","href":"https://www.youtube.com/channel/UCUNPaxoppH3lu6JTrUX78Ww"},{"title":"Twitter","href":"https://twitter.com/nullstackapp"},{"title":"GitHub","href":"https://github.com/nullstack"}]}}};
window.environment = {"client":false,"server":true,"development":false,"production":true,"static":true,"key":"9cdb5778f42a90a83e1427c9316c97d3"};
window.settings = {};
window.worker = {"enabled":true,"fetching":false,"preload":["/404","/about","/application-startup","/context-data","/context-environment","/context-page","/context-project","/context-secrets","/context-settings","/context","/full-stack-lifecycle","/getting-started","/how-to-deploy-a-nullstack-application","/how-to-use-facebook-pixel-with-nullstack","/how-to-use-google-analytics-with-nullstack","/how-to-use-mongodb-with-nullstack","/instance-self","/njs-file-extension","/renderable-components","/routes-and-params","/server-functions","/server-request-and-response","/server-side-rendering","/service-worker","/stateful-components","/static-site-generation","/styles","/two-way-bindings","/documentation","/components","/about","/contributors","/roboto-v20-latin-300.woff2","/roboto-v20-latin-500.woff2","/crete-round-v9-latin-regular.woff2","/nullachan.png"],"headers":{},"queues":{},"online":true,"responsive":true};
window.params = {"slug":"server-functions"};
window.project = {"type":"website","display":"standalone","orientation":"portrait","scope":"/","root":"/","favicon":"/favicon-96x96.png","icons":{"72":"/icon-72x72.png","96":"/icon-96x96.png","128":"/icon-128x128.png","144":"/icon-144x144.png","152":"/icon-152x152.png","180":"/icon-180x180.png","192":"/icon-192x192.png","384":"/icon-384x384.png","512":"/icon-512x512.png"},"disallow":[],"sitemap":true,"cdn":"","protocol":"https","name":"Nullstack","domain":"nullstack.app","color":"#d22365","backgroundColor":"#2d3748"};
window.context = {"mode":"light","oppositeMode":"dark"};
document.addEventListener('DOMContentLoaded', () => {
const script = window.document.createElement('script');
script.src = '/client-9cdb5778f42a90a83e1427c9316c97d3.js';
script.integrity = 'sha512-0uTc8acdgpOj0RrKj5FnYwXRpLXfqL4nWm0UipWJa7V9rarS5OyTT9S0p5UfMcWCCauR+1Jr68bzB5jKk/CKEA==';
script.crossOrigin = 'anonymous';
document.body.append(script);
});
</script>
</body>
</html>