@rdfc/js-runner 3.0.2 → 3.1.0-alpha.1

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/README.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # JavaScript runner for RDF-Connect
2
2
 
3
+ [![Build and tests with Node.js](https://github.com/rdf-connect/js-runner/actions/workflows/build-test.yml/badge.svg)](https://github.com/rdf-connect/js-runner/actions/workflows/build-test.yml) [![npm](https://img.shields.io/npm/v/@rdfc/js-runner.svg?style=popout)](https://npmjs.com/package/@rdfc/js-runner)
4
+
5
+ This package provides a JavaScript runner implementation for RDF-Connect, which allows you to run JavaScript/TypeScript processors in your [RDF-Connect](https://github.com/rdf-connect/rdf-connect) pipeline.
6
+
3
7
  ## Usage
4
8
 
5
9
  To use the JavaScript (Node or Bun) runner for RDF-Connect, you need to have a pipeline configuration that includes JavaScript/TypeScript processors.
@@ -1,5 +1,5 @@
1
1
  import { describe, expect, test, vi } from 'vitest'
2
- import { StreamMsgMock } from '../src/testUtils'
2
+ import { StreamMsgMock, channel, createRunner } from '../src/testUtils'
3
3
  import { WriterInstance } from '../src/writer'
4
4
  import { FromRunner, StreamIdentify } from '@rdfc/proto'
5
5
  import { createLogger, transports } from 'winston'
@@ -109,6 +109,8 @@ describe('Writer', async () => {
109
109
 
110
110
  await writer.close()
111
111
 
112
+ expect(writer.canceled).toBe(false)
113
+
112
114
  expect(msgs.length).toBe(1)
113
115
  expect(msgs.map((x) => x.close!.channel)).toEqual([uri])
114
116
 
@@ -150,4 +152,67 @@ describe('Writer', async () => {
150
152
  'world',
151
153
  ])
152
154
  })
155
+
156
+ test('is marked canceled when connected reader cancels', async () => {
157
+ const runner = createRunner()
158
+ const [writer, reader] = channel(runner, 'cancel-channel')
159
+
160
+ await reader.cancel()
161
+
162
+ expect(writer.canceled).toBe(true)
163
+ await expect(writer.string('hello')).rejects.toThrow(/canceled/i)
164
+ })
165
+
166
+ test('emits a cancel event when connected reader cancels', async () => {
167
+ const runner = createRunner()
168
+ const [writer, reader] = channel(runner, 'cancel-listener-channel')
169
+ const onCancel = vi.fn()
170
+
171
+ writer.on('cancel', onCancel)
172
+ await reader.cancel()
173
+
174
+ expect(onCancel).toBeCalledTimes(1)
175
+ })
176
+
177
+ test('does not emit a cancel event on a local close', async () => {
178
+ const uri = 'someUri'
179
+ const runner = 'myRunner'
180
+ const client = new StreamMsgMock(() => 1)
181
+ const write = async (_msg: FromRunner) => undefined
182
+ const writer = new WriterInstance(uri, client as any, write, runner, logger)
183
+ const onCancel = vi.fn()
184
+
185
+ writer.on('cancel', onCancel)
186
+ await writer.close()
187
+
188
+ expect(onCancel).not.toBeCalled()
189
+ })
190
+
191
+ test('throws when writing to a canceled writer', async () => {
192
+ const uri = 'someUri'
193
+ const runner = 'myRunner'
194
+ const client = new StreamMsgMock(() => 1)
195
+ const write = async (_msg: FromRunner) => undefined
196
+ const writer = new WriterInstance(uri, client as any, write, runner, logger)
197
+
198
+ await writer.close(true)
199
+
200
+ expect(writer.canceled).toBe(true)
201
+ await expect(writer.buffer(encoder.encode('x'))).rejects.toThrow(
202
+ /canceled/i,
203
+ )
204
+ })
205
+
206
+ test('rejects in-flight writes when reader cancels', async () => {
207
+ const runner = createRunner()
208
+ const [writer, reader] = channel(runner, 'cancel-in-flight')
209
+
210
+ // Register a reader consumer without draining it so the writer waits for processed.
211
+ reader.strings()
212
+
213
+ const pendingWrite = writer.string('hello')
214
+ await reader.cancel()
215
+
216
+ await expect(pendingWrite).rejects.toThrow(/canceled/i)
217
+ })
153
218
  })
@@ -70,12 +70,11 @@ describe('EchoProcessor', () => {
70
70
 
71
71
  const msgs: string[] = []
72
72
 
73
- ; (async () => {
74
- for await (const m of outputReader.strings()) {
75
- msgs.push(m)
76
- }
77
- })()
78
-
73
+ ;(async () => {
74
+ for await (const m of outputReader.strings()) {
75
+ msgs.push(m)
76
+ }
77
+ })()
79
78
 
80
79
  await inputWriter.string('Hello')
81
80
  expect(msgs).toEqual(['Hello'])
@@ -107,13 +106,13 @@ describe('EchoProcessor', () => {
107
106
 
108
107
  const msgs: string[] = []
109
108
 
110
- ; (async () => {
111
- for await (const m of outputReader.strings()) {
112
- msgs.push(m)
113
- }
114
- })()
109
+ ;(async () => {
110
+ for await (const m of outputReader.strings()) {
111
+ msgs.push(m)
112
+ }
113
+ })()
115
114
 
116
- const gen = async function*() {
115
+ const gen = async function* () {
117
116
  yield encoder.encode('Hello')
118
117
  yield encoder.encode('World')
119
118
  }