sendscript 0.0.0 → 0.0.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 ADDED
@@ -0,0 +1,23 @@
1
+ ### Changelog
2
+
3
+ All notable changes to this project will be documented in this file. Dates are displayed in UTC.
4
+
5
+ Generated by [`auto-changelog`](https://github.com/CookPete/auto-changelog).
6
+
7
+ #### [v0.0.2](https://github.com/bas080/sendscript/compare/v0.0.1...v0.0.2)
8
+
9
+ - Add table of content to readme [`a14f2d8`](https://github.com/bas080/sendscript/commit/a14f2d86f602a01721812d1c5be94b299e515397)
10
+
11
+ #### [v0.0.1](https://github.com/bas080/sendscript/compare/v0.0.0...v0.0.1)
12
+
13
+ > 26 September 2023
14
+
15
+ - Add square fn to the socket.io example [`8d7cfbd`](https://github.com/bas080/sendscript/commit/8d7cfbddd7933804e7168825cf1e17e792c91fe9)
16
+ - Rename dsl to api [`4a67324`](https://github.com/bas080/sendscript/commit/4a6732456656db743d02c5c35444f93a866d27ec)
17
+ - Move promise only concept to own module [`50adde6`](https://github.com/bas080/sendscript/commit/50adde694b3d23fb025a4ad20dcc83d7bb72b852)
18
+
19
+ #### v0.0.0
20
+
21
+ > 14 September 2023
22
+
23
+ - Initiate project [`2a192b3`](https://github.com/bas080/sendscript/commit/2a192b34e5390ab946b7b77fd299e23180c49f72)
package/README.md CHANGED
@@ -3,11 +3,29 @@
3
3
  Write JS code that you can run on servers, browsers or other clients.
4
4
 
5
5
  [![NPM](https://img.shields.io/npm/v/sendscript?color=blue&style=flat-square)](https://www.npmjs.com/package/sendscript)
6
+ [![100% Code Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square)](#tests)
6
7
  [![Standard Code Style](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](https://standardjs.com)
7
- [![License](https://img.shields.io/npm/l/sendscript?color=brightgreen&style=flat-square)](./LICENSE)
8
+ [![License](https://img.shields.io/npm/l/sendscript?color=brightgreen&style=flat-square)](./LICENSE.txt)
8
9
 
9
- > SendScript leaves it up to you to choose HTTP, web-sockets or any other method of
10
- > communication between servers and clients that best fits your needs.
10
+ > SendScript leaves it up to you to choose HTTP, web-sockets or any other
11
+ > method of communication between servers and clients that best fits your
12
+ > needs.
13
+
14
+ <!-- toc -->
15
+
16
+ - [Socket example](#socket-example)
17
+ * [Module](#module)
18
+ * [Server](#server)
19
+ * [Client](#client)
20
+ - [Reference](#reference)
21
+ * [`sendscript/api.mjs`](#sendscriptapimjs)
22
+ * [`sendscript/exec.mjs`](#sendscriptexecmjs)
23
+ - [Tests](#tests)
24
+ - [Formatting](#formatting)
25
+ - [Changelog](#changelog)
26
+ - [License](#license)
27
+
28
+ <!-- tocstop -->
11
29
 
12
30
  ## Socket example
13
31
 
@@ -21,17 +39,18 @@ npm install --no-save socket.io socket.io-client
21
39
 
22
40
  ### Module
23
41
 
24
- We write a simple module that only has an add function
42
+ We write a simple module.
25
43
 
26
44
  ```js
27
45
  // ./example/math.mjs
28
46
 
29
47
  export const add = (a, b) => a + b
48
+ export const square = a => a * a
30
49
  ```
31
50
 
32
51
  ### Server
33
52
 
34
- Here a simple module for running a socket.io server that runs SendScript programs.
53
+ Here a socket.io server that runs SendScript programs.
35
54
 
36
55
  ```js
37
56
  // ./example/server.socket.io.mjs
@@ -66,7 +85,7 @@ Now for a client that sends a program to the server.
66
85
  // ./example/client.socket.io.mjs
67
86
 
68
87
  import socketClient from 'socket.io-client'
69
- import dsl from '../dsl.mjs'
88
+ import api from '../api.mjs'
70
89
 
71
90
  const port = process.env.PORT || 3000
72
91
  const client = socketClient(`http://localhost:${port}`)
@@ -81,10 +100,10 @@ const exec = program => {
81
100
  })
82
101
  }
83
102
 
84
- const { add } = dsl(['add'], exec)
103
+ const { add, square } = api(['add', 'square'], exec)
85
104
 
86
105
  console.log(
87
- await add(1, add(add(2, 3), 4))
106
+ await square(add(1, add(add(2, 3), 4)))
88
107
  )
89
108
 
90
109
  process.exit(0)
@@ -102,33 +121,33 @@ node ./example/client.socket.io.mjs
102
121
  pkill sendscript
103
122
  ```
104
123
  ```
105
- 10
124
+ 100
106
125
  ```
107
126
 
108
127
  ## Reference
109
128
 
110
- SendScript is essentially a way to serialize a program to then send over the wire
111
- and execute it somewhere else.
129
+ SendScript is essentially a way to serialize a program to then send over the
130
+ wire and execute it somewhere else.
112
131
 
113
132
  We only have two modules. One that helps you write programs that can be sent
114
133
  over the wire and another for running that program.
115
134
 
116
- ### `sendscript/dsl.mjs`
135
+ ### `sendscript/api.mjs`
117
136
 
118
- The dsl module exports a function that takes two arguments.
137
+ The api module exports a function that takes two arguments.
119
138
 
120
139
  1. The schema, which represents the values that are available.
121
140
  2. The function that will be called with the serializable version of the
122
141
  program.
123
142
 
124
143
  It returns an object that contains functions which are defined in the schema.
125
- These functions are a JavaScript DSL for writing programs that can be sent to
144
+ These functions are a JavaScript API for writing programs that can be sent to
126
145
  a server.
127
146
 
128
147
  ```js
129
- import dsl from './dsl.mjs'
148
+ import api from './api.mjs'
130
149
 
131
- const { add, subtract } = dsl(
150
+ const { add, subtract } = api(
132
151
  ['add', 'subtract'],
133
152
  serializableProgram => sendSomewhereToBeExecuted(serializableProgram)
134
153
  )
@@ -144,7 +163,7 @@ soon as await or `.then` is used.
144
163
  > Notice that you do not have to await the subtract call. You only need to
145
164
  > await when you want to execute the program.
146
165
 
147
- This DSL is composable and wrappable.
166
+ This API is composable and wrappable.
148
167
 
149
168
  ### `sendscript/exec.mjs`
150
169
 
@@ -161,8 +180,8 @@ exec({
161
180
 
162
181
  The array you see here is the LISP that SendScript uses to represent programs.
163
182
 
164
- You could use SendScript without knowing the details of how the LISP works. It is an
165
- implementation detail and might change over time.
183
+ You could use SendScript without knowing the details of how the LISP works. It
184
+ is an implementation detail and might change over time.
166
185
 
167
186
  ## Tests
168
187
 
@@ -173,27 +192,28 @@ npx c8 --100 npm t -- -R classic
173
192
  ```
174
193
  ```
175
194
 
176
- > sendscript@0.0.0 test
195
+ > sendscript@0.0.2 test
177
196
  > tap *.test.mjs --no-cov -R classic
178
197
 
198
+ api.test.mjs .......................................... 5/5
179
199
  curry.test.mjs ........................................ 4/4
180
- dsl.test.mjs .......................................... 5/5
181
- exec.test.mjs ....................................... 15/15
182
- total ............................................... 24/24
200
+ exec.test.mjs ....................................... 16/16
201
+ total ............................................... 25/25
183
202
 
184
- 24 passing (400.194ms)
203
+ 25 passing (426.12ms)
185
204
 
186
205
  ok
187
- -----------|---------|----------|---------|---------|-------------------
188
- File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
189
- -----------|---------|----------|---------|---------|-------------------
190
- All files | 100 | 100 | 100 | 100 |
191
- curry.mjs | 100 | 100 | 100 | 100 |
192
- debug.mjs | 100 | 100 | 100 | 100 |
193
- dsl.mjs | 100 | 100 | 100 | 100 |
194
- error.mjs | 100 | 100 | 100 | 100 |
195
- exec.mjs | 100 | 100 | 100 | 100 |
196
- -----------|---------|----------|---------|---------|-------------------
206
+ ------------------|---------|----------|---------|---------|-------------------
207
+ File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
208
+ ------------------|---------|----------|---------|---------|-------------------
209
+ All files | 100 | 100 | 100 | 100 |
210
+ api.mjs | 100 | 100 | 100 | 100 |
211
+ curry.mjs | 100 | 100 | 100 | 100 |
212
+ debug.mjs | 100 | 100 | 100 | 100 |
213
+ error.mjs | 100 | 100 | 100 | 100 |
214
+ exec.mjs | 100 | 100 | 100 | 100 |
215
+ promise-only.mjs | 100 | 100 | 100 | 100 |
216
+ ------------------|---------|----------|---------|---------|-------------------
197
217
  ```
198
218
 
199
219
  ## Formatting
package/README.mz CHANGED
@@ -3,11 +3,15 @@
3
3
  Write JS code that you can run on servers, browsers or other clients.
4
4
 
5
5
  [![NPM](https://img.shields.io/npm/v/sendscript?color=blue&style=flat-square)](https://www.npmjs.com/package/sendscript)
6
+ [![100% Code Coverage](https://img.shields.io/badge/coverage-100%25-brightgreen?style=flat-square)](#tests)
6
7
  [![Standard Code Style](https://img.shields.io/badge/code_style-standard-brightgreen.svg?style=flat-square)](https://standardjs.com)
7
- [![License](https://img.shields.io/npm/l/sendscript?color=brightgreen&style=flat-square)](./LICENSE)
8
+ [![License](https://img.shields.io/npm/l/sendscript?color=brightgreen&style=flat-square)](./LICENSE.txt)
8
9
 
9
- > SendScript leaves it up to you to choose HTTP, web-sockets or any other method of
10
- > communication between servers and clients that best fits your needs.
10
+ > SendScript leaves it up to you to choose HTTP, web-sockets or any other
11
+ > method of communication between servers and clients that best fits your
12
+ > needs.
13
+
14
+ <!-- toc -->
11
15
 
12
16
  ## Socket example
13
17
 
@@ -21,17 +25,18 @@ npm install --no-save socket.io socket.io-client
21
25
 
22
26
  ### Module
23
27
 
24
- We write a simple module that only has an add function
28
+ We write a simple module.
25
29
 
26
30
  ```js cat - > ./example/math.mjs
27
31
  // ./example/math.mjs
28
32
 
29
33
  export const add = (a, b) => a + b
34
+ export const square = a => a * a
30
35
  ```
31
36
 
32
37
  ### Server
33
38
 
34
- Here a simple module for running a socket.io server that runs SendScript programs.
39
+ Here a socket.io server that runs SendScript programs.
35
40
 
36
41
  ```js cat - > ./example/server.socket.io.mjs
37
42
  // ./example/server.socket.io.mjs
@@ -66,7 +71,7 @@ Now for a client that sends a program to the server.
66
71
  // ./example/client.socket.io.mjs
67
72
 
68
73
  import socketClient from 'socket.io-client'
69
- import dsl from '../dsl.mjs'
74
+ import api from '../api.mjs'
70
75
 
71
76
  const port = process.env.PORT || 3000
72
77
  const client = socketClient(`http://localhost:${port}`)
@@ -81,10 +86,10 @@ const exec = program => {
81
86
  })
82
87
  }
83
88
 
84
- const { add } = dsl(['add'], exec)
89
+ const { add, square } = api(['add', 'square'], exec)
85
90
 
86
91
  console.log(
87
- await add(1, add(add(2, 3), 4))
92
+ await square(add(1, add(add(2, 3), 4)))
88
93
  )
89
94
 
90
95
  process.exit(0)
@@ -104,28 +109,28 @@ pkill sendscript
104
109
 
105
110
  ## Reference
106
111
 
107
- SendScript is essentially a way to serialize a program to then send over the wire
108
- and execute it somewhere else.
112
+ SendScript is essentially a way to serialize a program to then send over the
113
+ wire and execute it somewhere else.
109
114
 
110
115
  We only have two modules. One that helps you write programs that can be sent
111
116
  over the wire and another for running that program.
112
117
 
113
- ### `sendscript/dsl.mjs`
118
+ ### `sendscript/api.mjs`
114
119
 
115
- The dsl module exports a function that takes two arguments.
120
+ The api module exports a function that takes two arguments.
116
121
 
117
122
  1. The schema, which represents the values that are available.
118
123
  2. The function that will be called with the serializable version of the
119
124
  program.
120
125
 
121
126
  It returns an object that contains functions which are defined in the schema.
122
- These functions are a JavaScript DSL for writing programs that can be sent to
127
+ These functions are a JavaScript API for writing programs that can be sent to
123
128
  a server.
124
129
 
125
130
  ```js
126
- import dsl from './dsl.mjs'
131
+ import api from './api.mjs'
127
132
 
128
- const { add, subtract } = dsl(
133
+ const { add, subtract } = api(
129
134
  ['add', 'subtract'],
130
135
  serializableProgram => sendSomewhereToBeExecuted(serializableProgram)
131
136
  )
@@ -141,7 +146,7 @@ soon as await or `.then` is used.
141
146
  > Notice that you do not have to await the subtract call. You only need to
142
147
  > await when you want to execute the program.
143
148
 
144
- This DSL is composable and wrappable.
149
+ This API is composable and wrappable.
145
150
 
146
151
  ### `sendscript/exec.mjs`
147
152
 
@@ -158,8 +163,8 @@ exec({
158
163
 
159
164
  The array you see here is the LISP that SendScript uses to represent programs.
160
165
 
161
- You could use SendScript without knowing the details of how the LISP works. It is an
162
- implementation detail and might change over time.
166
+ You could use SendScript without knowing the details of how the LISP works. It
167
+ is an implementation detail and might change over time.
163
168
 
164
169
  ## Tests
165
170
 
package/api.mjs ADDED
@@ -0,0 +1,32 @@
1
+ import promiseOnly from './promise-only.mjs'
2
+
3
+ const symbol = Symbol('api')
4
+ const isNonAPI = v => v?.[symbol] !== symbol
5
+ const promiseOnlyNonAPI = promiseOnly(isNonAPI)
6
+
7
+ export default function api (schema, call) {
8
+ return schema.reduce((api, name) => {
9
+ const then = (program) => (resolve, reject) =>
10
+ Promise.resolve(call(program)).then(resolve, reject)
11
+
12
+ const fn = (...args) => ({
13
+ [symbol]: symbol,
14
+ toJSON () {
15
+ return [fn, ...args]
16
+ },
17
+ async then (resolve, reject) {
18
+ return then(await promiseOnlyNonAPI([
19
+ fn, ...args
20
+ ]))(resolve, reject)
21
+ }
22
+ })
23
+
24
+ fn.toJSON = () => ['ref', name]
25
+ fn.then = then(fn)
26
+ fn[symbol] = symbol
27
+
28
+ api[name] = fn
29
+
30
+ return api
31
+ }, {})
32
+ }
@@ -1,10 +1,10 @@
1
1
  import { test } from 'tap'
2
- import dsl from './dsl.mjs'
2
+ import api from './api.mjs'
3
3
 
4
4
  test('return a constant value', async t => {
5
5
  t.plan(1)
6
6
 
7
- const { constant } = dsl(['constant'], v => {
7
+ const { constant } = api(['constant'], v => {
8
8
  t.equal(JSON.stringify(v), '["ref","constant"]')
9
9
  })
10
10
 
@@ -14,7 +14,7 @@ test('return a constant value', async t => {
14
14
  test('use function calls as arguments', async t => {
15
15
  t.plan(4)
16
16
 
17
- const { add } = dsl(['add'], b => {
17
+ const { add } = api(['add'], b => {
18
18
  t.equal(JSON.stringify(awaited), JSON.stringify(b))
19
19
  return 'done'
20
20
  })
@@ -1,7 +1,7 @@
1
1
  // ./example/client.socket.io.mjs
2
2
 
3
3
  import socketClient from 'socket.io-client'
4
- import dsl from '../dsl.mjs'
4
+ import api from '../api.mjs'
5
5
 
6
6
  const port = process.env.PORT || 3000
7
7
  const client = socketClient(`http://localhost:${port}`)
@@ -16,10 +16,10 @@ const exec = program => {
16
16
  })
17
17
  }
18
18
 
19
- const { add } = dsl(['add'], exec)
19
+ const { add, square } = api(['add', 'square'], exec)
20
20
 
21
21
  console.log(
22
- await add(1, add(add(2, 3), 4))
22
+ await square(add(1, add(add(2, 3), 4)))
23
23
  )
24
24
 
25
25
  process.exit(0)
package/example/math.mjs CHANGED
@@ -1,3 +1,4 @@
1
1
  // ./example/math.mjs
2
2
 
3
3
  export const add = (a, b) => a + b
4
+ export const square = a => a * a
package/exec.test.mjs CHANGED
@@ -108,3 +108,18 @@ test('should reject with the error of the called function', async t => {
108
108
 
109
109
  t.end()
110
110
  })
111
+
112
+ test('should not exec expressions in an object', async t => {
113
+ const env = {
114
+ throws () {
115
+ throw new Error('Should not have been called.')
116
+ }
117
+ }
118
+
119
+ const result = await exec(env, { quoted: ['throws'] })
120
+
121
+ t.same(result, {
122
+ quoted: ['throws']
123
+ })
124
+ t.end()
125
+ })
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sendscript",
3
- "version": "0.0.0",
3
+ "version": "0.0.2",
4
4
  "description": "Blur the line between server and client code.",
5
5
  "module": true,
6
6
  "main": "index.mjs",
@@ -11,7 +11,7 @@
11
11
  "scripts": {
12
12
  "test": "tap *.test.mjs --no-cov",
13
13
  "version": "npm run docs && git add *.md",
14
- "docs": "markatzea README.mz | tee README.md"
14
+ "docs": "markatzea README.mz | tee README.md && npx markdown-toc -i README.md"
15
15
  },
16
16
  "author": "Bas Huis",
17
17
  "license": "MIT",
@@ -0,0 +1,13 @@
1
+ import curry from './curry.mjs'
2
+
3
+ const promiseOnly = curry(function promiseOnly (when, array) {
4
+ return array.reduce(async (asyncAcc, item) => {
5
+ const acc = await asyncAcc
6
+
7
+ acc.push(when(item) ? await item : item)
8
+
9
+ return acc
10
+ }, [])
11
+ })
12
+
13
+ export default promiseOnly
package/dsl.mjs DELETED
@@ -1,40 +0,0 @@
1
- const symbol = Symbol('dsl')
2
-
3
- // Only await values that are not part of the dsl.
4
- const promiseAllNonDSL = async values => values.reduce(async (_acc, value) => {
5
- const acc = await _acc
6
-
7
- if (value[symbol] === symbol) {
8
- acc.push(value)
9
- } else {
10
- acc.push(await value)
11
- }
12
-
13
- return acc
14
- }, [])
15
-
16
- export default function dsl (schema, call) {
17
- return schema.reduce((api, name) => {
18
- const then = (program) => (resolve, reject) =>
19
- Promise.resolve(call(program)).then(resolve, reject)
20
-
21
- const fn = (...args) => {
22
- // Only await non dsl values
23
- const v = [fn, ...args]
24
-
25
- v[symbol] = symbol
26
- v.then = async (...thenArgs) => {
27
- return then(await promiseAllNonDSL(v))(...thenArgs)
28
- }
29
- return v
30
- }
31
-
32
- fn.toJSON = () => ['ref', name]
33
- fn.then = then(fn)
34
- fn[symbol] = symbol
35
-
36
- api[name] = fn
37
-
38
- return api
39
- }, {})
40
- }