@alt-javascript/camel-lite-component-file 1.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/README.md +67 -0
- package/package.json +41 -0
- package/src/FileComponent.js +19 -0
- package/src/FileConsumer.js +81 -0
- package/src/FileEndpoint.js +43 -0
- package/src/FileProducer.js +43 -0
- package/src/index.js +7 -0
- package/test/file.test.js +202 -0
package/README.md
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
[](https://opensource.org/licenses/MIT)
|
|
2
|
+
|
|
3
|
+
## What
|
|
4
|
+
|
|
5
|
+
File read (consumer: polls a directory) and write (producer: writes exchange body to a file). Supports configurable file name, character encoding, and auto-delete after read.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```sh
|
|
10
|
+
npm install camel-lite-component-file
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## URI Syntax
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
file:/absolute/path[?fileName=out.txt&charset=utf8&delete=false]
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
| Parameter | Default | Description |
|
|
20
|
+
|------------|-------------|-------------|
|
|
21
|
+
| `fileName` | *(auto)* | Output file name for producers. Consumers ignore this; all files in the directory are read. |
|
|
22
|
+
| `charset` | `utf8` | Character encoding for reading/writing file content. |
|
|
23
|
+
| `delete` | `false` | Consumer only: delete the source file after it has been successfully read. |
|
|
24
|
+
|
|
25
|
+
## Usage
|
|
26
|
+
|
|
27
|
+
**Producer — write exchange body to a file:**
|
|
28
|
+
|
|
29
|
+
```js
|
|
30
|
+
import { CamelContext } from 'camel-lite-core';
|
|
31
|
+
import { FileComponent } from 'camel-lite-component-file';
|
|
32
|
+
|
|
33
|
+
const context = new CamelContext();
|
|
34
|
+
context.addComponent('file', new FileComponent());
|
|
35
|
+
|
|
36
|
+
context.addRoutes({
|
|
37
|
+
configure(ctx) {
|
|
38
|
+
ctx.from('direct:writeFile')
|
|
39
|
+
.to('file:/tmp/output?fileName=result.txt&charset=utf8');
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
|
|
43
|
+
await context.start();
|
|
44
|
+
|
|
45
|
+
const template = context.createProducerTemplate();
|
|
46
|
+
await template.sendBody('direct:writeFile', 'Hello, file!');
|
|
47
|
+
|
|
48
|
+
await context.stop();
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
**Consumer — read files from a directory:**
|
|
52
|
+
|
|
53
|
+
```js
|
|
54
|
+
context.addRoutes({
|
|
55
|
+
configure(ctx) {
|
|
56
|
+
ctx.from('file:/tmp/inbox?delete=true')
|
|
57
|
+
.process(exchange => {
|
|
58
|
+
console.log('File content:', exchange.in.body);
|
|
59
|
+
console.log('File name:', exchange.in.getHeader('CamelFileName'));
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## See Also
|
|
66
|
+
|
|
67
|
+
[camel-lite — root README](../../README.md)
|
package/package.json
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@alt-javascript/camel-lite-component-file",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"exports": {
|
|
6
|
+
".": "./src/index.js"
|
|
7
|
+
},
|
|
8
|
+
"dependencies": {
|
|
9
|
+
"@alt-javascript/logger": "^3.0.7",
|
|
10
|
+
"@alt-javascript/config": "^3.0.7",
|
|
11
|
+
"@alt-javascript/common": "^3.0.7",
|
|
12
|
+
"@alt-javascript/camel-lite-core": "1.0.2"
|
|
13
|
+
},
|
|
14
|
+
"scripts": {
|
|
15
|
+
"test": "node --test"
|
|
16
|
+
},
|
|
17
|
+
"repository": {
|
|
18
|
+
"type": "git",
|
|
19
|
+
"url": "https://github.com/alt-javascript/camel-lite"
|
|
20
|
+
},
|
|
21
|
+
"author": "Craig Parravicini",
|
|
22
|
+
"contributors": [
|
|
23
|
+
"Claude (Anthropic)",
|
|
24
|
+
"Apache Camel — design inspiration and pattern source"
|
|
25
|
+
],
|
|
26
|
+
"keywords": [
|
|
27
|
+
"alt-javascript",
|
|
28
|
+
"camel",
|
|
29
|
+
"camel-lite",
|
|
30
|
+
"eai",
|
|
31
|
+
"eip",
|
|
32
|
+
"integration",
|
|
33
|
+
"file",
|
|
34
|
+
"io",
|
|
35
|
+
"component"
|
|
36
|
+
],
|
|
37
|
+
"publishConfig": {
|
|
38
|
+
"registry": "https://registry.npmjs.org/",
|
|
39
|
+
"access": "public"
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Component } from '@alt-javascript/camel-lite-core';
|
|
2
|
+
import FileEndpoint from './FileEndpoint.js';
|
|
3
|
+
|
|
4
|
+
class FileComponent extends Component {
|
|
5
|
+
// Endpoint cache — same path returns same endpoint
|
|
6
|
+
#endpoints = new Map();
|
|
7
|
+
|
|
8
|
+
createEndpoint(uri, remaining, parameters, context) {
|
|
9
|
+
if (this.#endpoints.has(uri)) {
|
|
10
|
+
return this.#endpoints.get(uri);
|
|
11
|
+
}
|
|
12
|
+
const endpoint = new FileEndpoint(uri, remaining, parameters, context);
|
|
13
|
+
this.#endpoints.set(uri, endpoint);
|
|
14
|
+
return endpoint;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export { FileComponent };
|
|
19
|
+
export default FileComponent;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import { Consumer, Exchange } from '@alt-javascript/camel-lite-core';
|
|
2
|
+
import { LoggerFactory } from '@alt-javascript/logger';
|
|
3
|
+
import { readdir, readFile, mkdir, rename } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const log = LoggerFactory.getLogger('@alt-javascript/camel-lite/FileConsumer');
|
|
7
|
+
|
|
8
|
+
class FileConsumer extends Consumer {
|
|
9
|
+
#uri;
|
|
10
|
+
#context;
|
|
11
|
+
#dir;
|
|
12
|
+
#noop;
|
|
13
|
+
|
|
14
|
+
constructor(uri, context, dir, noop = false) {
|
|
15
|
+
super();
|
|
16
|
+
this.#uri = uri;
|
|
17
|
+
this.#context = context;
|
|
18
|
+
this.#dir = dir;
|
|
19
|
+
this.#noop = noop;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
get uri() { return this.#uri; }
|
|
23
|
+
|
|
24
|
+
async start() {
|
|
25
|
+
this.#context.registerConsumer(this.#uri, this);
|
|
26
|
+
log.info(`File consumer started: ${this.#dir}`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async stop() {
|
|
30
|
+
this.#context.registerConsumer(this.#uri, null);
|
|
31
|
+
log.info(`File consumer stopped: ${this.#dir}`);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* One-shot poll: read all non-hidden files from the directory.
|
|
36
|
+
* Returns an array of Exchange objects, one per file.
|
|
37
|
+
* Files are moved to dir/.done/ after reading unless noop=true.
|
|
38
|
+
*/
|
|
39
|
+
async poll() {
|
|
40
|
+
log.info(`Polling: ${this.#dir}`);
|
|
41
|
+
|
|
42
|
+
let entries;
|
|
43
|
+
try {
|
|
44
|
+
entries = await readdir(this.#dir, { withFileTypes: true });
|
|
45
|
+
} catch {
|
|
46
|
+
// Directory does not exist yet — return empty
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const files = entries.filter(
|
|
51
|
+
e => e.isFile() && !e.name.startsWith('.')
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
const exchanges = [];
|
|
55
|
+
|
|
56
|
+
for (const file of files) {
|
|
57
|
+
const filePath = join(this.#dir, file.name);
|
|
58
|
+
const content = await readFile(filePath, 'utf8');
|
|
59
|
+
log.debug(`Read: ${file.name}`);
|
|
60
|
+
|
|
61
|
+
const exchange = new Exchange();
|
|
62
|
+
exchange.in.body = content;
|
|
63
|
+
exchange.in.setHeader('CamelFileName', file.name);
|
|
64
|
+
exchange.in.setHeader('CamelFilePath', filePath);
|
|
65
|
+
|
|
66
|
+
if (!this.#noop) {
|
|
67
|
+
const doneDir = join(this.#dir, '.done');
|
|
68
|
+
await mkdir(doneDir, { recursive: true });
|
|
69
|
+
await rename(filePath, join(doneDir, file.name));
|
|
70
|
+
log.debug(`Moved to .done: ${file.name}`);
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
exchanges.push(exchange);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return exchanges;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
export { FileConsumer };
|
|
81
|
+
export default FileConsumer;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Endpoint } from '@alt-javascript/camel-lite-core';
|
|
2
|
+
import FileProducer from './FileProducer.js';
|
|
3
|
+
import FileConsumer from './FileConsumer.js';
|
|
4
|
+
|
|
5
|
+
class FileEndpoint extends Endpoint {
|
|
6
|
+
#uri;
|
|
7
|
+
#dir;
|
|
8
|
+
#fileName;
|
|
9
|
+
#noop;
|
|
10
|
+
#context;
|
|
11
|
+
|
|
12
|
+
constructor(uri, remaining, parameters, context) {
|
|
13
|
+
super();
|
|
14
|
+
this.#uri = uri;
|
|
15
|
+
this.#context = context;
|
|
16
|
+
|
|
17
|
+
// remaining is the directory path (everything after 'file:' and before '?')
|
|
18
|
+
this.#dir = remaining;
|
|
19
|
+
|
|
20
|
+
const params = parameters instanceof URLSearchParams
|
|
21
|
+
? parameters
|
|
22
|
+
: new URLSearchParams(typeof parameters === 'string' ? parameters : '');
|
|
23
|
+
|
|
24
|
+
this.#fileName = params.get('fileName') ?? null;
|
|
25
|
+
this.#noop = params.get('noop') === 'true';
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
get uri() { return this.#uri; }
|
|
29
|
+
get dir() { return this.#dir; }
|
|
30
|
+
get fileName() { return this.#fileName; }
|
|
31
|
+
get noop() { return this.#noop; }
|
|
32
|
+
|
|
33
|
+
createProducer() {
|
|
34
|
+
return new FileProducer(this.#dir, this.#fileName);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
createConsumer(pipeline) {
|
|
38
|
+
return new FileConsumer(this.#uri, this.#context, this.#dir, this.#noop);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { FileEndpoint };
|
|
43
|
+
export default FileEndpoint;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Producer } from '@alt-javascript/camel-lite-core';
|
|
2
|
+
import { LoggerFactory } from '@alt-javascript/logger';
|
|
3
|
+
import { writeFile, mkdir } from 'node:fs/promises';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
|
|
6
|
+
const log = LoggerFactory.getLogger('@alt-javascript/camel-lite/FileProducer');
|
|
7
|
+
|
|
8
|
+
class FileProducer extends Producer {
|
|
9
|
+
#dir;
|
|
10
|
+
#fileName;
|
|
11
|
+
|
|
12
|
+
constructor(dir, fileName = null) {
|
|
13
|
+
super();
|
|
14
|
+
this.#dir = dir;
|
|
15
|
+
this.#fileName = fileName;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
get dir() { return this.#dir; }
|
|
19
|
+
get fileName() { return this.#fileName; }
|
|
20
|
+
|
|
21
|
+
async send(exchange) {
|
|
22
|
+
// Resolve file name: CamelFileName header > constructor param > messageId.txt
|
|
23
|
+
const name = exchange.in.getHeader('CamelFileName')
|
|
24
|
+
?? this.#fileName
|
|
25
|
+
?? (exchange.in.messageId + '.txt');
|
|
26
|
+
|
|
27
|
+
const filePath = join(this.#dir, name);
|
|
28
|
+
await mkdir(this.#dir, { recursive: true });
|
|
29
|
+
|
|
30
|
+
const body = exchange.in.body ?? '';
|
|
31
|
+
const content = typeof body === 'string' ? body : JSON.stringify(body);
|
|
32
|
+
|
|
33
|
+
await writeFile(filePath, content, 'utf8');
|
|
34
|
+
log.info(`Written: ${filePath}`);
|
|
35
|
+
|
|
36
|
+
// Inform downstream steps of the written path
|
|
37
|
+
exchange.out.setHeader('CamelFileName', name);
|
|
38
|
+
exchange.out.setHeader('CamelFilePath', filePath);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export { FileProducer };
|
|
43
|
+
export default FileProducer;
|
package/src/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export { FileComponent } from './FileComponent.js';
|
|
2
|
+
export { FileEndpoint } from './FileEndpoint.js';
|
|
3
|
+
export { FileProducer } from './FileProducer.js';
|
|
4
|
+
export { FileConsumer } from './FileConsumer.js';
|
|
5
|
+
|
|
6
|
+
import FileComponent from './FileComponent.js';
|
|
7
|
+
export default FileComponent;
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import { describe, it, after } from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { tmpdir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
5
|
+
import { randomUUID } from 'node:crypto';
|
|
6
|
+
import { readFile, mkdir, writeFile, rm, access } from 'node:fs/promises';
|
|
7
|
+
import { CamelContext, Exchange, Component } from '@alt-javascript/camel-lite-core';
|
|
8
|
+
import { FileComponent, FileEndpoint, FileProducer, FileConsumer } from '@alt-javascript/camel-lite-component-file';
|
|
9
|
+
|
|
10
|
+
function makeTmpDir() {
|
|
11
|
+
return join(tmpdir(), 'camel-lite-file-test-' + randomUUID());
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
describe('FileProducer', () => {
|
|
15
|
+
it('writes string body to disk with default filename (messageId.txt)', async () => {
|
|
16
|
+
const dir = makeTmpDir();
|
|
17
|
+
const producer = new FileProducer(dir);
|
|
18
|
+
const exchange = new Exchange();
|
|
19
|
+
exchange.in.body = 'hello file';
|
|
20
|
+
|
|
21
|
+
await producer.send(exchange);
|
|
22
|
+
|
|
23
|
+
const filePath = join(dir, exchange.in.messageId + '.txt');
|
|
24
|
+
const content = await readFile(filePath, 'utf8');
|
|
25
|
+
assert.equal(content, 'hello file');
|
|
26
|
+
await rm(dir, { recursive: true, force: true });
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('uses CamelFileName header when set', async () => {
|
|
30
|
+
const dir = makeTmpDir();
|
|
31
|
+
const producer = new FileProducer(dir);
|
|
32
|
+
const exchange = new Exchange();
|
|
33
|
+
exchange.in.body = 'named content';
|
|
34
|
+
exchange.in.setHeader('CamelFileName', 'custom.txt');
|
|
35
|
+
|
|
36
|
+
await producer.send(exchange);
|
|
37
|
+
|
|
38
|
+
const content = await readFile(join(dir, 'custom.txt'), 'utf8');
|
|
39
|
+
assert.equal(content, 'named content');
|
|
40
|
+
assert.equal(exchange.out.getHeader('CamelFileName'), 'custom.txt');
|
|
41
|
+
await rm(dir, { recursive: true, force: true });
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
it('uses fileName constructor param as fallback', async () => {
|
|
45
|
+
const dir = makeTmpDir();
|
|
46
|
+
const producer = new FileProducer(dir, 'fixed.txt');
|
|
47
|
+
const exchange = new Exchange();
|
|
48
|
+
exchange.in.body = 'fixed name';
|
|
49
|
+
|
|
50
|
+
await producer.send(exchange);
|
|
51
|
+
|
|
52
|
+
const content = await readFile(join(dir, 'fixed.txt'), 'utf8');
|
|
53
|
+
assert.equal(content, 'fixed name');
|
|
54
|
+
await rm(dir, { recursive: true, force: true });
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
it('serialises non-string body as JSON', async () => {
|
|
58
|
+
const dir = makeTmpDir();
|
|
59
|
+
const producer = new FileProducer(dir, 'data.json');
|
|
60
|
+
const exchange = new Exchange();
|
|
61
|
+
exchange.in.body = { key: 'value', n: 42 };
|
|
62
|
+
|
|
63
|
+
await producer.send(exchange);
|
|
64
|
+
|
|
65
|
+
const content = await readFile(join(dir, 'data.json'), 'utf8');
|
|
66
|
+
assert.deepEqual(JSON.parse(content), { key: 'value', n: 42 });
|
|
67
|
+
await rm(dir, { recursive: true, force: true });
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
it('creates directory if it does not exist', async () => {
|
|
71
|
+
const dir = join(makeTmpDir(), 'nested', 'path');
|
|
72
|
+
const producer = new FileProducer(dir, 'out.txt');
|
|
73
|
+
const exchange = new Exchange();
|
|
74
|
+
exchange.in.body = 'nested';
|
|
75
|
+
|
|
76
|
+
await producer.send(exchange);
|
|
77
|
+
|
|
78
|
+
const content = await readFile(join(dir, 'out.txt'), 'utf8');
|
|
79
|
+
assert.equal(content, 'nested');
|
|
80
|
+
await rm(join(dir, '..', '..'), { recursive: true, force: true });
|
|
81
|
+
});
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
describe('FileConsumer', () => {
|
|
85
|
+
it('poll() returns one exchange per file with correct body', async () => {
|
|
86
|
+
const dir = makeTmpDir();
|
|
87
|
+
await mkdir(dir, { recursive: true });
|
|
88
|
+
await writeFile(join(dir, 'a.txt'), 'body-a', 'utf8');
|
|
89
|
+
await writeFile(join(dir, 'b.txt'), 'body-b', 'utf8');
|
|
90
|
+
await writeFile(join(dir, 'c.txt'), 'body-c', 'utf8');
|
|
91
|
+
|
|
92
|
+
const ctx = new CamelContext();
|
|
93
|
+
const consumer = new FileConsumer('file:' + dir, ctx, dir, true); // noop=true
|
|
94
|
+
await consumer.start();
|
|
95
|
+
|
|
96
|
+
const exchanges = await consumer.poll();
|
|
97
|
+
assert.equal(exchanges.length, 3);
|
|
98
|
+
const bodies = exchanges.map(e => e.in.body).sort();
|
|
99
|
+
assert.deepEqual(bodies, ['body-a', 'body-b', 'body-c']);
|
|
100
|
+
exchanges.forEach(e => {
|
|
101
|
+
assert.ok(e.in.getHeader('CamelFileName'), 'CamelFileName header set');
|
|
102
|
+
assert.ok(e.in.getHeader('CamelFilePath'), 'CamelFilePath header set');
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
await consumer.stop();
|
|
106
|
+
await rm(dir, { recursive: true, force: true });
|
|
107
|
+
});
|
|
108
|
+
|
|
109
|
+
it('poll() moves files to .done/ by default (noop=false)', async () => {
|
|
110
|
+
const dir = makeTmpDir();
|
|
111
|
+
await mkdir(dir, { recursive: true });
|
|
112
|
+
await writeFile(join(dir, 'move.txt'), 'content', 'utf8');
|
|
113
|
+
|
|
114
|
+
const ctx = new CamelContext();
|
|
115
|
+
const consumer = new FileConsumer('file:' + dir, ctx, dir, false);
|
|
116
|
+
await consumer.start();
|
|
117
|
+
|
|
118
|
+
const exchanges = await consumer.poll();
|
|
119
|
+
assert.equal(exchanges.length, 1);
|
|
120
|
+
|
|
121
|
+
// Original file should be gone
|
|
122
|
+
await assert.rejects(() => access(join(dir, 'move.txt')));
|
|
123
|
+
// File should be in .done/
|
|
124
|
+
const doneContent = await readFile(join(dir, '.done', 'move.txt'), 'utf8');
|
|
125
|
+
assert.equal(doneContent, 'content');
|
|
126
|
+
|
|
127
|
+
await consumer.stop();
|
|
128
|
+
await rm(dir, { recursive: true, force: true });
|
|
129
|
+
});
|
|
130
|
+
|
|
131
|
+
it('poll() noop=true: files remain in place', async () => {
|
|
132
|
+
const dir = makeTmpDir();
|
|
133
|
+
await mkdir(dir, { recursive: true });
|
|
134
|
+
await writeFile(join(dir, 'stay.txt'), 'stays', 'utf8');
|
|
135
|
+
|
|
136
|
+
const ctx = new CamelContext();
|
|
137
|
+
const consumer = new FileConsumer('file:' + dir, ctx, dir, true);
|
|
138
|
+
await consumer.start();
|
|
139
|
+
|
|
140
|
+
await consumer.poll();
|
|
141
|
+
|
|
142
|
+
// File should still be there
|
|
143
|
+
const content = await readFile(join(dir, 'stay.txt'), 'utf8');
|
|
144
|
+
assert.equal(content, 'stays');
|
|
145
|
+
|
|
146
|
+
await consumer.stop();
|
|
147
|
+
await rm(dir, { recursive: true, force: true });
|
|
148
|
+
});
|
|
149
|
+
|
|
150
|
+
it('poll() on empty dir returns []', async () => {
|
|
151
|
+
const dir = makeTmpDir();
|
|
152
|
+
await mkdir(dir, { recursive: true });
|
|
153
|
+
|
|
154
|
+
const ctx = new CamelContext();
|
|
155
|
+
const consumer = new FileConsumer('file:' + dir, ctx, dir, true);
|
|
156
|
+
await consumer.start();
|
|
157
|
+
|
|
158
|
+
const exchanges = await consumer.poll();
|
|
159
|
+
assert.equal(exchanges.length, 0);
|
|
160
|
+
|
|
161
|
+
await consumer.stop();
|
|
162
|
+
await rm(dir, { recursive: true, force: true });
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
it('poll() on non-existent dir returns []', async () => {
|
|
166
|
+
const dir = makeTmpDir(); // not created
|
|
167
|
+
const ctx = new CamelContext();
|
|
168
|
+
const consumer = new FileConsumer('file:' + dir, ctx, dir, true);
|
|
169
|
+
await consumer.start();
|
|
170
|
+
|
|
171
|
+
const exchanges = await consumer.poll();
|
|
172
|
+
assert.equal(exchanges.length, 0);
|
|
173
|
+
|
|
174
|
+
await consumer.stop();
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe('cross-package import integration', () => {
|
|
179
|
+
it('FileComponent is a subclass of Component', () => {
|
|
180
|
+
assert.ok(new FileComponent() instanceof Component);
|
|
181
|
+
});
|
|
182
|
+
|
|
183
|
+
it('FileComponent.createEndpoint returns FileEndpoint', () => {
|
|
184
|
+
const ctx = new CamelContext();
|
|
185
|
+
const comp = new FileComponent();
|
|
186
|
+
const ep = comp.createEndpoint('file:/tmp/test', '/tmp/test', new URLSearchParams(), ctx);
|
|
187
|
+
assert.ok(ep instanceof FileEndpoint);
|
|
188
|
+
assert.equal(ep.dir, '/tmp/test');
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
it('FileEndpoint.createProducer returns FileProducer', () => {
|
|
192
|
+
const ctx = new CamelContext();
|
|
193
|
+
const ep = new FileEndpoint('file:/tmp', '/tmp', new URLSearchParams(), ctx);
|
|
194
|
+
assert.ok(ep.createProducer() instanceof FileProducer);
|
|
195
|
+
});
|
|
196
|
+
|
|
197
|
+
it('FileEndpoint.createConsumer returns FileConsumer', () => {
|
|
198
|
+
const ctx = new CamelContext();
|
|
199
|
+
const ep = new FileEndpoint('file:/tmp', '/tmp', new URLSearchParams(), ctx);
|
|
200
|
+
assert.ok(ep.createConsumer(null) instanceof FileConsumer);
|
|
201
|
+
});
|
|
202
|
+
});
|