sendscript 2.4.1 → 2.4.2
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/CHANGELOG.md +8 -0
- package/CONTRIBUTING.md +0 -2
- package/README.md +101 -213
- package/README.mz +69 -43
- package/example/typescript/docs/functions/add.md +1 -1
- package/example/typescript/docs/functions/square.md +1 -1
- package/package.json +1 -1
- package/curry.mjs +0 -11
- package/curry.test.mjs +0 -35
package/CHANGELOG.md
CHANGED
|
@@ -4,8 +4,16 @@ 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.4.2](https://github.com/bas080/sendscript/compare/v2.4.1...v2.4.2)
|
|
8
|
+
|
|
9
|
+
- Update tap and typedoc [`46421de`](https://github.com/bas080/sendscript/commit/46421de16533066ee13c91ea75505b1ecdd548f0)
|
|
10
|
+
- Remove the unused curry helper [`9dcbb48`](https://github.com/bas080/sendscript/commit/9dcbb485b455937070c65359ecde8236c128bee8)
|
|
11
|
+
- Remove duplicate Promises section with outdated async/await information [`5f43ddb`](https://github.com/bas080/sendscript/commit/5f43ddb91ddb2d77227ddd6a570807f874230ea1)
|
|
12
|
+
|
|
7
13
|
#### [v2.4.1](https://github.com/bas080/sendscript/compare/v2.4.0...v2.4.1)
|
|
8
14
|
|
|
15
|
+
> 29 June 2026
|
|
16
|
+
|
|
9
17
|
- Update tap and typedoc version [`3f10410`](https://github.com/bas080/sendscript/commit/3f1041020e00331ff30ffb5f972738dbaf7a50f3)
|
|
10
18
|
- Update tap to 21.7.1 [`d1b5bbd`](https://github.com/bas080/sendscript/commit/d1b5bbd4cb7012e6606973d3d23d08df56cadca2)
|
|
11
19
|
- Document limitations of sendscript [`f577499`](https://github.com/bas080/sendscript/commit/f577499279b85e04ea589a3bcb1866d145216f00)
|
package/CONTRIBUTING.md
CHANGED
|
@@ -52,8 +52,6 @@ Generate the README from the mz file.
|
|
|
52
52
|
```bash bash
|
|
53
53
|
markatzea ./README.mz | tee ./README.md
|
|
54
54
|
|
|
55
|
-
npx documentation readme schema.mjs references.mjs stringify.mjs parse.mjs -s Reference --github --a public --markdown-toc false
|
|
56
|
-
|
|
57
55
|
npx markdown-toc --maxdepth 3 -i README.md
|
|
58
56
|
|
|
59
57
|
git add *.md ./example
|
package/README.md
CHANGED
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
# SendScript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Serialize and execute composable JavaScript function calls with JSON.
|
|
4
4
|
|
|
5
|
-
[](https://www.npmjs.com/package/sendscript)
|
|
6
6
|
[](#tests)
|
|
7
7
|
[](https://standardjs.com)
|
|
8
|
-
[](./LICENSE.txt)
|
|
9
|
+
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Composable function calls** - Combine multiple functions into a single
|
|
13
|
+
request
|
|
14
|
+
- **Write ordinary JavaScript** - Programs serialize to JSON and execute as
|
|
15
|
+
written
|
|
16
|
+
- **Type-safe** - Works great with TypeScript for client-side type checking
|
|
17
|
+
- **Zero dependencies** - Lightweight core library
|
|
18
|
+
- **Async/await support** - Seamless async operations within a single payload
|
|
19
|
+
- **Custom serializers** - Support for Date, Map, Set, BigInt, and more
|
|
20
|
+
- **Transport agnostic** - Use HTTP, WebSockets, or any other communication
|
|
21
|
+
method
|
|
9
22
|
|
|
10
23
|
<!-- toc -->
|
|
11
24
|
|
|
25
|
+
- [Installation](#installation)
|
|
26
|
+
- [Quick Start](#quick-start)
|
|
12
27
|
- [Introduction](#introduction)
|
|
13
|
-
- [
|
|
14
|
-
|
|
15
|
-
* [Parse](#parse)
|
|
16
|
-
* [parse](#parse)
|
|
17
|
-
* [References](#references)
|
|
18
|
-
* [SchemaNode](#schemanode)
|
|
19
|
-
* [Schema](#schema)
|
|
20
|
-
* [defaultLeafStringify](#defaultleafstringify)
|
|
21
|
-
* [Stringify](#stringify)
|
|
22
|
-
* [stringify](#stringify)
|
|
28
|
+
- [Why SendScript?](#why-sendscript)
|
|
29
|
+
- [How It Works](#how-it-works)
|
|
23
30
|
- [Socket example](#socket-example)
|
|
24
31
|
* [Module](#module)
|
|
25
32
|
* [Server](#server)
|
|
@@ -28,9 +35,6 @@ RPC and no-build with composable function calls in a single payload.
|
|
|
28
35
|
- [Promises](#promises)
|
|
29
36
|
* [.then / .catch](#then--catch)
|
|
30
37
|
* [await](#await)
|
|
31
|
-
- [Promises](#promises-1)
|
|
32
|
-
* [.then / .catch](#then--catch-1)
|
|
33
|
-
* [await](#await-1)
|
|
34
38
|
- [TypeScript](#typescript)
|
|
35
39
|
- [Schema and Nested Modules](#schema-and-nested-modules)
|
|
36
40
|
* [Defining a Nested Module](#defining-a-nested-module)
|
|
@@ -50,17 +54,63 @@ RPC and no-build with composable function calls in a single payload.
|
|
|
50
54
|
|
|
51
55
|
<!-- tocstop -->
|
|
52
56
|
|
|
57
|
+
## Installation
|
|
58
|
+
|
|
59
|
+
Install SendScript from npm:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
npm install sendscript
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
Here's the simplest example to get started with SendScript:
|
|
68
|
+
|
|
69
|
+
```js
|
|
70
|
+
import Stringify from 'sendscript/stringify.mjs'
|
|
71
|
+
import Parse from 'sendscript/parse.mjs'
|
|
72
|
+
import references from 'sendscript/references.mjs'
|
|
73
|
+
|
|
74
|
+
// Define your functions
|
|
75
|
+
const functions = {
|
|
76
|
+
greet: (name) => `Hello, ${name}!`,
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create client-side stubs
|
|
80
|
+
const { greet } = references(['greet'])
|
|
81
|
+
|
|
82
|
+
// Serialize a program on the client
|
|
83
|
+
const stringify = Stringify()
|
|
84
|
+
const program = stringify(greet('World'))
|
|
85
|
+
|
|
86
|
+
// Parse and execute on the server
|
|
87
|
+
const parse = Parse(['greet'], functions)
|
|
88
|
+
const result = parse(program) // "Hello, World!"
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
This demonstrates the core concept: write a program on the client, serialize it
|
|
92
|
+
to JSON, send it to the server, and execute it exactly as written.
|
|
93
|
+
|
|
53
94
|
## Introduction
|
|
54
95
|
|
|
55
96
|
There has been interest in improving APIs by allowing aggregations in a single
|
|
56
97
|
request. Examples include
|
|
57
98
|
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
99
|
+
- [JSON-RPC](https://json-rpc.dev/) which allows you to do multiple requests but
|
|
100
|
+
it does not allow you to compose the return value of one endpoint to be the
|
|
101
|
+
input/arguments of another.
|
|
102
|
+
|
|
103
|
+
- [GraphQL](https://graphql.org/) is very cool but also introduces a new
|
|
104
|
+
language and the tooling that is required to wield it.
|
|
105
|
+
|
|
106
|
+
## Why SendScript?
|
|
61
107
|
|
|
62
|
-
|
|
63
|
-
|
|
108
|
+
Unlike JSON-RPC (which doesn't support function composition) or GraphQL (which
|
|
109
|
+
requires learning a new language), SendScript lets you write ordinary
|
|
110
|
+
JavaScript/TypeScript that gets serialized and executed on the server exactly as
|
|
111
|
+
written.
|
|
112
|
+
|
|
113
|
+
## How It Works
|
|
64
114
|
|
|
65
115
|
What SendScript attempts is to allow for very expressive queries and mutations
|
|
66
116
|
to be performed that read and write like ordinary JS. That means that the
|
|
@@ -81,7 +131,6 @@ const stringify = Stringify()
|
|
|
81
131
|
|
|
82
132
|
console.log(stringify(add(1,2)))
|
|
83
133
|
```
|
|
84
|
-
|
|
85
134
|
```json
|
|
86
135
|
["call",["ref","add"],[["leaf","1"],["leaf","2"]]]
|
|
87
136
|
```
|
|
@@ -103,7 +152,6 @@ const program = '["call",["ref","add"],[1,2]]'
|
|
|
103
152
|
|
|
104
153
|
console.log(parse(program))
|
|
105
154
|
```
|
|
106
|
-
|
|
107
155
|
```json
|
|
108
156
|
3
|
|
109
157
|
```
|
|
@@ -113,131 +161,18 @@ composition and even await.
|
|
|
113
161
|
|
|
114
162
|
This package is nothing more than the absolute core of sendscript. It includes:
|
|
115
163
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
The naming could use more love and there are many things to solve either in the
|
|
122
|
-
core or around it. Things like supporting more complex (de)serializers, errors
|
|
123
|
-
and maybe mixing client functions with sendscript programs. Contact me if I have
|
|
124
|
-
piqued your interest.
|
|
125
|
-
|
|
126
|
-
## Reference
|
|
127
|
-
|
|
128
|
-
<!-- Generated by documentation.js. Update this documentation by updating the source code. -->
|
|
129
|
-
|
|
130
|
-
### defaultLeafParse
|
|
131
|
-
|
|
132
|
-
[parse.mjs:49-49](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/parse.mjs#L49-L49 "Source code on GitHub")
|
|
133
|
-
|
|
134
|
-
Default deserializer for leaf nodes.
|
|
135
|
-
|
|
136
|
-
#### Parameters
|
|
137
|
-
|
|
138
|
-
* `text` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
139
|
-
|
|
140
|
-
Returns **any** 
|
|
141
|
-
|
|
142
|
-
### Parse
|
|
143
|
-
|
|
144
|
-
[parse.mjs:68-215](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/parse.mjs#L68-L215 "Source code on GitHub")
|
|
145
|
-
|
|
146
|
-
#### Parameters
|
|
147
|
-
|
|
148
|
-
* `schema` **[Schema](#schema)** 
|
|
149
|
-
* `env` **Env** runtime environment for refs
|
|
150
|
-
* `leafParse` (optional, default `defaultLeafParse`)
|
|
151
|
-
|
|
152
|
-
Returns **[parse](#parse)** 
|
|
153
|
-
|
|
154
|
-
### parse
|
|
155
|
-
|
|
156
|
-
[parse.mjs:78-214](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/parse.mjs#L78-L214 "Source code on GitHub")
|
|
157
|
-
|
|
158
|
-
Parses and executes a serialized program.
|
|
159
|
-
|
|
160
|
-
#### Parameters
|
|
161
|
-
|
|
162
|
-
* `program` **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** JSON encoded program
|
|
163
|
-
|
|
164
|
-
Returns **(any | [Promise](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Promise)\<any>)** 
|
|
165
|
-
|
|
166
|
-
### References
|
|
167
|
-
|
|
168
|
-
[references.mjs:109-127](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/references.mjs#L109-L127 "Source code on GitHub")
|
|
169
|
-
|
|
170
|
-
Builds a nested API structure from a schema definition.
|
|
171
|
-
|
|
172
|
-
#### Parameters
|
|
173
|
-
|
|
174
|
-
* `schema` **[Schema](#schema)** 
|
|
175
|
-
* `parentPath` (optional, default `[]`)
|
|
176
|
-
|
|
177
|
-
<!---->
|
|
178
|
-
|
|
179
|
-
* Throws **[Error](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Error)** If schema format is invalid
|
|
180
|
-
|
|
181
|
-
Returns **[Object](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Object)** Nested instrumented API object
|
|
182
|
-
|
|
183
|
-
### SchemaNode
|
|
184
|
-
|
|
185
|
-
[schema.mjs:1-19](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/schema.mjs#L1-L6 "Source code on GitHub")
|
|
186
|
-
|
|
187
|
-
A single schema node.
|
|
188
|
-
|
|
189
|
-
Type: ([string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String) | \[[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String), [Schema](#schema)])
|
|
190
|
-
|
|
191
|
-
### Schema
|
|
192
|
-
|
|
193
|
-
[schema.mjs:1-19](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/schema.mjs#L8-L18 "Source code on GitHub")
|
|
164
|
+
- The `references` function to create stubs to write the programs.
|
|
165
|
+
- `stringify` which takes the program and returns a JSON string.
|
|
166
|
+
- `parse` which takes the `stringify` JSON string and a real module and returns
|
|
167
|
+
the result.
|
|
194
168
|
|
|
195
|
-
|
|
169
|
+
> **Note:** SendScript works in Node.js and browsers. The core library is
|
|
170
|
+
> framework-agnostic and transport-agnostic — use HTTP, WebSockets, or any other
|
|
171
|
+
> communication method that suits your needs.
|
|
196
172
|
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
Schema is recursive: nodes can contain nested schemas.
|
|
201
|
-
|
|
202
|
-
Type: [Array](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Array)<[SchemaNode](#schemanode)>
|
|
203
|
-
|
|
204
|
-
### defaultLeafStringify
|
|
205
|
-
|
|
206
|
-
[stringify.mjs:37-47](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/stringify.mjs#L37-L47 "Source code on GitHub")
|
|
207
|
-
|
|
208
|
-
Default strict serializer for leaf values.
|
|
209
|
-
|
|
210
|
-
Rejects non-JSON-safe values.
|
|
211
|
-
|
|
212
|
-
#### Parameters
|
|
213
|
-
|
|
214
|
-
* `x` **any** 
|
|
215
|
-
|
|
216
|
-
Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
217
|
-
|
|
218
|
-
### Stringify
|
|
219
|
-
|
|
220
|
-
[stringify.mjs:56-157](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/stringify.mjs#L56-L157 "Source code on GitHub")
|
|
221
|
-
|
|
222
|
-
Creates a stringify function for SendScript AST structures.
|
|
223
|
-
|
|
224
|
-
#### Parameters
|
|
225
|
-
|
|
226
|
-
* `leafStringify` (optional, default `defaultLeafStringify`)
|
|
227
|
-
|
|
228
|
-
Returns **[stringify](#stringify)** 
|
|
229
|
-
|
|
230
|
-
### stringify
|
|
231
|
-
|
|
232
|
-
[stringify.mjs:64-156](https://github.com/bas080/sendscript/blob/3f1041020e00331ff30ffb5f972738dbaf7a50f3/stringify.mjs#L64-L156 "Source code on GitHub")
|
|
233
|
-
|
|
234
|
-
Serializes a program into a JSON string representation.
|
|
235
|
-
|
|
236
|
-
#### Parameters
|
|
237
|
-
|
|
238
|
-
* `program` **any** 
|
|
239
|
-
|
|
240
|
-
Returns **[string](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/String)** 
|
|
173
|
+
Future enhancements may include support for more complex (de)serializers,
|
|
174
|
+
improved error handling, and deeper integration of client functions with
|
|
175
|
+
SendScript programs. Contributions and feedback are welcome.
|
|
241
176
|
|
|
242
177
|
## Socket example
|
|
243
178
|
|
|
@@ -259,7 +194,7 @@ export const square = (a) => a * a
|
|
|
259
194
|
|
|
260
195
|
### Server
|
|
261
196
|
|
|
262
|
-
Here a socket.io server that runs SendScript programs.
|
|
197
|
+
Here's a socket.io server that runs SendScript programs.
|
|
263
198
|
|
|
264
199
|
```js
|
|
265
200
|
// ./example/server.socket.io.mjs
|
|
@@ -339,8 +274,9 @@ node ./example/client.socket.io.mjs
|
|
|
339
274
|
|
|
340
275
|
pkill sendscript
|
|
341
276
|
```
|
|
342
|
-
|
|
343
|
-
|
|
277
|
+
```
|
|
278
|
+
Result: 100
|
|
279
|
+
```
|
|
344
280
|
|
|
345
281
|
## Repl
|
|
346
282
|
|
|
@@ -354,39 +290,7 @@ run it by simply typing `sendscript` in their console.
|
|
|
354
290
|
|
|
355
291
|
### .then / .catch
|
|
356
292
|
|
|
357
|
-
Supported since
|
|
358
|
-
|
|
359
|
-
```js
|
|
360
|
-
const getOrCreatePost = send(createPost(title).catch(createPost(title)))
|
|
361
|
-
```
|
|
362
|
-
|
|
363
|
-
You will likely need to define better helpers that makes it safer to handle
|
|
364
|
-
rejections and work with promises. It is however sensible to have this basic
|
|
365
|
-
behavior for the sendscript DSL and parser.
|
|
366
|
-
|
|
367
|
-
### await
|
|
368
|
-
|
|
369
|
-
SendScript as of `v2.4` supports functions to do basic templating. It does not
|
|
370
|
-
support async functions and will throw an error when you define one.
|
|
371
|
-
|
|
372
|
-
Under the hood the function is called when it is being parsed. Make sure you
|
|
373
|
-
understand what you are doing when mixing client and server functions.
|
|
374
|
-
|
|
375
|
-
```js
|
|
376
|
-
map((a) => add(a, 1))([1, 2, 3]))
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
It also supports nested functions.
|
|
380
|
-
|
|
381
|
-
```js
|
|
382
|
-
map(call)(map((a) => () => add(a, 1))([1, 2, 3]))
|
|
383
|
-
```
|
|
384
|
-
|
|
385
|
-
## Promises
|
|
386
|
-
|
|
387
|
-
### .then / .catch
|
|
388
|
-
|
|
389
|
-
Supported since vs `v2.3`.
|
|
293
|
+
Supported since `v2.3`.
|
|
390
294
|
|
|
391
295
|
```js
|
|
392
296
|
const getOrCreatePost = send(createPost(title).catch(createPost(title)))
|
|
@@ -424,19 +328,18 @@ defined properties and returned values.
|
|
|
424
328
|
|
|
425
329
|
There is a good use-case to write a module in TypeScript.
|
|
426
330
|
|
|
427
|
-
1.
|
|
428
|
-
|
|
429
|
-
2.
|
|
430
|
-
|
|
431
|
-
3.
|
|
432
|
-
|
|
331
|
+
1. Obviously the module would have the benefits that TypeScript offers when
|
|
332
|
+
coding.
|
|
333
|
+
2. You can use tools like [typedoc][typedoc] to generate docs from your types to
|
|
334
|
+
share with consumers of your API.
|
|
335
|
+
3. You can use the types of the module to coerce your client to adopt the
|
|
336
|
+
module's type.
|
|
433
337
|
|
|
434
338
|
Let's say we have this module which we use on the server.
|
|
435
339
|
|
|
436
340
|
```bash
|
|
437
341
|
cat ./example/typescript/math.ts
|
|
438
342
|
```
|
|
439
|
-
|
|
440
343
|
```ts
|
|
441
344
|
export const add = (a: number, b: number) => a + b
|
|
442
345
|
export const square = (a: number) => a * a
|
|
@@ -447,7 +350,6 @@ We can then coerce the types of the instrumented stubs.
|
|
|
447
350
|
```bash
|
|
448
351
|
cat ./example/typescript/client.ts
|
|
449
352
|
```
|
|
450
|
-
|
|
451
353
|
```ts
|
|
452
354
|
import math from './math.client.ts'
|
|
453
355
|
import Stringify from 'sendscript/stringify.mjs'
|
|
@@ -473,7 +375,7 @@ npx typedoc --plugin typedoc-plugin-markdown --out ./example/typescript/docs ./e
|
|
|
473
375
|
|
|
474
376
|
You can see the docs [here](./example/typescript/docs/globals.md)
|
|
475
377
|
|
|
476
|
-
>
|
|
378
|
+
> [!NOTE] Although type coercion on the client side can improve the development
|
|
477
379
|
> experience, it does not represent the actual type. Values are subject to
|
|
478
380
|
> serialization and deserialization.
|
|
479
381
|
|
|
@@ -540,9 +442,9 @@ export function createUser(user) {
|
|
|
540
442
|
|
|
541
443
|
**Benefits**:
|
|
542
444
|
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
445
|
+
- Ensures arguments match expected types and shapes.
|
|
446
|
+
- Throws structured errors that can be propagated to clients.
|
|
447
|
+
- Works with TypeScript for automatic type inference.
|
|
546
448
|
|
|
547
449
|
## Leaf Serializer
|
|
548
450
|
|
|
@@ -661,7 +563,7 @@ a new step.
|
|
|
661
563
|
### Error handling
|
|
662
564
|
|
|
663
565
|
Sendscript does not have builtin tools to handle errors. You can write your own
|
|
664
|
-
utilities for that or use things like
|
|
566
|
+
utilities for that or use things like [Ramda's tryCatch][tryCatch]. This will
|
|
665
567
|
likely never be supported as JS try catch does not have a return value. It might
|
|
666
568
|
make sense to wrap everything that can throw in promises which is easy to do
|
|
667
569
|
with async functions.
|
|
@@ -674,22 +576,13 @@ Tests with 100% code coverage.
|
|
|
674
576
|
npm t -- -R silent
|
|
675
577
|
npm t -- report text-summary
|
|
676
578
|
```
|
|
677
|
-
|
|
678
579
|
```
|
|
679
580
|
|
|
680
|
-
> sendscript@2.4.1 test
|
|
681
|
-
> tap -R silent
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
> sendscript@2.4.1 test
|
|
685
|
-
> tap report text-summary
|
|
686
|
-
|
|
687
|
-
|
|
688
581
|
=============================== Coverage summary ===============================
|
|
689
|
-
Statements : 100% (
|
|
690
|
-
Branches : 100% (
|
|
691
|
-
Functions : 100% (
|
|
692
|
-
Lines : 100% (
|
|
582
|
+
Statements : 100% ( 512/512 )
|
|
583
|
+
Branches : 100% ( 147/147 )
|
|
584
|
+
Functions : 100% ( 23/23 )
|
|
585
|
+
Lines : 100% ( 512/512 )
|
|
693
586
|
================================================================================
|
|
694
587
|
```
|
|
695
588
|
|
|
@@ -719,13 +612,8 @@ See the [LICENSE.txt][license] file for details.
|
|
|
719
612
|
See [issues][issues] for roadmap and known bugs.
|
|
720
613
|
|
|
721
614
|
[license]: ./LICENSE.txt
|
|
722
|
-
|
|
723
615
|
[socket.io]: https://socket.io/
|
|
724
|
-
|
|
725
616
|
[changelog]: ./CHANGELOG.md
|
|
726
|
-
|
|
727
617
|
[auto-changelog]: https://www.npmjs.com/package/auto-changelog
|
|
728
|
-
|
|
729
618
|
[typedoc]: https://github.com/TypeStrong/typedoc
|
|
730
|
-
|
|
731
619
|
[issues]: https://github.com/bas080/sendscript/issues
|
package/README.mz
CHANGED
|
@@ -1,14 +1,64 @@
|
|
|
1
1
|
# SendScript
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Serialize and execute composable JavaScript function calls with JSON.
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/sendscript)
|
|
6
6
|
[](#tests)
|
|
7
7
|
[](https://standardjs.com)
|
|
8
8
|
[](./LICENSE.txt)
|
|
9
9
|
|
|
10
|
+
## Features
|
|
11
|
+
|
|
12
|
+
- **Composable function calls** - Combine multiple functions into a single
|
|
13
|
+
request
|
|
14
|
+
- **Write ordinary JavaScript** - Programs serialize to JSON and execute as
|
|
15
|
+
written
|
|
16
|
+
- **Type-safe** - Works great with TypeScript for client-side type checking
|
|
17
|
+
- **Zero dependencies** - Lightweight core library
|
|
18
|
+
- **Async/await support** - Seamless async operations within a single payload
|
|
19
|
+
- **Custom serializers** - Support for Date, Map, Set, BigInt, and more
|
|
20
|
+
- **Transport agnostic** - Use HTTP, WebSockets, or any other communication
|
|
21
|
+
method
|
|
22
|
+
|
|
10
23
|
<!-- toc -->
|
|
11
24
|
|
|
25
|
+
## Installation
|
|
26
|
+
|
|
27
|
+
Install SendScript from npm:
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
npm install sendscript
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Quick Start
|
|
34
|
+
|
|
35
|
+
Here's the simplest example to get started with SendScript:
|
|
36
|
+
|
|
37
|
+
```js
|
|
38
|
+
import Stringify from 'sendscript/stringify.mjs'
|
|
39
|
+
import Parse from 'sendscript/parse.mjs'
|
|
40
|
+
import references from 'sendscript/references.mjs'
|
|
41
|
+
|
|
42
|
+
// Define your functions
|
|
43
|
+
const functions = {
|
|
44
|
+
greet: (name) => `Hello, ${name}!`,
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Create client-side stubs
|
|
48
|
+
const { greet } = references(['greet'])
|
|
49
|
+
|
|
50
|
+
// Serialize a program on the client
|
|
51
|
+
const stringify = Stringify()
|
|
52
|
+
const program = stringify(greet('World'))
|
|
53
|
+
|
|
54
|
+
// Parse and execute on the server
|
|
55
|
+
const parse = Parse(['greet'], functions)
|
|
56
|
+
const result = parse(program) // "Hello, World!"
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
This demonstrates the core concept: write a program on the client, serialize it
|
|
60
|
+
to JSON, send it to the server, and execute it exactly as written.
|
|
61
|
+
|
|
12
62
|
## Introduction
|
|
13
63
|
|
|
14
64
|
There has been interest in improving APIs by allowing aggregations in a single
|
|
@@ -19,7 +69,16 @@ request. Examples include
|
|
|
19
69
|
input/arguments of another.
|
|
20
70
|
|
|
21
71
|
- [GraphQL](https://graphql.org/) is very cool but also introduces a new
|
|
22
|
-
|
|
72
|
+
language and the tooling that is required to wield it.
|
|
73
|
+
|
|
74
|
+
## Why SendScript?
|
|
75
|
+
|
|
76
|
+
Unlike JSON-RPC (which doesn't support function composition) or GraphQL (which
|
|
77
|
+
requires learning a new language), SendScript lets you write ordinary
|
|
78
|
+
JavaScript/TypeScript that gets serialized and executed on the server exactly as
|
|
79
|
+
written.
|
|
80
|
+
|
|
81
|
+
## How It Works
|
|
23
82
|
|
|
24
83
|
What SendScript attempts is to allow for very expressive queries and mutations
|
|
25
84
|
to be performed that read and write like ordinary JS. That means that the
|
|
@@ -69,14 +128,13 @@ This package is nothing more than the absolute core of sendscript. It includes:
|
|
|
69
128
|
- `parse` which takes the `stringify` JSON string and a real module and returns
|
|
70
129
|
the result.
|
|
71
130
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
piqued your interest.
|
|
76
|
-
|
|
77
|
-
## Reference
|
|
131
|
+
> **Note:** SendScript works in Node.js and browsers. The core library is
|
|
132
|
+
> framework-agnostic and transport-agnostic — use HTTP, WebSockets, or any other
|
|
133
|
+
> communication method that suits your needs.
|
|
78
134
|
|
|
79
|
-
|
|
135
|
+
Future enhancements may include support for more complex (de)serializers,
|
|
136
|
+
improved error handling, and deeper integration of client functions with
|
|
137
|
+
SendScript programs. Contributions and feedback are welcome.
|
|
80
138
|
|
|
81
139
|
## Socket example
|
|
82
140
|
|
|
@@ -98,7 +156,7 @@ export const square = (a) => a * a
|
|
|
98
156
|
|
|
99
157
|
### Server
|
|
100
158
|
|
|
101
|
-
Here a socket.io server that runs SendScript programs.
|
|
159
|
+
Here's a socket.io server that runs SendScript programs.
|
|
102
160
|
|
|
103
161
|
```js cat - > ./example/server.socket.io.mjs
|
|
104
162
|
// ./example/server.socket.io.mjs
|
|
@@ -191,39 +249,7 @@ run it by simply typing `sendscript` in their console.
|
|
|
191
249
|
|
|
192
250
|
### .then / .catch
|
|
193
251
|
|
|
194
|
-
Supported since
|
|
195
|
-
|
|
196
|
-
```js
|
|
197
|
-
const getOrCreatePost = send(createPost(title).catch(createPost(title)))
|
|
198
|
-
```
|
|
199
|
-
|
|
200
|
-
You will likely need to define better helpers that makes it safer to handle
|
|
201
|
-
rejections and work with promises. It is however sensible to have this basic
|
|
202
|
-
behavior for the sendscript DSL and parser.
|
|
203
|
-
|
|
204
|
-
### await
|
|
205
|
-
|
|
206
|
-
SendScript as of `v2.4` supports functions to do basic templating. It does not
|
|
207
|
-
support async functions and will throw an error when you define one.
|
|
208
|
-
|
|
209
|
-
Under the hood the function is called when it is being parsed. Make sure you
|
|
210
|
-
understand what you are doing when mixing client and server functions.
|
|
211
|
-
|
|
212
|
-
```js
|
|
213
|
-
map((a) => add(a, 1))([1, 2, 3]))
|
|
214
|
-
```
|
|
215
|
-
|
|
216
|
-
It also supports nested functions.
|
|
217
|
-
|
|
218
|
-
```js
|
|
219
|
-
map(call)(map((a) => () => add(a, 1))([1, 2, 3]))
|
|
220
|
-
```
|
|
221
|
-
|
|
222
|
-
## Promises
|
|
223
|
-
|
|
224
|
-
### .then / .catch
|
|
225
|
-
|
|
226
|
-
Supported since vs `v2.3`.
|
|
252
|
+
Supported since `v2.3`.
|
|
227
253
|
|
|
228
254
|
```js
|
|
229
255
|
const getOrCreatePost = send(createPost(title).catch(createPost(title)))
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
> **add**(`a`, `b`): `number`
|
|
10
10
|
|
|
11
|
-
Defined in: [math.ts:1](https://github.com/bas080/sendscript/blob/
|
|
11
|
+
Defined in: [math.ts:1](https://github.com/bas080/sendscript/blob/46421de16533066ee13c91ea75505b1ecdd548f0/example/typescript/math.ts#L1)
|
|
12
12
|
|
|
13
13
|
## Parameters
|
|
14
14
|
|
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
> **square**(`a`): `number`
|
|
10
10
|
|
|
11
|
-
Defined in: [math.ts:2](https://github.com/bas080/sendscript/blob/
|
|
11
|
+
Defined in: [math.ts:2](https://github.com/bas080/sendscript/blob/46421de16533066ee13c91ea75505b1ecdd548f0/example/typescript/math.ts#L2)
|
|
12
12
|
|
|
13
13
|
## Parameters
|
|
14
14
|
|
package/package.json
CHANGED
package/curry.mjs
DELETED
package/curry.test.mjs
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import { test } from 'tap'
|
|
2
|
-
import curry from './curry.mjs'
|
|
3
|
-
|
|
4
|
-
test('curry function', (t) => {
|
|
5
|
-
t.test('curry function returns a function', (assert) => {
|
|
6
|
-
const curried = curry((a, b, c) => a + b + c)
|
|
7
|
-
assert.type(curried, 'function', 'returns a function')
|
|
8
|
-
assert.end()
|
|
9
|
-
})
|
|
10
|
-
|
|
11
|
-
t.test('curried function returns correct result', (assert) => {
|
|
12
|
-
const curried = curry((a, b, c) => a + b + c)
|
|
13
|
-
const result = curried(1)(2)(3)
|
|
14
|
-
assert.equal(result, 6, 'returns correct result')
|
|
15
|
-
assert.end()
|
|
16
|
-
})
|
|
17
|
-
|
|
18
|
-
t.test('curried function handles partial application', (assert) => {
|
|
19
|
-
const curried = curry((a, b, c) => a + b + c)
|
|
20
|
-
const partial = curried(1, 2)
|
|
21
|
-
const result = partial(3)
|
|
22
|
-
assert.equal(result, 6, 'handles partial application')
|
|
23
|
-
assert.end()
|
|
24
|
-
})
|
|
25
|
-
|
|
26
|
-
t.test('curried function handles multiple arguments', (assert) => {
|
|
27
|
-
const curried = curry((a, b, c, d) => a + b + c + d)
|
|
28
|
-
const partial = curried(1)
|
|
29
|
-
const result = partial(2)(3, 4)
|
|
30
|
-
assert.equal(result, 10, 'handles multiple arguments')
|
|
31
|
-
assert.end()
|
|
32
|
-
})
|
|
33
|
-
|
|
34
|
-
t.end()
|
|
35
|
-
})
|