sendscript 2.3.1 → 2.3.3
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/.prettierrc +6 -0
- package/CHANGELOG.md +16 -0
- package/CONTRIBUTING.md +28 -4
- package/README.md +203 -128
- package/README.mz +82 -87
- package/example/client.socket.io.mjs +2 -4
- package/example/math.mjs +1 -1
- package/example/typescript/docs/functions/add.md +1 -1
- package/example/typescript/docs/functions/square.md +1 -1
- package/package.json +1 -1
- package/parse.mjs +51 -29
- package/references.mjs +57 -6
- package/stringify.mjs +45 -15
package/.prettierrc
ADDED
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,24 @@ All notable changes to this project will be documented in this file. Dates are d
|
|
|
4
4
|
|
|
5
5
|
Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
|
|
6
6
|
|
|
7
|
+
#### [v2.3.3](https://github.com/bas080/sendscript/compare/v2.3.2...v2.3.3)
|
|
8
|
+
|
|
9
|
+
- Add JSDoc to relevant function for docs [`d1d3709`](https://github.com/bas080/sendscript/commit/d1d3709088a51b71651170ef642b013eedc9ca3a)
|
|
10
|
+
- Remove tests section from README [`5da7bb3`](https://github.com/bas080/sendscript/commit/5da7bb3f3b1dc8078683e076fe2b520bc6d28896)
|
|
11
|
+
- Add generated from JSDoc reference section [`08eb266`](https://github.com/bas080/sendscript/commit/08eb266b06d8998e6849dbc5c9738fbe782ada18)
|
|
12
|
+
|
|
13
|
+
#### [v2.3.2](https://github.com/bas080/sendscript/compare/v2.3.1...v2.3.2)
|
|
14
|
+
|
|
15
|
+
> 14 April 2026
|
|
16
|
+
|
|
17
|
+
- Format the README.mz file [`df43dbb`](https://github.com/bas080/sendscript/commit/df43dbb8b790cfc612536f49571f9fe4aad03837)
|
|
18
|
+
- Move some commands from README to CONTRIBUTING [`45659c5`](https://github.com/bas080/sendscript/commit/45659c51354ac3bbe3bed5ef3826785d8a1a4a32)
|
|
19
|
+
- Add format markdown check in contributing md [`e68d4d6`](https://github.com/bas080/sendscript/commit/e68d4d6aea26a7a54c2f933ad98a8e363d7f3357)
|
|
20
|
+
|
|
7
21
|
#### [v2.3.1](https://github.com/bas080/sendscript/compare/v2.3.0...v2.3.1)
|
|
8
22
|
|
|
23
|
+
> 14 April 2026
|
|
24
|
+
|
|
9
25
|
- Update typedoc dev dep to 0.28.19 [`69e8cc4`](https://github.com/bas080/sendscript/commit/69e8cc48251af650c02faf3214ff0f9c2b61dbc9)
|
|
10
26
|
|
|
11
27
|
#### [v2.3.0](https://github.com/bas080/sendscript/compare/v2.2.0...v2.3.0)
|
package/CONTRIBUTING.md
CHANGED
|
@@ -1,16 +1,38 @@
|
|
|
1
1
|
# Contributing
|
|
2
2
|
|
|
3
|
-
|
|
4
3
|
For the README.mz examples to work we need sendscript to be linked.
|
|
5
4
|
|
|
6
5
|
```bash bash > /dev/null
|
|
7
6
|
set -e
|
|
8
7
|
|
|
8
|
+
npm ci
|
|
9
9
|
npm link
|
|
10
10
|
npm link sendscript
|
|
11
11
|
cd ./example
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
Check if packages are up to date on release.
|
|
15
|
+
|
|
16
|
+
```bash bash
|
|
17
|
+
npm outdated && echo 'No outdated packages found'
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Check if no vulnerable dependencies
|
|
21
|
+
|
|
22
|
+
```bash bash
|
|
23
|
+
npm audit
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Check if code follows standard formatting.
|
|
27
|
+
|
|
28
|
+
```bash bash
|
|
29
|
+
npx standard
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
Check if markdown is correctly formatted.
|
|
33
|
+
|
|
34
|
+
```bash bash
|
|
35
|
+
npx prettier --check --parser markdown ./README.mz ./CONTRIBUTING.md
|
|
14
36
|
```
|
|
15
37
|
|
|
16
38
|
Generate the README from the mz file.
|
|
@@ -18,7 +40,9 @@ Generate the README from the mz file.
|
|
|
18
40
|
```bash bash
|
|
19
41
|
markatzea ./README.mz | tee ./README.md
|
|
20
42
|
|
|
21
|
-
npx markdown-toc
|
|
43
|
+
npx documentation readme references.mjs parse.mjs stringify.mjs -s Reference --github --a public --markdown-toc false
|
|
44
|
+
|
|
45
|
+
npx markdown-toc --maxdepth 3 -i README.md
|
|
22
46
|
|
|
23
47
|
git add *.md ./example
|
|
24
48
|
```
|
package/README.md
CHANGED
|
@@ -2,14 +2,22 @@
|
|
|
2
2
|
|
|
3
3
|
Write JS code that you can run on servers, browsers or other clients.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/sendscript)
|
|
6
6
|
[](#tests)
|
|
7
7
|
[](https://standardjs.com)
|
|
8
|
-
[](./LICENSE.txt)
|
|
9
9
|
|
|
10
10
|
<!-- toc -->
|
|
11
11
|
|
|
12
12
|
- [Introduction](#introduction)
|
|
13
|
+
- [Reference](#reference)
|
|
14
|
+
* [defaultLeafDeserializer](#defaultleafdeserializer)
|
|
15
|
+
* [Parse](#parse)
|
|
16
|
+
* [parse](#parse)
|
|
17
|
+
* [References](#references)
|
|
18
|
+
* [strictStringify](#strictstringify)
|
|
19
|
+
* [Stringify](#stringify)
|
|
20
|
+
* [stringify](#stringify)
|
|
13
21
|
- [Socket example](#socket-example)
|
|
14
22
|
* [Module](#module)
|
|
15
23
|
* [Server](#server)
|
|
@@ -25,34 +33,33 @@ Write JS code that you can run on servers, browsers or other clients.
|
|
|
25
33
|
* [Validating structured input](#validating-structured-input)
|
|
26
34
|
- [Leaf Serializer](#leaf-serializer)
|
|
27
35
|
* [Example with superjson](#example-with-superjson)
|
|
28
|
-
- [Tests](#tests)
|
|
29
|
-
- [Formatting](#formatting)
|
|
30
36
|
- [Changelog](#changelog)
|
|
31
|
-
- [Dependencies](#dependencies)
|
|
32
37
|
- [License](#license)
|
|
33
|
-
- [
|
|
38
|
+
- [Issues](#issues)
|
|
34
39
|
|
|
35
40
|
<!-- tocstop -->
|
|
36
41
|
|
|
37
42
|
## Introduction
|
|
38
43
|
|
|
39
|
-
There has been interest in improving APIs by allowing aggregations in a
|
|
40
|
-
|
|
44
|
+
There has been interest in improving APIs by allowing aggregations in a single
|
|
45
|
+
request. Examples include
|
|
41
46
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
47
|
+
* [JSON-RPC](https://json-rpc.dev/) which allows you to do multiple requests but
|
|
48
|
+
it does not allow you to compose the return value of one endpoint to be the
|
|
49
|
+
input/arguments of another.
|
|
45
50
|
|
|
46
|
-
|
|
47
|
-
|
|
51
|
+
* [GraphQL](https://graphql.org/) is very cool but also introduces a new
|
|
52
|
+
languages and the tooling that is required to wield it.
|
|
48
53
|
|
|
49
|
-
What SendScript attempts is to allow for very expressive queries and mutations
|
|
50
|
-
that read and write like ordinary JS. That means that the
|
|
51
|
-
that are sent to the server from a client can also
|
|
52
|
-
|
|
53
|
-
using more advanced
|
|
54
|
+
What SendScript attempts is to allow for very expressive queries and mutations
|
|
55
|
+
to be performed that read and write like ordinary JS. That means that the
|
|
56
|
+
queries and complete programs that are sent to the server from a client can also
|
|
57
|
+
just run on the server as is. The only limitation being the serialization which
|
|
58
|
+
by default is limited by JSON and could be extended by using more advanced
|
|
59
|
+
(de)serialization libraries.
|
|
54
60
|
|
|
55
|
-
SendScript produces an intermediate JSON representation of the program. Let's
|
|
61
|
+
SendScript produces an intermediate JSON representation of the program. Let's
|
|
62
|
+
see what that looks like.
|
|
56
63
|
|
|
57
64
|
```js
|
|
58
65
|
import Stringify from 'sendscript/stringify.mjs'
|
|
@@ -63,6 +70,7 @@ const stringify = Stringify()
|
|
|
63
70
|
|
|
64
71
|
console.log(stringify(add(1,2)))
|
|
65
72
|
```
|
|
73
|
+
|
|
66
74
|
```json
|
|
67
75
|
["call",["ref","add"],[["leaf","1"],["leaf","2"]]]
|
|
68
76
|
```
|
|
@@ -84,6 +92,7 @@ const program = '["call",["ref","add"],[1,2]]'
|
|
|
84
92
|
|
|
85
93
|
console.log(parse(program))
|
|
86
94
|
```
|
|
95
|
+
|
|
87
96
|
```json
|
|
88
97
|
3
|
|
89
98
|
```
|
|
@@ -91,22 +100,113 @@ console.log(parse(program))
|
|
|
91
100
|
SendScript does more than a simple function call. It supports function
|
|
92
101
|
composition and even await.
|
|
93
102
|
|
|
94
|
-
This package is nothing more than the absolute core of sendscript. It
|
|
95
|
-
|
|
103
|
+
This package is nothing more than the absolute core of sendscript. It includes:
|
|
104
|
+
|
|
105
|
+
* The `references` function to create stubs to write the programs.
|
|
106
|
+
* `stringify` which takes the program and returns a JSON string.
|
|
107
|
+
* `parse` which takes the `stringify` JSON string and a real module and returns
|
|
108
|
+
the result.
|
|
109
|
+
|
|
110
|
+
The naming could use more love and there are many things to solve either in the
|
|
111
|
+
core or around it. Things like supporting more complex (de)serializers, errors
|
|
112
|
+
and maybe mixing client functions with sendscript programs. Contact me if I have
|
|
113
|
+
piqued your interest.
|
|
114
|
+
|
|
115
|
+
***
|
|
116
|
+
|
|
117
|
+
SendScript leaves it up to you to choose HTTP, web-sockets or any other method
|
|
118
|
+
of communication between servers and clients that best fits your needs.
|
|
119
|
+
|
|
120
|
+
## Reference
|
|
121
|
+
|
|
122
|
+
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
123
|
+
|
|
124
|
+
### defaultLeafDeserializer
|
|
125
|
+
|
|
126
|
+
Default deserializer for leaf nodes.
|
|
127
|
+
|
|
128
|
+
#### Parameters
|
|
129
|
+
|
|
130
|
+
* `text` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
131
|
+
|
|
132
|
+
Returns **any** 
|
|
133
|
+
|
|
134
|
+
### Parse
|
|
135
|
+
|
|
136
|
+
Creates a program parser for a given schema and environment.
|
|
137
|
+
|
|
138
|
+
The parser:
|
|
139
|
+
|
|
140
|
+
* resolves references into runtime functions
|
|
141
|
+
* deserializes leaf nodes
|
|
142
|
+
* collects and executes async awaits
|
|
143
|
+
* evaluates AST-like JSON programs
|
|
144
|
+
|
|
145
|
+
#### Parameters
|
|
146
|
+
|
|
147
|
+
* `schemaArg` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)])>** 
|
|
148
|
+
* `env` **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** runtime environment for refs
|
|
149
|
+
* `deserialize` (optional, default `defaultLeafDeserializer`)
|
|
150
|
+
|
|
151
|
+
### parse
|
|
152
|
+
|
|
153
|
+
Parses and executes a serialized program.
|
|
154
|
+
|
|
155
|
+
#### Parameters
|
|
156
|
+
|
|
157
|
+
* `program` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** JSON encoded program
|
|
158
|
+
|
|
159
|
+
Returns **(any | [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<any>)** 
|
|
160
|
+
|
|
161
|
+
### References
|
|
162
|
+
|
|
163
|
+
Builds a nested API structure from a schema definition.
|
|
164
|
+
|
|
165
|
+
Schema supports:
|
|
166
|
+
|
|
167
|
+
* string => leaf function node
|
|
168
|
+
* \[name, children] => namespace with nested schema
|
|
169
|
+
|
|
170
|
+
#### Parameters
|
|
171
|
+
|
|
172
|
+
* `schema` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)])>** 
|
|
173
|
+
* `parentPath` **[Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)>** (optional, default `[]`)
|
|
174
|
+
|
|
175
|
+
<!---->
|
|
176
|
+
|
|
177
|
+
* Throws **[Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)** If schema format is invalid
|
|
178
|
+
|
|
179
|
+
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Nested instrumented API object
|
|
180
|
+
|
|
181
|
+
### strictStringify
|
|
182
|
+
|
|
183
|
+
Default strict serializer for leaf values.
|
|
184
|
+
|
|
185
|
+
Rejects non-JSON-safe values.
|
|
186
|
+
|
|
187
|
+
#### Parameters
|
|
188
|
+
|
|
189
|
+
* `x` **any** 
|
|
190
|
+
|
|
191
|
+
Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
96
192
|
|
|
97
|
-
|
|
98
|
-
- `stringify` which takes the program and returns a JSON string.
|
|
99
|
-
- `parse` which takes the `stringify` JSON string and a real module and returns the result.
|
|
193
|
+
### Stringify
|
|
100
194
|
|
|
101
|
-
|
|
102
|
-
Things like supporting more complex (de)serializers, errors and maybe mixing client functions with
|
|
103
|
-
sendscript programs. Contact me if I have piqued your interest.
|
|
195
|
+
Creates a stringify function for SendScript AST structures.
|
|
104
196
|
|
|
105
|
-
|
|
197
|
+
#### Parameters
|
|
106
198
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
199
|
+
* `leafSerializer` (optional, default `strictStringify`)
|
|
200
|
+
|
|
201
|
+
### stringify
|
|
202
|
+
|
|
203
|
+
Serializes a program into a JSON string representation.
|
|
204
|
+
|
|
205
|
+
#### Parameters
|
|
206
|
+
|
|
207
|
+
* `program` **any** 
|
|
208
|
+
|
|
209
|
+
Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
110
210
|
|
|
111
211
|
## Socket example
|
|
112
212
|
|
|
@@ -120,7 +220,7 @@ We write a simple module.
|
|
|
120
220
|
// ./example/math.mjs
|
|
121
221
|
|
|
122
222
|
export const add = (a, b) => a + b
|
|
123
|
-
export const square = a => a * a
|
|
223
|
+
export const square = (a) => a * a
|
|
124
224
|
```
|
|
125
225
|
|
|
126
226
|
### Server
|
|
@@ -172,12 +272,10 @@ const stringify = Stringify()
|
|
|
172
272
|
const port = process.env.PORT || 3000
|
|
173
273
|
const client = socketClient(`http://localhost:${port}`)
|
|
174
274
|
|
|
175
|
-
const send = program => {
|
|
275
|
+
const send = (program) => {
|
|
176
276
|
return new Promise((resolve, reject) => {
|
|
177
277
|
client.emit('message', stringify(program), (error, result) => {
|
|
178
|
-
error
|
|
179
|
-
? reject(error)
|
|
180
|
-
: resolve(result)
|
|
278
|
+
error ? reject(error) : resolve(result)
|
|
181
279
|
})
|
|
182
280
|
})
|
|
183
281
|
}
|
|
@@ -207,15 +305,16 @@ node ./example/client.socket.io.mjs
|
|
|
207
305
|
|
|
208
306
|
pkill sendscript
|
|
209
307
|
```
|
|
210
|
-
|
|
211
|
-
Result: 100
|
|
212
|
-
```
|
|
308
|
+
|
|
309
|
+
Result: 100
|
|
213
310
|
|
|
214
311
|
## Repl
|
|
215
312
|
|
|
216
|
-
Sendscript ships with a barebones (no-dependencies) node-repl script. One can
|
|
313
|
+
Sendscript ships with a barebones (no-dependencies) node-repl script. One can
|
|
314
|
+
run it by simply typing `sendscript` in their console.
|
|
217
315
|
|
|
218
|
-
> Use the `DEBUG='*'` to enable all logs or `DEBUG='sendscript:*'` for
|
|
316
|
+
> Use the `DEBUG='*'` to enable all logs or `DEBUG='sendscript:*'` for
|
|
317
|
+
> printingonly sendscript logs.
|
|
219
318
|
|
|
220
319
|
## Promises
|
|
221
320
|
|
|
@@ -227,44 +326,51 @@ Supported since vs `v2.3`.
|
|
|
227
326
|
const getOrCreatePost = send(createPost(title).catch(createPost(title)))
|
|
228
327
|
```
|
|
229
328
|
|
|
230
|
-
You will likely need to define better helpers that makes it safer to handle
|
|
231
|
-
|
|
329
|
+
You will likely need to define better helpers that makes it safer to handle
|
|
330
|
+
rejections and work with promises. It is however sensible to have this basic
|
|
331
|
+
behavior for the sendscript DSL and parser.
|
|
232
332
|
|
|
233
333
|
### await
|
|
234
334
|
|
|
235
|
-
SendScript supports async/await seamlessly within a single request. This avoids
|
|
335
|
+
SendScript supports async/await seamlessly within a single request. This avoids
|
|
336
|
+
the performance pitfalls of waterfall-style messaging, which can be especially
|
|
337
|
+
slow on high-latency networks.
|
|
236
338
|
|
|
237
|
-
While it's possible to chain promises manually or use utility functions, native
|
|
339
|
+
While it's possible to chain promises manually or use utility functions, native
|
|
340
|
+
async/await support makes your code more readable, modern, and easier to reason
|
|
341
|
+
about — aligning SendScript with today’s JavaScript best practices.
|
|
238
342
|
|
|
239
343
|
```js
|
|
240
344
|
const userId = 'user-123'
|
|
241
345
|
const program = {
|
|
242
346
|
unread: await fetchUnreadMessages(userId),
|
|
243
347
|
emptyTrash: await emptyTrash(userId),
|
|
244
|
-
archived: await archiveMessages(selectMessages({ old: true }))
|
|
348
|
+
archived: await archiveMessages(selectMessages({ old: true })),
|
|
245
349
|
}
|
|
246
350
|
|
|
247
351
|
const result = await send(program)
|
|
248
352
|
```
|
|
249
353
|
|
|
250
|
-
This operation is done in a single round-trip. The result is an object with the
|
|
354
|
+
This operation is done in a single round-trip. The result is an object with the
|
|
355
|
+
defined properties and returned values.
|
|
251
356
|
|
|
252
357
|
## TypeScript
|
|
253
358
|
|
|
254
359
|
There is a good use-case to write a module in TypeScript.
|
|
255
360
|
|
|
256
|
-
1.
|
|
257
|
-
|
|
258
|
-
2.
|
|
259
|
-
|
|
260
|
-
3.
|
|
261
|
-
|
|
361
|
+
1. Obviously the module would have the benefits that TypeScript offers when
|
|
362
|
+
coding.
|
|
363
|
+
2. You can use tools like [typedoc][typedoc] to generate docs from your types to
|
|
364
|
+
share with consumers of your API.
|
|
365
|
+
3. You can use the types of the module to coerce your client to adopt the
|
|
366
|
+
module's type.
|
|
262
367
|
|
|
263
368
|
Let's say we have this module which we use on the server.
|
|
264
369
|
|
|
265
370
|
```bash
|
|
266
371
|
cat ./example/typescript/math.ts
|
|
267
372
|
```
|
|
373
|
+
|
|
268
374
|
```ts
|
|
269
375
|
export const add = (a: number, b: number) => a + b
|
|
270
376
|
export const square = (a: number) => a * a
|
|
@@ -275,6 +381,7 @@ We can then coerce the types of the instrumented stubs.
|
|
|
275
381
|
```bash
|
|
276
382
|
cat ./example/typescript/client.ts
|
|
277
383
|
```
|
|
384
|
+
|
|
278
385
|
```ts
|
|
279
386
|
import math from './math.client.ts'
|
|
280
387
|
import Stringify from 'sendscript/stringify.mjs'
|
|
@@ -300,15 +407,16 @@ npx typedoc --plugin typedoc-plugin-markdown --out ./example/typescript/docs ./e
|
|
|
300
407
|
|
|
301
408
|
You can see the docs [here](./example/typescript/docs/globals.md)
|
|
302
409
|
|
|
303
|
-
> [!NOTE]
|
|
304
|
-
>
|
|
305
|
-
>
|
|
306
|
-
> Values are subject to serialization and deserialization.
|
|
307
|
-
|
|
410
|
+
> \[!NOTE] Although type coercion on the client side can improve the development
|
|
411
|
+
> experience, it does not represent the actual type. Values are subject to
|
|
412
|
+
> serialization and deserialization.
|
|
308
413
|
|
|
309
414
|
## Schema and Nested Modules
|
|
310
415
|
|
|
311
|
-
Sendscript allows you to define your API as a **nested object of functions**,
|
|
416
|
+
Sendscript allows you to define your API as a **nested object of functions**,
|
|
417
|
+
making it easy to organize your DSL into modules and submodules. Each function
|
|
418
|
+
is instrumented so that when serialized, it produces a structured reference that
|
|
419
|
+
can be safely sent and executed elsewhere.
|
|
312
420
|
|
|
313
421
|
### Defining a Nested Module
|
|
314
422
|
|
|
@@ -340,17 +448,13 @@ Functions are referenced via their **path in the module tree**:
|
|
|
340
448
|
```js
|
|
341
449
|
const { math, vector } = references(schema)
|
|
342
450
|
|
|
343
|
-
math.add(
|
|
344
|
-
1,
|
|
345
|
-
vector.length(
|
|
346
|
-
vector.multiply([1,2], 3)
|
|
347
|
-
)
|
|
348
|
-
)
|
|
451
|
+
math.add(1, vector.length(vector.multiply([1, 2], 3)))
|
|
349
452
|
```
|
|
350
453
|
|
|
351
454
|
## Validation (using Zod)
|
|
352
455
|
|
|
353
|
-
SendScript focuses on program serialization and execution. For runtime input
|
|
456
|
+
SendScript focuses on program serialization and execution. For runtime input
|
|
457
|
+
validation, you can use [Zod](https://zod.dev).
|
|
354
458
|
|
|
355
459
|
### Validating structured input
|
|
356
460
|
|
|
@@ -358,7 +462,7 @@ SendScript focuses on program serialization and execution. For runtime input val
|
|
|
358
462
|
const userSchema = z.object({
|
|
359
463
|
id: z.string().uuid(),
|
|
360
464
|
name: z.string(),
|
|
361
|
-
roles: z.array(z.string())
|
|
465
|
+
roles: z.array(z.string()),
|
|
362
466
|
})
|
|
363
467
|
|
|
364
468
|
export function createUser(user) {
|
|
@@ -370,19 +474,25 @@ export function createUser(user) {
|
|
|
370
474
|
|
|
371
475
|
**Benefits**:
|
|
372
476
|
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
477
|
+
* Ensures arguments match expected types and shapes.
|
|
478
|
+
* Throws structured errors that can be propagated to clients.
|
|
479
|
+
* Works with TypeScript for automatic type inference.
|
|
376
480
|
|
|
377
481
|
## Leaf Serializer
|
|
378
482
|
|
|
379
|
-
By default, SendScript uses JSON for serialization, which limits support to
|
|
483
|
+
By default, SendScript uses JSON for serialization, which limits support to
|
|
484
|
+
primitives and plain objects/arrays. To support richer JavaScript types like
|
|
485
|
+
`Date`, `RegExp`, `BigInt`, `Map`, `Set`, and `undefined`, you can provide
|
|
486
|
+
custom serialization functions.
|
|
380
487
|
|
|
381
|
-
The `stringify` function accepts an optional `leafSerializer` parameter, and
|
|
488
|
+
The `stringify` function accepts an optional `leafSerializer` parameter, and
|
|
489
|
+
`parse` accepts an optional `leafDeserializer` parameter. These functions
|
|
490
|
+
control how non-SendScript values (leaves) are encoded and decoded.
|
|
382
491
|
|
|
383
492
|
### Example with superjson
|
|
384
493
|
|
|
385
|
-
Here's how to use [superjson](https://github.com/blitz-js/superjson) to support
|
|
494
|
+
Here's how to use [superjson](https://github.com/blitz-js/superjson) to support
|
|
495
|
+
extended types:
|
|
386
496
|
|
|
387
497
|
```js
|
|
388
498
|
import SuperJSON from 'superjson'
|
|
@@ -412,7 +522,10 @@ const program = {
|
|
|
412
522
|
pattern: /foo/gi,
|
|
413
523
|
count: BigInt('9007199254740992'),
|
|
414
524
|
items: new Set([1, 2, 3]),
|
|
415
|
-
mapping: new Map([
|
|
525
|
+
mapping: new Map([
|
|
526
|
+
['a', 1],
|
|
527
|
+
['b', 2],
|
|
528
|
+
]),
|
|
416
529
|
}
|
|
417
530
|
|
|
418
531
|
// Serialize with custom leaf serializer
|
|
@@ -422,8 +535,8 @@ const json = stringify(processData(program))
|
|
|
422
535
|
const env = {
|
|
423
536
|
processData: (data) => ({
|
|
424
537
|
success: true,
|
|
425
|
-
received: data
|
|
426
|
-
})
|
|
538
|
+
received: data,
|
|
539
|
+
}),
|
|
427
540
|
}
|
|
428
541
|
|
|
429
542
|
// Parse with custom leaf deserializer
|
|
@@ -432,41 +545,8 @@ const parse = Parse(schema, env, leadDeserializer)
|
|
|
432
545
|
const result = parse(json)
|
|
433
546
|
```
|
|
434
547
|
|
|
435
|
-
The leaf wrapper format is `['leaf', serializedPayload]`, making it unambiguous
|
|
436
|
-
|
|
437
|
-
## Tests
|
|
438
|
-
|
|
439
|
-
Tests with 100% code coverage.
|
|
440
|
-
|
|
441
|
-
```bash
|
|
442
|
-
npm t -- -R silent
|
|
443
|
-
npm t -- report text-summary
|
|
444
|
-
```
|
|
445
|
-
```
|
|
446
|
-
|
|
447
|
-
> sendscript@2.3.1 test
|
|
448
|
-
> tap -R silent
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
> sendscript@2.3.1 test
|
|
452
|
-
> tap report text-summary
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
=============================== Coverage summary ===============================
|
|
456
|
-
Statements : 100% ( 372/372 )
|
|
457
|
-
Branches : 100% ( 137/137 )
|
|
458
|
-
Functions : 100% ( 24/24 )
|
|
459
|
-
Lines : 100% ( 372/372 )
|
|
460
|
-
================================================================================
|
|
461
|
-
```
|
|
462
|
-
|
|
463
|
-
## Formatting
|
|
464
|
-
|
|
465
|
-
Standard because no config.
|
|
466
|
-
|
|
467
|
-
```bash
|
|
468
|
-
npx standard
|
|
469
|
-
```
|
|
548
|
+
The leaf wrapper format is `['leaf', serializedPayload]`, making it unambiguous
|
|
549
|
+
and safe from colliding with SendScript operators.
|
|
470
550
|
|
|
471
551
|
## Changelog
|
|
472
552
|
|
|
@@ -477,27 +557,22 @@ The [changelog][changelog] is generated using the useful
|
|
|
477
557
|
npx auto-changelog -p
|
|
478
558
|
```
|
|
479
559
|
|
|
480
|
-
##
|
|
560
|
+
## License
|
|
481
561
|
|
|
482
|
-
|
|
562
|
+
See the [LICENSE.txt][license] file for details.
|
|
483
563
|
|
|
484
|
-
|
|
485
|
-
npm outdated && echo 'No outdated packages found'
|
|
486
|
-
```
|
|
487
|
-
```
|
|
488
|
-
No outdated packages found
|
|
489
|
-
```
|
|
564
|
+
## Issues
|
|
490
565
|
|
|
491
|
-
|
|
566
|
+
See [issues][issues] for roadmap and known bugs.
|
|
492
567
|
|
|
493
|
-
|
|
568
|
+
[license]: ./LICENSE.txt
|
|
569
|
+
|
|
570
|
+
[socket.io]: https://socket.io/
|
|
571
|
+
|
|
572
|
+
[changelog]: ./CHANGELOG.md
|
|
494
573
|
|
|
495
|
-
|
|
574
|
+
[auto-changelog]: https://www.npmjs.com/package/auto-changelog
|
|
496
575
|
|
|
497
|
-
|
|
576
|
+
[typedoc]: https://github.com/TypeStrong/typedoc
|
|
498
577
|
|
|
499
|
-
[
|
|
500
|
-
[socket.io]:https://socket.io/
|
|
501
|
-
[changelog]:./CHANGELOG.md
|
|
502
|
-
[auto-changelog]:https://www.npmjs.com/package/auto-changelog
|
|
503
|
-
[typedoc]:https://github.com/TypeStrong/typedoc
|
|
578
|
+
[issues]: https://github.com/bas080/sendscript/issues
|