sendscript 0.1.0 → 0.1.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 CHANGED
@@ -4,8 +4,22 @@ 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
+ #### [v0.1.2](https://github.com/bas080/sendscript/compare/v0.1.1...v0.1.2)
8
+
9
+ - Update tap to 10.9.5 [`4e3ddcc`](https://github.com/bas080/sendscript/commit/4e3ddcca823ca64c52bc1966ac23a712480d6c4d)
10
+
11
+ #### [v0.1.1](https://github.com/bas080/sendscript/compare/v0.1.0...v0.1.1)
12
+
13
+ > 4 January 2024
14
+
15
+ - Add a json schema for the sendscript program [`2acf884`](https://github.com/bas080/sendscript/commit/2acf8848134e1ae175afc0af9c5f1e93c4039f8f)
16
+ - Document a way of using sendscript with typescript [`2683c28`](https://github.com/bas080/sendscript/commit/2683c2873b8c4833711cdb00c777792c0630954a)
17
+ - Improve naming of promise helper [`e177f39`](https://github.com/bas080/sendscript/commit/e177f39c740bc16864f1ed4fc90a6daa3321751f)
18
+
7
19
  #### [v0.1.0](https://github.com/bas080/sendscript/compare/v0.0.4...v0.1.0)
8
20
 
21
+ > 21 October 2023
22
+
9
23
  - Allow nesting arrays, calls and args [`48e5804`](https://github.com/bas080/sendscript/commit/48e5804891db0ee0ed8c274f20f81d49d6609a54)
10
24
 
11
25
  #### [v0.0.4](https://github.com/bas080/sendscript/compare/v0.0.3...v0.0.4)
package/README.md CHANGED
@@ -16,6 +16,7 @@ Write JS code that you can run on servers, browsers or other clients.
16
16
  - [Reference](#reference)
17
17
  * [`sendscript/api.mjs`](#sendscriptapimjs)
18
18
  * [`sendscript/exec.mjs`](#sendscriptexecmjs)
19
+ - [TypeScript](#typescript)
19
20
  - [Tests](#tests)
20
21
  - [Formatting](#formatting)
21
22
  - [Changelog](#changelog)
@@ -184,6 +185,44 @@ The array you see here is the LISP that SendScript uses to represent programs.
184
185
  You could use SendScript without knowing the details of how the LISP works. It
185
186
  is an implementation detail and might change over time.
186
187
 
188
+ ## TypeScript
189
+
190
+ There is a good use-case to write an environment module in TypeScript.
191
+
192
+ 1. Obviously the module would have the benefits that TypeScript offers when
193
+ coding.
194
+ 2. You can use tools like [typedoc][typedoc] to generate docs from your types to
195
+ share with consumers of your API.
196
+ 3. You can generate a .d.ts with `tsc --declaration` and use it to coerce your
197
+ client to adopt the modules type.
198
+
199
+ ```bash
200
+ # Create pretty docs for your module.
201
+ npx typedoc my-module.ts
202
+
203
+ # Create the .d.ts file for your module.
204
+ tsc --declaration
205
+ ```
206
+
207
+ Now we can use the `my-module.d.ts` file for the client API.
208
+
209
+ ```ts
210
+ import type * as MyModule from './my-module.d.ts'
211
+
212
+ import sendScriptApi from 'sendscript/api.mjs'
213
+
214
+ export default sendScriptApi([
215
+ fnOne,
216
+ fnTwo,
217
+ ], /* perform websocket request */) as typeof MyModule
218
+ ```
219
+
220
+ > [!NOTE]
221
+ > Although type coercion on the client side can improve the development
222
+ > experience, it does not represent the actual type.
223
+ > Values are likely subject to serialization and deserialization,
224
+ > particularly when interfacing with JSON formats.
225
+
187
226
  ## Tests
188
227
 
189
228
  Tests with 100% code coverage.
@@ -194,19 +233,19 @@ npm t -- report text-summary
194
233
  ```
195
234
  ```
196
235
 
197
- > sendscript@0.1.0 test
236
+ > sendscript@0.1.2 test
198
237
  > tap -R silent
199
238
 
200
239
 
201
- > sendscript@0.1.0 test
240
+ > sendscript@0.1.2 test
202
241
  > tap report text-summary
203
242
 
204
243
 
205
244
  =============================== Coverage summary ===============================
206
- Statements : 100% ( 92/92 )
245
+ Statements : 100% ( 98/98 )
207
246
  Branches : 100% ( 30/30 )
208
247
  Functions : 100% ( 10/10 )
209
- Lines : 100% ( 92/92 )
248
+ Lines : 100% ( 98/98 )
210
249
  ================================================================================
211
250
  ```
212
251
 
@@ -246,3 +285,4 @@ See the [LICENSE.txt][license] file for details.
246
285
  [socket.io]:https://socket.io/
247
286
  [changelog]:./CHANGELOG.md
248
287
  [auto-changelog]:https://www.npmjs.com/package/auto-changelog
288
+ [typedoc]:https://github.com/TypeStrong/typedoc
package/README.mz CHANGED
@@ -166,6 +166,44 @@ The array you see here is the LISP that SendScript uses to represent programs.
166
166
  You could use SendScript without knowing the details of how the LISP works. It
167
167
  is an implementation detail and might change over time.
168
168
 
169
+ ## TypeScript
170
+
171
+ There is a good use-case to write an environment module in TypeScript.
172
+
173
+ 1. Obviously the module would have the benefits that TypeScript offers when
174
+ coding.
175
+ 2. You can use tools like [typedoc][typedoc] to generate docs from your types to
176
+ share with consumers of your API.
177
+ 3. You can generate a .d.ts with `tsc --declaration` and use it to coerce your
178
+ client to adopt the modules type.
179
+
180
+ ```bash
181
+ # Create pretty docs for your module.
182
+ npx typedoc my-module.ts
183
+
184
+ # Create the .d.ts file for your module.
185
+ tsc --declaration
186
+ ```
187
+
188
+ Now we can use the `my-module.d.ts` file for the client API.
189
+
190
+ ```ts
191
+ import type * as MyModule from './my-module.d.ts'
192
+
193
+ import sendScriptApi from 'sendscript/api.mjs'
194
+
195
+ export default sendScriptApi([
196
+ fnOne,
197
+ fnTwo,
198
+ ], /* perform websocket request */) as typeof MyModule
199
+ ```
200
+
201
+ > [!NOTE]
202
+ > Although type coercion on the client side can improve the development
203
+ > experience, it does not represent the actual type.
204
+ > Values are likely subject to serialization and deserialization,
205
+ > particularly when interfacing with JSON formats.
206
+
169
207
  ## Tests
170
208
 
171
209
  Tests with 100% code coverage.
@@ -208,3 +246,4 @@ See the [LICENSE.txt][license] file for details.
208
246
  [socket.io]:https://socket.io/
209
247
  [changelog]:./CHANGELOG.md
210
248
  [auto-changelog]:https://www.npmjs.com/package/auto-changelog
249
+ [typedoc]:https://github.com/TypeStrong/typedoc
package/api.mjs CHANGED
@@ -1,22 +1,30 @@
1
- import promiseOnly from './promise-only.mjs'
1
+ import awaitWhen from './await-when.mjs'
2
2
 
3
3
  const symbol = Symbol('api')
4
- const isNonAPI = v => v?.[symbol] !== symbol
5
- const promiseOnlyNonAPI = promiseOnly(isNonAPI)
4
+ const isNotStub = v => v?.[symbol] !== symbol
5
+ const awaitWhenNotStub = awaitWhen(isNotStub)
6
6
 
7
+ /**
8
+ * Create stubs to be used to build the program.
9
+ *
10
+ * @param {string[]} schema - Names of stubs.
11
+ * @param {Function} call - Function to call when awaited.
12
+ *
13
+ * @return {Object} An object containing the named stubs.
14
+ */
7
15
  export default function api (schema, call) {
8
16
  return schema.reduce((api, name) => {
9
17
  const then = (program) => (resolve, reject) =>
10
18
  Promise.resolve(call(program)).then(resolve, reject)
11
19
 
12
20
  const fn = (...args) => {
13
- const toJSON = () => ['call', fn, ...args]
21
+ const toJSON = () => ['call', fn, args]
14
22
 
15
23
  return {
16
24
  [symbol]: symbol,
17
25
  toJSON,
18
26
  async then (resolve, reject) {
19
- return then(await promiseOnlyNonAPI(toJSON()))(resolve, reject)
27
+ return then(await awaitWhenNotStub(toJSON()))(resolve, reject)
20
28
  }
21
29
  }
22
30
  }
@@ -1,6 +1,6 @@
1
1
  import curry from './curry.mjs'
2
2
 
3
- const promiseOnly = curry(function promiseOnly (when, array) {
3
+ export default curry(function awaitWhen (when, array) {
4
4
  return array.reduce(async (asyncAcc, item) => {
5
5
  const acc = await asyncAcc
6
6
 
@@ -9,5 +9,3 @@ const promiseOnly = curry(function promiseOnly (when, array) {
9
9
  return acc
10
10
  }, [])
11
11
  })
12
-
13
- export default promiseOnly
package/exec.mjs CHANGED
@@ -13,9 +13,9 @@ const exec = curry(async (env, expression) => {
13
13
  const [operator, ...args] = expression
14
14
 
15
15
  if (operator === 'call') {
16
- const [fnName, ...fnArgs] = args
16
+ const [fnRef, fnArgs] = args
17
17
 
18
- const fn = await exec(env, fnName)
18
+ const fn = await exec(env, fnRef)
19
19
  return fn.apply(env, await exec(env, fnArgs))
20
20
  }
21
21
 
package/exec.test.mjs CHANGED
@@ -18,6 +18,11 @@ test('should evaluate basic expressions correctly', async (t) => {
18
18
  3
19
19
  )
20
20
 
21
+ t.strictSame(
22
+ await evaluate([]),
23
+ []
24
+ )
25
+
21
26
  t.strictSame(
22
27
  await evaluate(concat([1, 2], [[add(1, 2)]])),
23
28
  [1, 2, [3]]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sendscript",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Blur the line between server and client code.",
5
5
  "module": true,
6
6
  "main": "index.mjs",
package/schema.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "$schema": "http://json-schema.org/draft-07/schema#",
3
+ "title": "JSON S-expression Language Schema",
4
+ "description": "Schema for a custom JSON S-expression language.",
5
+ "definitions": {
6
+ "ref": {
7
+ "title": "Reference Operator",
8
+ "description": "A reference to a function or identifier.",
9
+ "type": "array",
10
+ "minItems": 2,
11
+ "maxItems": 2,
12
+ "items": [
13
+ { "enum": ["ref"], "title": "Operator", "description": "The operator type, representing a reference to a function or identifier." },
14
+ { "type": "string", "title": "Identifier", "description": "The identifier or function name." }
15
+ ]
16
+ },
17
+ "call": {
18
+ "title": "Call Operator",
19
+ "description": "A function call.",
20
+ "type": "array",
21
+ "minItems": 2,
22
+ "maxItems": 3,
23
+ "items": [
24
+ { "const": "call", "title": "Operator", "description": "The operator type, representing a function call." },
25
+ { "$ref": "#/definitions/ref", "title": "Reference", "description": "The reference to a function or identifier." },
26
+ {
27
+ "type": "array",
28
+ "items": {
29
+ "$ref": "#"
30
+ },
31
+ "title": "Arguments",
32
+ "description": "The arguments passed to the function."
33
+ }
34
+ ]
35
+ }
36
+ },
37
+ "oneOf": [
38
+ { "$ref": "#/definitions/ref" },
39
+ { "$ref": "#/definitions/call" },
40
+ { "type": "number", "title": "Number", "description": "A JSON number." },
41
+ { "type": "string", "title": "String", "description": "A JSON string." },
42
+ { "type": "boolean", "title": "Boolean", "description": "A JSON boolean." },
43
+ { "type": "null", "title": "Null", "description": "A JSON null value." },
44
+ {
45
+ "title": "Object",
46
+ "description": "A generic JSON object with additional properties.",
47
+ "type": "object",
48
+ "additionalProperties": {
49
+ "$ref": "#"
50
+ }
51
+ }
52
+ ]
53
+ }