@t4h.framework/fs 0.6.0 → 0.8.0

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.
Files changed (78) hide show
  1. package/.ai/skills/framework-fs/SKILL.md +28 -7
  2. package/.ai/skills/framework-fs-split/SKILL.md +113 -18
  3. package/.ai/skills/framework-fs-write/SKILL.md +242 -0
  4. package/CHANGELOG.md +78 -0
  5. package/LICENSE +21 -0
  6. package/README.md +154 -7
  7. package/dist/FileSystemClaim.d.ts +1 -1
  8. package/dist/FileSystemClaim.d.ts.map +1 -1
  9. package/dist/FileSystemClaim.js.map +1 -1
  10. package/dist/activities/FileJoinActivity.d.ts +32 -12
  11. package/dist/activities/FileJoinActivity.d.ts.map +1 -1
  12. package/dist/activities/FileJoinActivity.js +21 -34
  13. package/dist/activities/FileJoinActivity.js.map +1 -1
  14. package/dist/activities/FileReadActivity.d.ts +22 -0
  15. package/dist/activities/FileReadActivity.d.ts.map +1 -0
  16. package/dist/activities/FileReadActivity.js +68 -0
  17. package/dist/activities/FileReadActivity.js.map +1 -0
  18. package/dist/activities/FileSplitActivity.d.ts +2 -1
  19. package/dist/activities/FileSplitActivity.d.ts.map +1 -1
  20. package/dist/activities/FileSplitActivity.js +1 -0
  21. package/dist/activities/FileSplitActivity.js.map +1 -1
  22. package/dist/activities/FileWriteActivity.d.ts +20 -0
  23. package/dist/activities/FileWriteActivity.d.ts.map +1 -0
  24. package/dist/activities/FileWriteActivity.js +26 -0
  25. package/dist/activities/FileWriteActivity.js.map +1 -0
  26. package/dist/constants/operations.d.ts +3 -0
  27. package/dist/constants/operations.d.ts.map +1 -0
  28. package/dist/constants/operations.js +18 -0
  29. package/dist/constants/operations.js.map +1 -0
  30. package/dist/fs.d.ts +2 -0
  31. package/dist/fs.d.ts.map +1 -1
  32. package/dist/fs.js +2 -0
  33. package/dist/fs.js.map +1 -1
  34. package/dist/helpers/CSV.d.ts +14 -0
  35. package/dist/helpers/CSV.d.ts.map +1 -0
  36. package/dist/helpers/CSV.js +44 -0
  37. package/dist/helpers/CSV.js.map +1 -0
  38. package/dist/helpers/byte-delimiter-scanner.d.ts +8 -1
  39. package/dist/helpers/byte-delimiter-scanner.d.ts.map +1 -1
  40. package/dist/helpers/byte-delimiter-scanner.js +26 -2
  41. package/dist/helpers/byte-delimiter-scanner.js.map +1 -1
  42. package/dist/tools/assert-where-serializable.d.ts +2 -0
  43. package/dist/tools/assert-where-serializable.d.ts.map +1 -0
  44. package/dist/tools/assert-where-serializable.js +19 -0
  45. package/dist/tools/assert-where-serializable.js.map +1 -0
  46. package/package.json +6 -3
  47. package/dist/ActivityFileSystemClaim.d.ts +0 -7
  48. package/dist/ActivityFileSystemClaim.d.ts.map +0 -1
  49. package/dist/ActivityFileSystemClaim.js +0 -3
  50. package/dist/ActivityFileSystemClaim.js.map +0 -1
  51. package/dist/activities/__tests__/FileJoinActivity.spec.d.ts +0 -2
  52. package/dist/activities/__tests__/FileJoinActivity.spec.d.ts.map +0 -1
  53. package/dist/activities/__tests__/FileJoinActivity.spec.js +0 -160
  54. package/dist/activities/__tests__/FileJoinActivity.spec.js.map +0 -1
  55. package/dist/activities/__tests__/FileSplitActivity.spec.d.ts +0 -2
  56. package/dist/activities/__tests__/FileSplitActivity.spec.d.ts.map +0 -1
  57. package/dist/activities/__tests__/FileSplitActivity.spec.js +0 -149
  58. package/dist/activities/__tests__/FileSplitActivity.spec.js.map +0 -1
  59. package/dist/helpers/__tests__/byte-delimiter-scanner.spec.d.ts +0 -2
  60. package/dist/helpers/__tests__/byte-delimiter-scanner.spec.d.ts.map +0 -1
  61. package/dist/helpers/__tests__/byte-delimiter-scanner.spec.js +0 -127
  62. package/dist/helpers/__tests__/byte-delimiter-scanner.spec.js.map +0 -1
  63. package/dist/helpers/__tests__/csv-reader.spec.d.ts +0 -2
  64. package/dist/helpers/__tests__/csv-reader.spec.d.ts.map +0 -1
  65. package/dist/helpers/__tests__/csv-reader.spec.js +0 -60
  66. package/dist/helpers/__tests__/csv-reader.spec.js.map +0 -1
  67. package/dist/helpers/csv-reader.d.ts +0 -8
  68. package/dist/helpers/csv-reader.d.ts.map +0 -1
  69. package/dist/helpers/csv-reader.js +0 -14
  70. package/dist/helpers/csv-reader.js.map +0 -1
  71. package/dist/helpers/parsers.d.ts +0 -9
  72. package/dist/helpers/parsers.d.ts.map +0 -1
  73. package/dist/helpers/parsers.js +0 -14
  74. package/dist/helpers/parsers.js.map +0 -1
  75. package/dist/testing/index.d.ts +0 -3
  76. package/dist/testing/index.d.ts.map +0 -1
  77. package/dist/testing/index.js +0 -32
  78. package/dist/testing/index.js.map +0 -1
package/README.md CHANGED
@@ -1,7 +1,10 @@
1
1
  # @t4h.framework/fs
2
2
 
3
- File system claim for reading and writing files within activities, and a file
4
- split activity that fans a large file out into one child workflow per slice.
3
+ File system claim for reading and writing files within activities, plus the
4
+ workflow-facing file activities: `split` fans a large file out into one child
5
+ workflow per slice, `join` folds the batch results back into a single file,
6
+ `read` brings a small byte window (a header, a trailer) into the workflow as a
7
+ string, and `write` turns content the workflow produced into a file.
5
8
 
6
9
  ## Claim
7
10
 
@@ -20,6 +23,7 @@ abstract class FileSystemClaim {
20
23
  public abstract write(
21
24
  path: string,
22
25
  readable: Readable | Buffer,
26
+ contentType?: string,
23
27
  ): Binary | Promise<Binary>
24
28
  public abstract read(path: string): Binary | Promise<Binary>
25
29
 
@@ -69,6 +73,74 @@ The runtime must supply a concrete implementation:
69
73
  { provide: FileSystemClaim, value: new LocalFileSystemClaimImpl() }
70
74
  ```
71
75
 
76
+ ## File read
77
+
78
+ ### read
79
+
80
+ Reads a byte window of a `Binary` into the workflow as a decoded string. The
81
+ output is recorded in the workflow history (replay never re-reads the file),
82
+ which is why reads are capped at 1 MiB: this is the primitive for headers,
83
+ trailers and single records — a data file flows through `split`, never through
84
+ `read`.
85
+
86
+ ```typescript
87
+ import { read } from '@t4h.framework/fs'
88
+
89
+ const header = await read(file, { range: { start: 0, end: 240 } })
90
+
91
+ const trailer = await read(file, {
92
+ range: { start: file.contentLength - 240, end: file.contentLength },
93
+ })
94
+ ```
95
+
96
+ Options: `range` (default: the whole binary, subject to the same cap) and
97
+ `encoding` (default `'utf8'`).
98
+
99
+ The activity tries `FileSystemClaim.slice` first — on a file-backed binary a
100
+ trailer read is a ranged download, whatever the file size. Binaries the claim
101
+ cannot slice (e.g. an SFTP reference) fall back to streaming: the stream is
102
+ consumed up to the window and destroyed as soon as it is filled, so a header
103
+ read pulls the first chunks only, whatever the file size. The one expensive
104
+ case is a trailing window over a non-sliceable binary — the stream must
105
+ traverse the whole file to reach it.
106
+
107
+ Reading a slice is relative to the slice: `read(slice, { range: { start: 0,
108
+ end: 10 } })` returns the first 10 bytes of the slice, not of the underlying
109
+ file — slice ranges compose.
110
+
111
+ ## File write
112
+
113
+ ### write
114
+
115
+ Stores content produced inside the workflow and returns its `Binary` — the only
116
+ supported way to obtain a `Binary` from a string or a `Buffer`:
117
+
118
+ ```typescript
119
+ import { write } from '@t4h.framework/fs'
120
+
121
+ const file = await write(JSON.stringify(state, null, 2), {
122
+ contentType: 'application/json',
123
+ })
124
+
125
+ await sftp.put('/out/state.json', file)
126
+ ```
127
+
128
+ Options: `contentType` (default: inferred from the filename, then
129
+ `application/octet-stream`), `filename` (default: the activity id) and
130
+ `encoding` for a string content (default `'utf8'`; a `Buffer` always travels as
131
+ base64).
132
+
133
+ **Never implement `Binary` in an App.** Passing a value to a primitive makes it
134
+ the input of a durable activity, and that input is serialized to storage before
135
+ the activity runs — a `Binary` holding bytes in memory has nothing to serialize
136
+ into, and the activity may run in another process after a replay. A hand-rolled
137
+ class can pass locally (the dev server keeps values in memory) and fail once
138
+ deployed.
139
+
140
+ `write` takes content already in workflow memory — a state file, a report, a
141
+ return file. To build a large file out of many records, use `split` + `join`,
142
+ which stream through storage.
143
+
72
144
  ## File split
73
145
 
74
146
  ### split
@@ -148,9 +220,10 @@ start of the next slice.
148
220
  await split(file, workflow, {
149
221
  delimiter: Split.line(), // required: where to cut
150
222
  every: 10_000, // cut only every N occurrences (groups records)
223
+ trim: { start: 241, end: 241 }, // bytes cut off each end before scanning
151
224
  skipEmpty: false, // keep zero-length slices (default: skipped)
152
225
  encoding: 'latin1', // delimiter bytes + slice hydration (default: utf8)
153
- timeout: 3_600_000, // max ms to await the batch; rejects on expiry
226
+ timeoutInMs: 3_600_000, // max ms to await the batch; rejects on expiry
154
227
  })
155
228
  ```
156
229
 
@@ -158,6 +231,23 @@ await split(file, workflow, {
158
231
  10_000` starts 100 children instead of one million; each child receives a
159
232
  raw block with its inner delimiters untouched and iterates locally. `keep`
160
233
  arithmetic only applies at actual cut points.
234
+ - **`trim`** cuts a fixed number of bytes off each end of the file before
235
+ scanning — a positional header/trailer, which may not be aligned with the
236
+ record delimiter (a record-start delimiter like `Split.char('\n10')` fuses
237
+ the trailer into the last record's slice, so counting records would drop a
238
+ valid one along with it). Trimmed content never becomes a slice nor counts
239
+ toward `every`; fetch it with `read`. Getting the byte counts right is the
240
+ caller's business — positional layouts make them constants:
241
+
242
+ ```typescript
243
+ const header = await read(file, { range: { start: 0, end: 240 } })
244
+
245
+ const batch = await split(file, processInvoice, {
246
+ delimiter: Split.char('\n10', { next: 2 }),
247
+ trim: { start: 241, end: 241 }, // header + '\n', trailer + '\n'
248
+ })
249
+ ```
250
+
161
251
  - **`skipEmpty`** (default `true`) drops zero-length slices — consecutive
162
252
  delimiters, or a file starting/ending with one — so they never become child
163
253
  workflows. Turn it off when the slice index must align 1:1 with the record
@@ -166,7 +256,7 @@ await split(file, workflow, {
166
256
  - **`encoding`** converts the delimiter to bytes and tells the runtime how to
167
257
  hydrate each slice for the child. Offsets are always computed over raw
168
258
  bytes, so multi-byte encodings never skew the ranges.
169
- - **`timeout`** is the maximum time in milliseconds to await the batch. On
259
+ - **`timeoutInMs`** is the maximum time in milliseconds to await the batch. On
170
260
  expiry the activity rejects (reason `timeout`) instead of suspending
171
261
  forever — the safety net for a child that never reaches a terminal state.
172
262
 
@@ -203,9 +293,12 @@ const csv = await join(batch, {
203
293
  default.
204
294
  - **`csv`** — projects object outputs into RFC 4180 escaped columns. Options:
205
295
  `columns` (required; each entry is `{ key, header? }` where `key` selects
206
- the value on the child output and `header` is the label on the header row —
207
- a plain string is shorthand for `{ key }`), `delimiter` (default `','`),
208
- `header` (default `true`; emits the column labels as the first row).
296
+ the value on the child output — a dot-path like `'meta.total'` reaches
297
+ nested fields, matching the `where` semantics; a literal top-level key that
298
+ contains dots wins over the nested path — and `header` is the label on the
299
+ header row — a plain string is shorthand for `{ key }`), `delimiter`
300
+ (default `','`), `header` (default `true`; emits the column labels as the
301
+ first row).
209
302
 
210
303
  ### Status filter
211
304
 
@@ -218,6 +311,60 @@ rejected children for reprocessing is one call away:
218
311
  const failures = await join(batch, { format: 'entries', status: ['rejected'] })
219
312
  ```
220
313
 
314
+ ### Where filter
315
+
316
+ `where` narrows results with a [sift](https://github.com/crcn/sift.js)
317
+ (MongoDB-style) query over each entry's output, applied after the `status`
318
+ filter. The accepted subset is deliberate — only declarative, JSON-only
319
+ operators: `$eq`, `$ne`, `$lt`, `$lte`, `$gt`, `$gte`, `$in`, `$nin`,
320
+ `$exists`, `$not`, `$and`, `$or`, `$nor`, plus plain equality and dot-paths
321
+ for nested fields:
322
+
323
+ ```typescript
324
+ const relevant = await join(batch, {
325
+ format: 'csv',
326
+ columns: ['id', 'total'],
327
+ where: {
328
+ valid: true, // plain strict equality
329
+ total: { $gt: 100 }, // operators
330
+ 'meta.situacao': 'aprovada', // dot-path into nested output
331
+ $or: [{ ref: 'a' }, { ref: 'b' }],
332
+ },
333
+ })
334
+ ```
335
+
336
+ `join` also accepts the child output type as a generic — top-level keys then
337
+ narrow to its fields, with values typed by the field (dot-paths are accepted
338
+ without narrowing):
339
+
340
+ ```typescript
341
+ type InvoiceResult = { id: string; valid: boolean; total: number }
342
+
343
+ await join<InvoiceResult>(batch, {
344
+ format: 'csv',
345
+ columns: ['id'],
346
+ where: { valid: true, total: { $gt: 100 } }, // { valid: 'yes' } rejects
347
+ })
348
+ ```
349
+
350
+ Anything that cannot serialize losslessly into the workflow history is
351
+ rejected eagerly at `toInput` with a `TypeError`: functions (including
352
+ `$where`), `RegExp` values (including `$regex`), `undefined`, and operators
353
+ outside the subset — a dropped closure would make the replay filter
354
+ differently than the first execution. For arbitrary predicates, write a
355
+ custom activity in project code (the function then lives in versioned code,
356
+ not in history).
357
+
358
+ Two MongoDB semantics worth knowing: array fields match by containment
359
+ (`{ tags: 'a' }` matches `tags: ['a', 'b']`), and equality against an object
360
+ value compares deeply (never by reference). Comparisons never coerce types.
361
+
362
+ Filtering runs inside the existing streaming loop, over outputs that are
363
+ already hydrated one at a time — the query compiles once and adds one
364
+ predicate call per entry, no extra serialization and no change to the memory
365
+ profile. It is applied app-side: every child output is still fetched and
366
+ parsed; `where` decides what enters the file, not what leaves the database.
367
+
221
368
  ### ByteDelimiterScanner
222
369
 
223
370
  The scanner behind `split` is exported for direct use. It is a pass-through
@@ -1,7 +1,7 @@
1
1
  import type { Readable } from 'node:stream';
2
2
  import type { Binary } from '@t4h.framework/core';
3
3
  export declare abstract class FileSystemClaim {
4
- abstract write(path: string, readable: Readable | Buffer): Binary | Promise<Binary>;
4
+ abstract write(path: string, readable: Readable | Buffer, contentType?: string): Binary | Promise<Binary>;
5
5
  abstract read(path: string): Binary | Promise<Binary>;
6
6
  abstract slice(binary: Binary, range: {
7
7
  start: number;
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemClaim.d.ts","sourceRoot":"","sources":["../src/FileSystemClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,8BAAsB,eAAe;aACnB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,MAAM,GAC1B,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;aAEX,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;aAE5C,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EACrC,QAAQ,CAAC,EAAE,cAAc,GACxB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAC5B"}
1
+ {"version":3,"file":"FileSystemClaim.d.ts","sourceRoot":"","sources":["../src/FileSystemClaim.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAE3C,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAEjD,8BAAsB,eAAe;aACnB,KAAK,CACnB,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,QAAQ,GAAG,MAAM,EAC3B,WAAW,CAAC,EAAE,MAAM,GACnB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;aAEX,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;aAE5C,KAAK,CACnB,MAAM,EAAE,MAAM,EACd,KAAK,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EACrC,QAAQ,CAAC,EAAE,cAAc,GACxB,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;CAC5B"}
@@ -1 +1 @@
1
- {"version":3,"file":"FileSystemClaim.js","sourceRoot":"","sources":["../src/FileSystemClaim.ts"],"names":[],"mappings":"AAIA,MAAM,OAAgB,eAAe;CAapC"}
1
+ {"version":3,"file":"FileSystemClaim.js","sourceRoot":"","sources":["../src/FileSystemClaim.ts"],"names":[],"mappings":"AAIA,MAAM,OAAgB,eAAe;CAcpC"}
@@ -1,27 +1,47 @@
1
- import { type Binary, SyncActivity, type WorkflowBatchRef } from '@t4h.framework/core';
1
+ import { type Binary, type Serializable, SyncActivity, type WorkflowBatchRef } from '@t4h.framework/core';
2
+ import { CSV } from '../helpers/CSV.js';
2
3
  export type FileJoinStatus = 'fulfilled' | 'rejected';
3
- type FileJoinOptionsBase = {
4
+ type FileJoinWhereOperators<TValue> = {
5
+ $eq?: TValue;
6
+ $ne?: TValue;
7
+ $lt?: TValue;
8
+ $lte?: TValue;
9
+ $gt?: TValue;
10
+ $gte?: TValue;
11
+ $in?: TValue[];
12
+ $nin?: TValue[];
13
+ $exists?: boolean;
14
+ $not?: FileJoinWhereCondition<TValue>;
15
+ };
16
+ type FileJoinWhereCondition<TValue> = TValue | FileJoinWhereOperators<TValue>;
17
+ export type FileJoinWhere<TOutput = unknown> = ([TOutput] extends [object] ? {
18
+ [K in keyof TOutput]?: FileJoinWhereCondition<Exclude<TOutput[K], undefined>>;
19
+ } & {
20
+ [path: `${string}.${string}`]: Serializable;
21
+ } : Record<string, Serializable>) & {
22
+ $and?: FileJoinWhere<TOutput>[];
23
+ $or?: FileJoinWhere<TOutput>[];
24
+ $nor?: FileJoinWhere<TOutput>[];
25
+ };
26
+ type FileJoinOptionsBase<TOutput> = {
4
27
  status?: FileJoinStatus[];
28
+ where?: FileJoinWhere<TOutput>;
5
29
  };
6
- type FileJoinOptionsLines = FileJoinOptionsBase & {
30
+ type FileJoinOptionsLines<TOutput> = FileJoinOptionsBase<TOutput> & {
7
31
  format: 'lines';
8
32
  header?: string;
9
33
  separator?: string;
10
34
  };
11
- type FileJoinOptionsEntries = FileJoinOptionsBase & {
35
+ type FileJoinOptionsEntries<TOutput> = FileJoinOptionsBase<TOutput> & {
12
36
  format: 'entries';
13
37
  };
14
- export type FileJoinColumn = string | {
15
- key: string;
16
- header?: string;
17
- };
18
- type FileJoinOptionsCsv = FileJoinOptionsBase & {
38
+ type FileJoinOptionsCsv<TOutput> = FileJoinOptionsBase<TOutput> & {
19
39
  format: 'csv';
20
- columns: FileJoinColumn[];
40
+ columns: CSV.Column[];
21
41
  delimiter?: string;
22
42
  header?: boolean;
23
43
  };
24
- export type FileJoinOptions = FileJoinOptionsLines | FileJoinOptionsEntries | FileJoinOptionsCsv;
44
+ export type FileJoinOptions<TOutput = unknown> = FileJoinOptionsLines<TOutput> | FileJoinOptionsEntries<TOutput> | FileJoinOptionsCsv<TOutput>;
25
45
  export type FileJoinActivityInput = {
26
46
  batch: string;
27
47
  options: FileJoinOptions;
@@ -34,6 +54,6 @@ export declare class FileJoinActivity extends SyncActivity<readonly [batch: Work
34
54
  private writeHeader;
35
55
  private toLine;
36
56
  }
37
- export declare function join(batch: WorkflowBatchRef, options: FileJoinOptions): Promise<Binary>;
57
+ export declare function join<TOutput = unknown>(batch: WorkflowBatchRef, options: FileJoinOptions<TOutput>): Promise<Binary>;
38
58
  export {};
39
59
  //# sourceMappingURL=FileJoinActivity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"FileJoinActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileJoinActivity.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,KAAK,MAAM,EAGX,YAAY,EAGZ,KAAK,gBAAgB,EACtB,MAAM,qBAAqB,CAAA;AAI5B,MAAM,MAAM,cAAc,GAAG,WAAW,GAAG,UAAU,CAAA;AAErD,KAAK,mBAAmB,GAAG;IACzB,MAAM,CAAC,EAAE,cAAc,EAAE,CAAA;CAC1B,CAAA;AAED,KAAK,oBAAoB,GAAG,mBAAmB,GAAG;IAChD,MAAM,EAAE,OAAO,CAAA;IACf,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,sBAAsB,GAAG,mBAAmB,GAAG;IAClD,MAAM,EAAE,SAAS,CAAA;CAClB,CAAA;AAED,MAAM,MAAM,cAAc,GACtB,MAAM,GACN;IACE,GAAG,EAAE,MAAM,CAAA;IACX,MAAM,CAAC,EAAE,MAAM,CAAA;CAChB,CAAA;AAEL,KAAK,kBAAkB,GAAG,mBAAmB,GAAG;IAC9C,MAAM,EAAE,KAAK,CAAA;IACb,OAAO,EAAE,cAAc,EAAE,CAAA;IACzB,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,MAAM,CAAC,EAAE,OAAO,CAAA;CACjB,CAAA;AAED,MAAM,MAAM,eAAe,GACvB,oBAAoB,GACpB,sBAAsB,GACtB,kBAAkB,CAAA;AAEtB,MAAM,MAAM,qBAAqB,GAAG;IAClC,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAgCD,qBAAa,gBAAiB,SAAQ,YAAY,CAChD,SAAS,CAAC,KAAK,EAAE,gBAAgB,EAAE,OAAO,EAAE,eAAe,CAAC,EAC5D,qBAAqB,EACrB,MAAM,EACN,MAAM,CACP;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;IAEK,OAAO,CACZ,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,eAAe,GACvB,qBAAqB;IAIX,GAAG,CAAC,EAAE,KAAK,EAAE,OAAO,EAAE,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IAgCrE,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;YAIzB,WAAW;IAkBzB,OAAO,CAAC,MAAM;CAsBf;AAED,wBAAsB,IAAI,CACxB,KAAK,EAAE,gBAAgB,EACvB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,MAAM,CAAC,CAEjB"}
1
+ {"version":3,"file":"FileJoinActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileJoinActivity.ts"],"names":[],"mappings":"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"}
@@ -1,35 +1,24 @@
1
1
  import { once } from 'node:events';
2
2
  import { PassThrough } from 'node:stream';
3
3
  import { Claim, History, SyncActivity, WorkflowBatchClaim, } from '@t4h.framework/core';
4
+ import sift from 'sift';
5
+ import { OPERATIONS } from '../constants/operations.js';
4
6
  import { FileSystemClaim } from '../FileSystemClaim.js';
7
+ import { CSV } from '../helpers/CSV.js';
8
+ import { assertWhereSerializable } from '../tools/assert-where-serializable.js';
5
9
  const extensions = {
6
10
  lines: 'txt',
7
11
  entries: 'ndjson',
8
12
  csv: 'csv',
9
13
  };
10
- function columnKey(column) {
11
- return typeof column === 'string' ? column : column.key;
12
- }
13
- function columnHeader(column) {
14
- return typeof column === 'string' ? column : (column.header ?? column.key);
15
- }
16
- function csvEscape(value, delimiter) {
17
- if (value === null || typeof value === 'undefined')
18
- return '';
19
- const text = typeof value === 'object' ? JSON.stringify(value) : String(value);
20
- if (text.includes(delimiter) ||
21
- text.includes('"') ||
22
- text.includes('\n') ||
23
- text.includes('\r'))
24
- return `"${text.replaceAll('"', '""')}"`;
25
- return text;
26
- }
27
14
  export class FileJoinActivity extends SyncActivity {
28
15
  claims = new Claim({
29
16
  fs: FileSystemClaim,
30
17
  batch: WorkflowBatchClaim,
31
18
  });
32
19
  toInput(batch, options) {
20
+ if (options.where)
21
+ assertWhereSerializable(options.where, 'where');
33
22
  return { batch: batch.id, options };
34
23
  }
35
24
  async run({ batch, options }) {
@@ -39,14 +28,19 @@ export class FileJoinActivity extends SyncActivity {
39
28
  if (!stream.write(line))
40
29
  await once(stream, 'drain');
41
30
  };
42
- const statuses = new Set(options.status ??
43
- (options.format === 'entries'
44
- ? ['fulfilled', 'rejected']
45
- : ['fulfilled']));
31
+ const statuses = new Set(options.status ?? ['fulfilled']);
32
+ if (!options.status && options.format === 'entries')
33
+ statuses.add('rejected');
34
+ const matches = options.where &&
35
+ sift.createQueryTester(options.where, {
36
+ operations: OPERATIONS,
37
+ });
46
38
  await this.writeHeader(options, write);
47
39
  for await (const entry of this.claims.batch.outputs(batch)) {
48
40
  if (!statuses.has(entry.status))
49
41
  continue;
42
+ if (matches && !matches(entry.output))
43
+ continue;
50
44
  await write(this.toLine(entry, options));
51
45
  }
52
46
  stream.end();
@@ -58,23 +52,16 @@ export class FileJoinActivity extends SyncActivity {
58
52
  async writeHeader(options, write) {
59
53
  if (options.format === 'lines' && options.header)
60
54
  await write(options.header + (options.separator ?? '\n'));
61
- if (options.format === 'csv' && options.header !== false) {
62
- const delimiter = options.delimiter ?? ',';
63
- await write(options.columns
64
- .map(column => csvEscape(columnHeader(column), delimiter))
65
- .join(delimiter) + '\n');
66
- }
55
+ if (options.format === 'csv' && options.header !== false)
56
+ await write(CSV.toHeader(options.columns, { delimiter: options.delimiter }));
67
57
  }
68
58
  toLine(entry, options) {
69
59
  if (options.format === 'entries')
70
60
  return JSON.stringify(entry) + '\n';
71
- if (options.format === 'csv') {
72
- const delimiter = options.delimiter ?? ',';
73
- const output = (entry.output ?? {});
74
- return (options.columns
75
- .map(column => csvEscape(output[columnKey(column)], delimiter))
76
- .join(delimiter) + '\n');
77
- }
61
+ if (options.format === 'csv')
62
+ return CSV.toLine(entry.output, options.columns, {
63
+ delimiter: options.delimiter,
64
+ });
78
65
  const value = typeof entry.output === 'string'
79
66
  ? entry.output
80
67
  : JSON.stringify(entry.output);
@@ -1 +1 @@
1
- {"version":3,"file":"FileJoinActivity.js","sourceRoot":"","sources":["../../src/activities/FileJoinActivity.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"FileJoinActivity.js","sourceRoot":"","sources":["../../src/activities/FileJoinActivity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ import { type Binary, SyncActivity } from '@t4h.framework/core';
2
+ export type FileReadOptions = {
3
+ range?: {
4
+ start: number;
5
+ end: number;
6
+ };
7
+ encoding?: BufferEncoding;
8
+ };
9
+ export type FileReadActivityInput = {
10
+ binary: Binary;
11
+ options: FileReadOptions;
12
+ };
13
+ export declare class FileReadActivity extends SyncActivity<readonly [binary: Binary, options: FileReadOptions], FileReadActivityInput, string, string> {
14
+ private readonly claims;
15
+ toInput(binary: Binary, options: FileReadOptions): FileReadActivityInput;
16
+ run({ binary, options, }: FileReadActivityInput): Promise<string>;
17
+ toOutput(output: string): string;
18
+ private slice;
19
+ private window;
20
+ }
21
+ export declare function read(binary: Binary, options?: FileReadOptions): Promise<string>;
22
+ //# sourceMappingURL=FileReadActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileReadActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileReadActivity.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,KAAK,MAAM,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAI/E,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,QAAQ,CAAC,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,qBAAqB,GAAG;IAClC,MAAM,EAAE,MAAM,CAAA;IACd,OAAO,EAAE,eAAe,CAAA;CACzB,CAAA;AAID,qBAAa,gBAAiB,SAAQ,YAAY,CAChD,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,CAAC,EACnD,qBAAqB,EACrB,MAAM,EACN,MAAM,CACP;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAErB;IAEK,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,eAAe,GACvB,qBAAqB;IAIX,GAAG,CAAC,EACf,MAAM,EACN,OAAO,GACR,EAAE,qBAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IAyBnC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;YAIzB,KAAK;YAYL,MAAM;CAuCrB;AAED,wBAAsB,IAAI,CACxB,MAAM,EAAE,MAAM,EACd,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,MAAM,CAAC,CAEjB"}
@@ -0,0 +1,68 @@
1
+ import { buffer } from 'node:stream/consumers';
2
+ import { Claim, History, SyncActivity } from '@t4h.framework/core';
3
+ import { FileSystemClaim } from '../FileSystemClaim.js';
4
+ const FILE_READ_MAX_BYTES = 1024 * 1024;
5
+ export class FileReadActivity extends SyncActivity {
6
+ claims = new Claim({
7
+ fs: FileSystemClaim,
8
+ });
9
+ toInput(binary, options) {
10
+ return { binary, options };
11
+ }
12
+ async run({ binary, options, }) {
13
+ const encoding = options.encoding ?? 'utf8';
14
+ const range = options.range ?? { start: 0, end: binary.contentLength };
15
+ const length = range.end - range.start;
16
+ if (!Number.isInteger(range.start) || range.start < 0 || length < 0)
17
+ throw new TypeError('Read range must be a non-negative byte window');
18
+ if (range.end > binary.contentLength)
19
+ throw new TypeError('Read range must not exceed the binary length');
20
+ if (length > FILE_READ_MAX_BYTES)
21
+ throw new RangeError(`Length ${length} exceeded max ${FILE_READ_MAX_BYTES}`);
22
+ const slice = await this.slice(binary, range, encoding);
23
+ if (slice)
24
+ return (await buffer(await slice.stream())).toString(encoding);
25
+ return (await this.window(await binary.stream(), range)).toString(encoding);
26
+ }
27
+ toOutput(output) {
28
+ return output;
29
+ }
30
+ async slice(binary, range, encoding) {
31
+ try {
32
+ return await this.claims.fs.slice(binary, range, encoding);
33
+ }
34
+ catch {
35
+ return null;
36
+ }
37
+ }
38
+ async window(readable, range) {
39
+ const chunks = [];
40
+ let position = 0;
41
+ let size = 0;
42
+ try {
43
+ for await (const data of readable) {
44
+ const chunk = Buffer.isBuffer(data) ? data : Buffer.from(data);
45
+ const chunkStart = position;
46
+ position += chunk.length;
47
+ if (position <= range.start)
48
+ continue;
49
+ const from = Math.max(range.start - chunkStart, 0);
50
+ const to = Math.min(range.end - chunkStart, chunk.length);
51
+ chunks.push(chunk.subarray(from, to));
52
+ size += to - from;
53
+ if (position >= range.end)
54
+ break;
55
+ }
56
+ }
57
+ finally {
58
+ readable.destroy();
59
+ }
60
+ if (size < range.end - range.start)
61
+ throw new RangeError('Binary stream ended before the read window was filled');
62
+ return Buffer.concat(chunks);
63
+ }
64
+ }
65
+ export async function read(binary, options = {}) {
66
+ return await History.reconciler(FileReadActivity, binary, options);
67
+ }
68
+ //# sourceMappingURL=FileReadActivity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileReadActivity.js","sourceRoot":"","sources":["../../src/activities/FileReadActivity.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,uBAAuB,CAAA;AAE9C,OAAO,EAAe,KAAK,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAE/E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AAYvD,MAAM,mBAAmB,GAAG,IAAI,GAAG,IAAI,CAAA;AAEvC,MAAM,OAAO,gBAAiB,SAAQ,YAKrC;IACkB,MAAM,GAAG,IAAI,KAAK,CAAC;QAClC,EAAE,EAAE,eAAe;KACpB,CAAC,CAAA;IAEK,OAAO,CACZ,MAAc,EACd,OAAwB;QAExB,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,CAAA;IAC5B,CAAC;IAEM,KAAK,CAAC,GAAG,CAAC,EACf,MAAM,EACN,OAAO,GACe;QACtB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAA;QAE3C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,MAAM,CAAC,aAAa,EAAE,CAAA;QAEtE,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK,CAAA;QAEtC,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,GAAG,CAAC;YACjE,MAAM,IAAI,SAAS,CAAC,+CAA+C,CAAC,CAAA;QAEtE,IAAI,KAAK,CAAC,GAAG,GAAG,MAAM,CAAC,aAAa;YAClC,MAAM,IAAI,SAAS,CAAC,8CAA8C,CAAC,CAAA;QAErE,IAAI,MAAM,GAAG,mBAAmB;YAC9B,MAAM,IAAI,UAAU,CAClB,UAAU,MAAM,iBAAiB,mBAAmB,EAAE,CACvD,CAAA;QAEH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;QAEvD,IAAI,KAAK;YAAE,OAAO,CAAC,MAAM,MAAM,CAAC,MAAM,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;QAEzE,OAAO,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,MAAM,MAAM,CAAC,MAAM,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAA;IAC7E,CAAC;IAEM,QAAQ,CAAC,MAAc;QAC5B,OAAO,MAAM,CAAA;IACf,CAAC;IAEO,KAAK,CAAC,KAAK,CACjB,MAAc,EACd,KAAqC,EACrC,QAAwB;QAExB,IAAI,CAAC;YACH,OAAO,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,KAAK,EAAE,QAAQ,CAAC,CAAA;QAC5D,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAA;QACb,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,MAAM,CAClB,QAAkB,EAClB,KAAqC;QAErC,MAAM,MAAM,GAAa,EAAE,CAAA;QAE3B,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,IAAI,IAAI,GAAG,CAAC,CAAA;QAEZ,IAAI,CAAC;YACH,IAAI,KAAK,EAAE,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;gBAClC,MAAM,KAAK,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;gBAE9D,MAAM,UAAU,GAAG,QAAQ,CAAA;gBAE3B,QAAQ,IAAI,KAAK,CAAC,MAAM,CAAA;gBAExB,IAAI,QAAQ,IAAI,KAAK,CAAC,KAAK;oBAAE,SAAQ;gBAErC,MAAM,IAAI,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,GAAG,UAAU,EAAE,CAAC,CAAC,CAAA;gBAClD,MAAM,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,GAAG,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;gBAEzD,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAA;gBAErC,IAAI,IAAI,EAAE,GAAG,IAAI,CAAA;gBAEjB,IAAI,QAAQ,IAAI,KAAK,CAAC,GAAG;oBAAE,MAAK;YAClC,CAAC;QACH,CAAC;gBAAS,CAAC;YACT,QAAQ,CAAC,OAAO,EAAE,CAAA;QACpB,CAAC;QAED,IAAI,IAAI,GAAG,KAAK,CAAC,GAAG,GAAG,KAAK,CAAC,KAAK;YAChC,MAAM,IAAI,UAAU,CAClB,uDAAuD,CACxD,CAAA;QAEH,OAAO,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAA;IAC9B,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,IAAI,CACxB,MAAc,EACd,UAA2B,EAAE;IAE7B,OAAO,MAAM,OAAO,CAAC,UAAU,CAAC,gBAAgB,EAAE,MAAM,EAAE,OAAO,CAAC,CAAA;AACpE,CAAC"}
@@ -1,8 +1,9 @@
1
1
  import { AsyncActivity, type Binary, type Workflow, WorkflowBatchRef, workflowBatchSchema } from '@t4h.framework/core';
2
- import { type FileSplitDelimiter } from '../helpers/byte-delimiter-scanner.js';
2
+ import { type ByteTrim, type FileSplitDelimiter } from '../helpers/byte-delimiter-scanner.js';
3
3
  export type FileSplitOptions = {
4
4
  delimiter: FileSplitDelimiter;
5
5
  every?: number;
6
+ trim?: ByteTrim;
6
7
  skipEmpty?: boolean;
7
8
  encoding?: BufferEncoding;
8
9
  timeoutInMs?: number;
@@ -1 +1 @@
1
- {"version":3,"file":"FileSplitActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileSplitActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,KAAK,MAAM,EAGX,KAAK,QAAQ,EACb,gBAAgB,EAEhB,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAEL,KAAK,kBAAkB,EACxB,MAAM,sCAAsC,CAAA;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,kBAAkB,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,qBAAa,iBAAkB,SAAQ,aAAa,CAClD,SAAS;IACP,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAC5B,OAAO,EAAE,gBAAgB;CAC1B,EACD,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,OAAO,mBAAmB,CAC3B;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;IAEK,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAC5B,OAAO,EAAE,gBAAgB,GACxB,sBAAsB;IASZ,SAAS,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,OAAO,GACR,EAAE,sBAAsB;;;;IAmClB,OAAO,CAAC,OAAO,EAAE,cAAc;IAI/B,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB;CAG1D;AAED,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAC5B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAS3B;AAED,yBAAiB,KAAK,CAAC;IACd,MAAM,IAAI,GAAI,cAAY,KAAG,kBAAiC,CAAA;IAE9D,MAAM,IAAI,GACf,OAAO,MAAM,EACb,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAChC,kBAAuC,CAAA;CAC3C"}
1
+ {"version":3,"file":"FileSplitActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileSplitActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EACb,KAAK,MAAM,EAGX,KAAK,QAAQ,EACb,gBAAgB,EAEhB,mBAAmB,EACpB,MAAM,qBAAqB,CAAA;AAG5B,OAAO,EAEL,KAAK,QAAQ,EACb,KAAK,kBAAkB,EACxB,MAAM,sCAAsC,CAAA;AAE7C,MAAM,MAAM,gBAAgB,GAAG;IAC7B,SAAS,EAAE,kBAAkB,CAAA;IAC7B,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,IAAI,CAAC,EAAE,QAAQ,CAAA;IACf,SAAS,CAAC,EAAE,OAAO,CAAA;IACnB,QAAQ,CAAC,EAAE,cAAc,CAAA;IACzB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;IAChB,OAAO,EAAE,gBAAgB,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,cAAc,GAAG;IAC3B,KAAK,EAAE,MAAM,CAAA;IACb,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,qBAAa,iBAAkB,SAAQ,aAAa,CAClD,SAAS;IACP,MAAM,EAAE,MAAM;IACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC;IAC5B,OAAO,EAAE,gBAAgB;CAC1B,EACD,sBAAsB,EACtB,cAAc,EACd,gBAAgB,EAChB,sBAAsB,EACtB,OAAO,mBAAmB,CAC3B;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAGrB;IAEK,OAAO,CACZ,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAC5B,OAAO,EAAE,gBAAgB,GACxB,sBAAsB;IASZ,SAAS,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,OAAO,GACR,EAAE,sBAAsB;;;;IAoClB,OAAO,CAAC,OAAO,EAAE,cAAc;IAI/B,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,gBAAgB;CAG1D;AAED,wBAAsB,KAAK,CACzB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,QAAQ,CAAC,GAAG,EAAE,GAAG,CAAC,EAC5B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAS3B;AAED,yBAAiB,KAAK,CAAC;IACd,MAAM,IAAI,GAAI,cAAY,KAAG,kBAAiC,CAAA;IAE9D,MAAM,IAAI,GACf,OAAO,MAAM,EACb,OAAO,kBAAkB,CAAC,MAAM,CAAC,KAChC,kBAAuC,CAAA;CAC3C"}
@@ -16,6 +16,7 @@ export class FileSplitActivity extends AsyncActivity {
16
16
  const scanner = new ByteDelimiterScanner({
17
17
  delimiter: options.delimiter,
18
18
  every: options.every,
19
+ trim: options.trim,
19
20
  skipEmpty: options.skipEmpty,
20
21
  encoding,
21
22
  });
@@ -1 +1 @@
1
- {"version":3,"file":"FileSplitActivity.js","sourceRoot":"","sources":["../../src/activities/FileSplitActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,aAAa,EAEb,KAAK,EACL,OAAO,EAEP,gBAAgB,EAChB,aAAa,EACb,mBAAmB,GACpB,MAAM,qBAAqB,CAAA;AAE5B,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAA;AACvD,OAAO,EACL,oBAAoB,GAErB,MAAM,sCAAsC,CAAA;AAqB7C,MAAM,OAAO,iBAAkB,SAAQ,aAWtC;IACkB,MAAM,GAAG,IAAI,KAAK,CAAC;QAClC,EAAE,EAAE,eAAe;QACnB,QAAQ,EAAE,aAAa;KACxB,CAAC,CAAA;IAEK,OAAO,CACZ,MAAc,EACd,QAA4B,EAC5B,OAAyB;QAEzB,IAAI,CAAC,QAAQ,CAAC,EAAE;YACd,MAAM,IAAI,SAAS,CACjB,sDAAsD,CACvD,CAAA;QAEH,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,OAAO,EAAE,CAAA;IACnD,CAAC;IAEM,KAAK,CAAC,SAAS,CAAC,EACrB,MAAM,EACN,QAAQ,EACR,OAAO,GACgB;QACvB,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,MAAM,CAAA;QAE3C,MAAM,OAAO,GAAG,IAAI,oBAAoB,CAAC;YACvC,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,KAAK,EAAE,OAAO,CAAC,KAAK;YACpB,SAAS,EAAE,OAAO,CAAC,SAAS;YAC5B,QAAQ;SACT,CAAC,CAAA;QAEF,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,EAAE,CAAA;QAEpC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CACxC,SAAS,IAAI,CAAC,EAAE,EAAE,EAClB,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CACrB,CAAA;QAED,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,GAAG,CAC9B,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE,CACzB,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,CAC/C,CACF,CAAA;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAA;QAEpE,IAAI,KAAK,CAAC,KAAK,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAA;QAEtE,OAAO,IAAI,CAAC,OAAO,CAAC;YAClB,MAAM,EAAE,mBAAmB;YAC3B,GAAG,CAAC,OAAO,CAAC,WAAW,IAAI;gBACzB,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,OAAO,CAAC,WAAW,CAAC;aACtD,CAAC;SACH,CAAC,CAAA;IACJ,CAAC;IAEM,OAAO,CAAC,OAAuB;QACpC,OAAO,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC3B,CAAC;IAEM,QAAQ,CAAC,MAAsB;QACpC,OAAO,IAAI,gBAAgB,CAAC,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,KAAK,CAAC,CAAA;IACzD,CAAC;CACF;AAED,MAAM,CAAC,KAAK,UAAU,KAAK,CACzB,MAAc,EACd,QAA4B,EAC5B,OAAyB;IAEzB,MAAM,SAAS,GAAG,MAAM,OAAO,CAAC,UAAU,CACxC,iBAAiB,EACjB,MAAM,EACN,QAAQ,EACR,OAAO,CACR,CAAA;IAED,OAAO,MAAM,SAAS,CAAC,IAAI,EAAE,CAAA;AAC/B,CAAC;AAED,MAAM,KAAW,KAAK,CAOrB;AAPD,WAAiB,KAAK;IACP,UAAI,GAAG,CAAC,KAAK,GAAG,IAAI,EAAsB,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAA;IAExD,UAAI,GAAG,CAClB,KAAa,EACb,IAAiC,EACb,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAA;AAC5C,CAAC,EAPgB,KAAK,KAAL,KAAK,QAOrB"}
1
+ {"version":3,"file":"FileSplitActivity.js","sourceRoot":"","sources":["../../src/activities/FileSplitActivity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,20 @@
1
+ import { type Binary, SyncActivity } from '@t4h.framework/core';
2
+ export type FileWriteOptions = {
3
+ filename?: string;
4
+ contentType?: string;
5
+ encoding?: BufferEncoding;
6
+ };
7
+ export type FileWriteActivityInput = {
8
+ content: string;
9
+ encoding: BufferEncoding;
10
+ filename: string;
11
+ contentType?: string;
12
+ };
13
+ export declare class FileWriteActivity extends SyncActivity<readonly [content: string | Buffer, options: FileWriteOptions], FileWriteActivityInput, Binary, Binary> {
14
+ private readonly claims;
15
+ toInput(content: string | Buffer, options: FileWriteOptions): FileWriteActivityInput;
16
+ run({ content, encoding, filename, contentType, }: FileWriteActivityInput): Promise<Binary>;
17
+ toOutput(output: Binary): Binary;
18
+ }
19
+ export declare function write(content: string | Buffer, options?: FileWriteOptions): Promise<Binary>;
20
+ //# sourceMappingURL=FileWriteActivity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"FileWriteActivity.d.ts","sourceRoot":"","sources":["../../src/activities/FileWriteActivity.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,MAAM,EAAkB,YAAY,EAAE,MAAM,qBAAqB,CAAA;AAI/E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,QAAQ,CAAC,EAAE,cAAc,CAAA;CAC1B,CAAA;AAED,MAAM,MAAM,sBAAsB,GAAG;IACnC,OAAO,EAAE,MAAM,CAAA;IACf,QAAQ,EAAE,cAAc,CAAA;IACxB,QAAQ,EAAE,MAAM,CAAA;IAChB,WAAW,CAAC,EAAE,MAAM,CAAA;CACrB,CAAA;AAED,qBAAa,iBAAkB,SAAQ,YAAY,CACjD,SAAS,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,EAAE,OAAO,EAAE,gBAAgB,CAAC,EAC9D,sBAAsB,EACtB,MAAM,EACN,MAAM,CACP;IACC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAErB;IAEK,OAAO,CACZ,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,EAAE,gBAAgB,GACxB,sBAAsB;IAWZ,GAAG,CAAC,EACf,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,WAAW,GACZ,EAAE,sBAAsB,GAAG,OAAO,CAAC,MAAM,CAAC;IAQpC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM;CAGxC;AAED,wBAAsB,KAAK,CACzB,OAAO,EAAE,MAAM,GAAG,MAAM,EACxB,OAAO,GAAE,gBAAqB,GAC7B,OAAO,CAAC,MAAM,CAAC,CAEjB"}
@@ -0,0 +1,26 @@
1
+ import { Claim, History, SyncActivity } from '@t4h.framework/core';
2
+ import { FileSystemClaim } from '../FileSystemClaim.js';
3
+ export class FileWriteActivity extends SyncActivity {
4
+ claims = new Claim({
5
+ fs: FileSystemClaim,
6
+ });
7
+ toInput(content, options) {
8
+ const isBuffer = Buffer.isBuffer(content);
9
+ return {
10
+ content: isBuffer ? content.toString('base64') : content,
11
+ encoding: isBuffer ? 'base64' : (options.encoding ?? 'utf8'),
12
+ filename: options.filename ?? this.id,
13
+ contentType: options.contentType,
14
+ };
15
+ }
16
+ async run({ content, encoding, filename, contentType, }) {
17
+ return await this.claims.fs.write(filename, Buffer.from(content, encoding), contentType);
18
+ }
19
+ toOutput(output) {
20
+ return output;
21
+ }
22
+ }
23
+ export async function write(content, options = {}) {
24
+ return await History.reconciler(FileWriteActivity, content, options);
25
+ }
26
+ //# sourceMappingURL=FileWriteActivity.js.map