@t4h.framework/fs 0.13.0 → 0.14.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.
- package/.ai/skills/framework-fs/SKILL.md +87 -186
- package/.ai/skills/framework-fs-split/SKILL.md +134 -314
- package/.ai/skills/framework-fs-write/SKILL.md +54 -214
- package/CHANGELOG.md +56 -0
- package/README.md +20 -351
- package/dist/activities/FileJoinActivity.d.ts +4 -5
- package/dist/activities/FileJoinActivity.d.ts.map +1 -1
- package/dist/activities/FileJoinActivity.js +38 -43
- package/dist/activities/FileJoinActivity.js.map +1 -1
- package/dist/activities/FileReadActivity.d.ts +1 -0
- package/dist/activities/FileReadActivity.d.ts.map +1 -1
- package/dist/activities/FileReadActivity.js +34 -26
- package/dist/activities/FileReadActivity.js.map +1 -1
- package/dist/activities/FileSplitActivity.d.ts +23 -43
- package/dist/activities/FileSplitActivity.d.ts.map +1 -1
- package/dist/activities/FileSplitActivity.js +23 -38
- package/dist/activities/FileSplitActivity.js.map +1 -1
- package/dist/constants/operations.d.ts +1 -1
- package/dist/constants/operations.d.ts.map +1 -1
- package/dist/constants/operations.js +3 -14
- package/dist/constants/operations.js.map +1 -1
- package/dist/fs.d.ts +5 -1
- package/dist/fs.d.ts.map +1 -1
- package/dist/helpers/CSV.d.ts +2 -2
- package/dist/helpers/CSV.d.ts.map +1 -1
- package/dist/helpers/CSV.js +20 -22
- package/dist/helpers/CSV.js.map +1 -1
- package/dist/helpers/group-by-key.d.ts +8 -0
- package/dist/helpers/group-by-key.d.ts.map +1 -0
- package/dist/helpers/group-by-key.js +35 -0
- package/dist/helpers/group-by-key.js.map +1 -0
- package/dist/helpers/group-records.d.ts +2 -2
- package/dist/helpers/group-records.d.ts.map +1 -1
- package/dist/helpers/group-records.js +3 -3
- package/dist/helpers/group-records.js.map +1 -1
- package/dist/helpers/in-chunks.d.ts +5 -0
- package/dist/helpers/in-chunks.d.ts.map +1 -0
- package/dist/helpers/in-chunks.js +17 -0
- package/dist/helpers/in-chunks.js.map +1 -0
- package/dist/helpers/split-records.d.ts +4 -3
- package/dist/helpers/split-records.d.ts.map +1 -1
- package/dist/helpers/split-records.js +75 -46
- package/dist/helpers/split-records.js.map +1 -1
- package/dist/helpers/where-matcher.d.ts +21 -0
- package/dist/helpers/where-matcher.d.ts.map +1 -0
- package/dist/helpers/where-matcher.js +11 -0
- package/dist/helpers/where-matcher.js.map +1 -0
- package/dist/models/BinaryRecordKey.d.ts +27 -0
- package/dist/models/BinaryRecordKey.d.ts.map +1 -0
- package/dist/models/BinaryRecordKey.js +52 -0
- package/dist/models/BinaryRecordKey.js.map +1 -0
- package/dist/models/BinarySource.d.ts +45 -0
- package/dist/models/BinarySource.d.ts.map +1 -0
- package/dist/models/BinarySource.js +58 -0
- package/dist/models/BinarySource.js.map +1 -0
- package/dist/models/BinarySplit.d.ts +45 -0
- package/dist/models/BinarySplit.d.ts.map +1 -0
- package/dist/models/BinarySplit.js +81 -0
- package/dist/models/BinarySplit.js.map +1 -0
- package/dist/models/BinarySplitInput.d.ts +21 -0
- package/dist/models/BinarySplitInput.d.ts.map +1 -0
- package/dist/models/BinarySplitInput.js +85 -0
- package/dist/models/BinarySplitInput.js.map +1 -0
- package/dist/models/Database.d.ts +15 -0
- package/dist/models/Database.d.ts.map +1 -0
- package/dist/models/Database.js +57 -0
- package/dist/models/Database.js.map +1 -0
- package/dist/models/OpenKeyGroup.d.ts +23 -0
- package/dist/models/OpenKeyGroup.d.ts.map +1 -0
- package/dist/models/OpenKeyGroup.js +42 -0
- package/dist/models/OpenKeyGroup.js.map +1 -0
- package/dist/models/SplitDatabaseWorker.d.ts +12 -0
- package/dist/models/SplitDatabaseWorker.d.ts.map +1 -0
- package/dist/models/SplitDatabaseWorker.js +65 -0
- package/dist/models/SplitDatabaseWorker.js.map +1 -0
- package/dist/workers/split-database.d.ts +10 -0
- package/dist/workers/split-database.d.ts.map +1 -0
- package/dist/workers/split-database.js +43 -0
- package/dist/workers/split-database.js.map +1 -0
- package/package.json +5 -4
|
@@ -1,242 +1,82 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: framework-fs-write
|
|
3
3
|
description: >-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
implement its own `Binary` subclass — this skill explains why and what to do
|
|
13
|
-
instead.
|
|
4
|
+
Shows how to turn content that a T4H Framework workflow built (a JSON
|
|
5
|
+
string, a CSV, a positional return file, a Buffer) into a Binary with
|
|
6
|
+
write() from @t4h.framework/fs, and how to test it. Use when a workflow must
|
|
7
|
+
upload, send or save content it made itself (sftp.put or sftp.append with
|
|
8
|
+
generated content, an HTTP request with a file body, a report), or when
|
|
9
|
+
someone asks to create a Binary, convert a string or a Buffer to a Binary,
|
|
10
|
+
writes a stringToBinary or BufferBinary helper, or extends Binary. A
|
|
11
|
+
workflow never implements its own Binary.
|
|
14
12
|
---
|
|
15
13
|
|
|
16
|
-
#
|
|
14
|
+
# write — workflow content into a Binary
|
|
17
15
|
|
|
18
|
-
|
|
19
|
-
`sftp.append`, `split`, `join`, `pdf`, HTTP bodies. A `Binary` is a
|
|
20
|
-
**reference** to stored content, not the bytes themselves.
|
|
16
|
+
Read the skill `framework-fs` first for the `Binary` rules.
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
## Write and upload
|
|
23
19
|
|
|
24
20
|
```typescript
|
|
25
21
|
import { write } from '@t4h.framework/fs'
|
|
26
22
|
|
|
27
23
|
const file = await write(JSON.stringify(state, null, 2), {
|
|
28
24
|
contentType: 'application/json',
|
|
25
|
+
filename: 'state.json',
|
|
29
26
|
})
|
|
30
27
|
|
|
31
28
|
await sftp.put('/out/state.json', file)
|
|
32
29
|
```
|
|
33
30
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
1. Build the content as a `string` or a `Buffer` in the workflow.
|
|
32
|
+
2. Call `write(content, { contentType })`. Set `contentType` when the
|
|
33
|
+
receiver cares. Without it, the claim infers one from `filename`, which
|
|
34
|
+
defaults to the activity id.
|
|
35
|
+
3. Pass the `Binary` to the next primitive. One `Binary` can go to many
|
|
36
|
+
primitives (for example `sftp.put` to a `.tmp` path and then to the final
|
|
37
|
+
path); nothing is copied.
|
|
38
|
+
|
|
39
|
+
## Traps
|
|
40
|
+
|
|
41
|
+
- Do not write a `Binary` subclass or a `stringToBinary` helper that wraps
|
|
42
|
+
bytes. Replace its body with `write`; keep the helper name if it reads well.
|
|
43
|
+
- The option is `filename`, not `path` or `name`. It is the storage name, not
|
|
44
|
+
the upload path.
|
|
45
|
+
- `encoding` applies only to a string `content` (default `'utf8'`). A
|
|
46
|
+
`Buffer` is written as it is.
|
|
47
|
+
- `write` takes only `string | Buffer`. A value that already is a `Binary`
|
|
48
|
+
goes straight to the next primitive.
|
|
49
|
+
- `write` is for content that fits in workflow memory: a state file, a
|
|
50
|
+
report, a return file. To build a large file from many records, use
|
|
51
|
+
`split` and `join` (skill `framework-fs-split`); never concatenate records in
|
|
52
|
+
the workflow.
|
|
53
|
+
- `write` is an activity. On replay it returns the recorded `Binary` and does
|
|
54
|
+
not write again.
|
|
55
|
+
|
|
56
|
+
## Test
|
|
57
|
+
|
|
58
|
+
Mock `FileSystemClaim.write`. `write` passes the content to the claim as a
|
|
59
|
+
`Buffer`. Use the `TestBinary` double from the skill `framework-fs`:
|
|
41
60
|
|
|
42
61
|
```typescript
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
private readonly content: Buffer,
|
|
47
|
-
readonly contentType = '...',
|
|
48
|
-
) {
|
|
49
|
-
super()
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
get contentLength() {
|
|
53
|
-
return this.content.length
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
stream() {
|
|
57
|
-
return Readable.from(this.content)
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
await sftp.put('/out/state.json', new BufferBinary(Buffer.from(json)))
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
```typescript
|
|
65
|
-
// ✅ ALWAYS
|
|
66
|
-
await sftp.put(
|
|
67
|
-
'/out/state.json',
|
|
68
|
-
await write(json, {
|
|
69
|
-
contentType: 'application/json',
|
|
70
|
-
}),
|
|
62
|
+
const writeFile = vi.fn(
|
|
63
|
+
async (_path: string, content: Buffer, contentType?: string) =>
|
|
64
|
+
new TestBinary(content, contentType),
|
|
71
65
|
)
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
### Why a custom `Binary` cannot work
|
|
75
|
-
|
|
76
|
-
A workflow is **durable**: the body replays, and each activity is persisted
|
|
77
|
-
before it runs. When you pass a value to a primitive, that value becomes the
|
|
78
|
-
activity **input**, and the input is serialized to storage.
|
|
79
|
-
|
|
80
|
-
A `Binary` holding bytes in memory has nothing to serialize into — the buffer
|
|
81
|
-
lives in the process that built it, and the activity may run in another
|
|
82
|
-
process, minutes later, after a replay. The runtime therefore has to spool the
|
|
83
|
-
content somewhere before the activity can be persisted at all.
|
|
84
|
-
|
|
85
|
-
Symptoms of doing it by hand:
|
|
86
|
-
|
|
87
|
-
- `TypeError: Unsupported binary instance` when the activity input is
|
|
88
|
-
serialized, on older runtimes;
|
|
89
|
-
- the activity is never persisted, the transaction rolls back, and the message
|
|
90
|
-
ends up in the dead letter queue after the retries — the run stops mid-way
|
|
91
|
-
with no obvious error in the workflow itself;
|
|
92
|
-
- it may still "work" locally, because the dev server keeps values in memory
|
|
93
|
-
and never crosses a process boundary. **Passing locally proves nothing here.**
|
|
94
|
-
|
|
95
|
-
Current runtimes spool an unknown `Binary` to storage instead of failing, so a
|
|
96
|
-
hand-rolled class may survive — but it pays a hidden copy, loses the content
|
|
97
|
-
type you meant to set, and depends on runtime-version behavior. `write` is the
|
|
98
|
-
contract.
|
|
99
|
-
|
|
100
|
-
---
|
|
101
|
-
|
|
102
|
-
## API
|
|
103
|
-
|
|
104
|
-
```typescript
|
|
105
|
-
function write(
|
|
106
|
-
content: string | Buffer,
|
|
107
|
-
options?: FileWriteOptions,
|
|
108
|
-
): Promise<Binary>
|
|
109
|
-
```
|
|
110
|
-
|
|
111
|
-
| Option | Type | Required | Purpose |
|
|
112
|
-
| ------------- | ---------------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
113
|
-
| `contentType` | `string` | No | Content type stored with the file — `'application/json'`, `'text/csv'`, … Defaults to what the filename extension implies, then `application/octet-stream`. |
|
|
114
|
-
| `filename` | `string` | No | Name the file is stored under. Defaults to the activity id. |
|
|
115
|
-
| `encoding` | `BufferEncoding` | No | How a **string** `content` is encoded. Defaults to `'utf8'`. Ignored for a `Buffer`, which always travels as base64. |
|
|
116
|
-
|
|
117
|
-
`write` is a durable activity: on replay the content is **not** written again;
|
|
118
|
-
the recorded `Binary` is returned.
|
|
119
|
-
|
|
120
|
-
---
|
|
121
|
-
|
|
122
|
-
## When to use it
|
|
123
|
-
|
|
124
|
-
| Situation | Use |
|
|
125
|
-
| ----------------------------------------------------------------------------- | ----------------------------------------------- |
|
|
126
|
-
| Send content the workflow built (JSON, CSV, positional file) over SFTP/HTTP | `write` |
|
|
127
|
-
| Read a small window of an existing file into the workflow | [`read`](./read) — see **framework-fs-split** |
|
|
128
|
-
| Fan a large file out into one workflow per record | `split` — see **framework-fs-split** |
|
|
129
|
-
| Fold a finished batch back into a file | `join` — see **framework-fs-split** |
|
|
130
|
-
| Content already is a `Binary` (HTTP response body, `sftp.get`, `join` result) | pass it straight through — do not re-`write` it |
|
|
131
|
-
|
|
132
|
-
---
|
|
133
|
-
|
|
134
|
-
## Size matters: keep content bounded
|
|
135
|
-
|
|
136
|
-
`write` takes content **in workflow memory**, so it is bounded by what the
|
|
137
|
-
workflow can reasonably hold — a state file, a report, a return file. It is not
|
|
138
|
-
the tool for gigabyte outputs.
|
|
139
|
-
|
|
140
|
-
To build a large file out of many records, use `join` over a batch: it streams
|
|
141
|
-
results one at a time into storage, and nothing but the resulting `Binary`
|
|
142
|
-
reaches the workflow.
|
|
143
66
|
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
## Patterns
|
|
147
|
-
|
|
148
|
-
### A) Write then upload
|
|
149
|
-
|
|
150
|
-
```typescript
|
|
151
|
-
const csv = await write(rows.map(toCsvLine).join('\n'), {
|
|
152
|
-
contentType: 'text/csv',
|
|
153
|
-
filename: `report-${input.date}.csv`,
|
|
67
|
+
await TestWorkflowEnvironment.create().execute(workflow, input, {
|
|
68
|
+
claims: [mockClaim(FileSystemClaim, { write: writeFile })],
|
|
154
69
|
})
|
|
155
70
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
The same `Binary` can be handed to more than one primitive — it is a reference,
|
|
162
|
-
so nothing is copied and nothing is re-uploaded:
|
|
163
|
-
|
|
164
|
-
```typescript
|
|
165
|
-
const file = await write(json, { contentType: 'application/json' })
|
|
166
|
-
|
|
167
|
-
await sftp.put(`${path}.tmp`, file)
|
|
168
|
-
await sftp.put(path, file)
|
|
169
|
-
```
|
|
170
|
-
|
|
171
|
-
Note that a hand-rolled `Binary` backed by a single-use stream would break on
|
|
172
|
-
the second call — another reason not to build one.
|
|
173
|
-
|
|
174
|
-
### C) Binary content
|
|
175
|
-
|
|
176
|
-
```typescript
|
|
177
|
-
const pdfBytes: Buffer = await buildPdf()
|
|
178
|
-
|
|
179
|
-
await sftp.put(
|
|
180
|
-
'/out/invoice.pdf',
|
|
181
|
-
await write(pdfBytes, {
|
|
182
|
-
contentType: 'application/pdf',
|
|
183
|
-
}),
|
|
71
|
+
expect(writeFile).toHaveBeenCalledWith(
|
|
72
|
+
'report.csv',
|
|
73
|
+
expect.any(Buffer),
|
|
74
|
+
'text/csv',
|
|
184
75
|
)
|
|
185
76
|
```
|
|
186
77
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
## Testing
|
|
190
|
-
|
|
191
|
-
`write` goes through `FileSystemClaim.write`, so mock that claim like any
|
|
192
|
-
other. See the **framework-workflow-testing** skill for the harness API.
|
|
193
|
-
|
|
194
|
-
```typescript
|
|
195
|
-
import { TestWorkflowEnvironment, mockClaim } from '@t4h.framework/core/testing'
|
|
196
|
-
import { FileSystemClaim } from '@t4h.framework/fs'
|
|
197
|
-
|
|
198
|
-
// replay runs the workflow twice — return a fresh Binary per call
|
|
199
|
-
const write = vi
|
|
200
|
-
.fn()
|
|
201
|
-
.mockImplementation(
|
|
202
|
-
async (path, content, contentType) =>
|
|
203
|
-
new MockBinary(
|
|
204
|
-
Buffer.isBuffer(content) ? content : await toBuffer(content),
|
|
205
|
-
contentType,
|
|
206
|
-
),
|
|
207
|
-
)
|
|
208
|
-
|
|
209
|
-
await env.execute(workflow, input, {
|
|
210
|
-
claims: [
|
|
211
|
-
mockClaim(FileSystemClaim, { write, read: vi.fn(), slice: vi.fn() }),
|
|
212
|
-
],
|
|
213
|
-
})
|
|
214
|
-
|
|
215
|
-
expect(write).toHaveBeenCalledWith('report.csv', expect.any(Buffer), 'text/csv')
|
|
216
|
-
```
|
|
217
|
-
|
|
218
|
-
---
|
|
219
|
-
|
|
220
|
-
## Anti-patterns
|
|
221
|
-
|
|
222
|
-
- **Declaring a class that extends `Binary`** in an App. There is no valid
|
|
223
|
-
reason to; use `write`.
|
|
224
|
-
- Helper functions like `stringToBinary(value)` that wrap content in a custom
|
|
225
|
-
class — replace the implementation with `write`, keeping the helper name if
|
|
226
|
-
it reads well.
|
|
227
|
-
- `write`-ing a value that already is a `Binary` (an HTTP response body, a
|
|
228
|
-
`sftp.get` result, a `join` output) — that copies a file to obtain a
|
|
229
|
-
reference you already had.
|
|
230
|
-
- Building a large file by concatenating records in memory and calling `write`
|
|
231
|
-
once — use `split`/`join` instead.
|
|
232
|
-
- Relying on the filename extension to set the content type when the consumer
|
|
233
|
-
cares about it — pass `contentType` explicitly.
|
|
234
|
-
|
|
235
|
-
---
|
|
236
|
-
|
|
237
|
-
## Related skills
|
|
78
|
+
## Reference
|
|
238
79
|
|
|
239
|
-
- `framework
|
|
240
|
-
- `framework
|
|
241
|
-
- `framework-
|
|
242
|
-
- `framework-workflow-creation` — the rules a workflow body must follow.
|
|
80
|
+
- `write`: https://tech4humans-brasil.github.io/framework/fs/write
|
|
81
|
+
- Types: `node_modules/@t4h.framework/fs/dist/activities/FileWriteActivity.d.ts`
|
|
82
|
+
- Related skills: `framework-fs`, `framework-fs-split`, `framework-sftp`.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,61 @@
|
|
|
1
1
|
# @t4h.framework/fs
|
|
2
2
|
|
|
3
|
+
## 0.14.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- [#260](https://github.com/tech4humans-brasil/framework/pull/260) [`e9e8036`](https://github.com/tech4humans-brasil/framework/commit/e9e80366440b8da611489267dd02680592ca32e9) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - `split` gets two options. `groupBy` starts one child per key, with all the records of the key. `with` gives each child the rows of other files that have the same key. The key is a `match` `RegExp` with optional `replace` steps. The `input` template gets two more markers: `Split.key` and `Split.rows(name)`. `split` reads each file one time into a temporary SQLite file on the local disk, keeps only the rows of `with` whose key is in the main file, and removes the file at the end. The files can have 1 GiB in total. The package now needs Node 22.13 or later, the first version with `node:sqlite` and `iterate()` without a flag.
|
|
8
|
+
|
|
9
|
+
The types of `split` now have the `Binary` prefix: `BinarySplitOptions`, `BinarySourceOptions`, `BinaryRecordKeyOptions`, `BinaryReplace`, `BinaryDelimiter` and `BinaryWhere`, with a `JSON` form for the stored options. `FileSplitOptions` and `FileSplitActivityOptions` extend them and keep their shape. `FileSplitDelimiter` and `FileSplitWhere` are deprecated: use `BinaryDelimiter` and `BinaryWhere`.
|
|
10
|
+
|
|
11
|
+
- [#262](https://github.com/tech4humans-brasil/framework/pull/262) [`e46ebbb`](https://github.com/tech4humans-brasil/framework/commit/e46ebbbe1e711febd21ddcb920e890125fbb9f0a) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - `split` gets the `input` option: a template that each child gets, with its slice in place of the `Split.slice` marker. The other values of the template stay as they are. `tsc` checks the template against the schema of the child workflow, so `split` and `FileSplitOptions` take the child workflow as a type parameter. `FileSplitActivityInput` stores the template in `input`, and its `options` use the new `FileSplitActivityOptions` type, which has no `input`.
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- [#248](https://github.com/tech4humans-brasil/framework/pull/248) [`ae6d224`](https://github.com/tech4humans-brasil/framework/commit/ae6d22475ee07307ac59582581a6077788b902ca) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Adds the `no-batch-query-in-loop` rule to `@t4h.framework/core/eslint` and turns it on in `configs.recommended`, at the `error` level, for TypeScript files that are not tests. After the upgrade, a project that uses the recommended config can get new lint errors. The rule reports these calls in a loop or in the callback of an array method:
|
|
16
|
+
- `join`, `split` and `index` from `@t4h.framework/fs`, and `size()`, `take()` and `toArray()` on a `WorkflowBatchCollectionRef` (also after `.filter(...)`). Each call queries or scans the whole batch or file, so a loop does N scans.
|
|
17
|
+
- `read` from `@t4h.framework/fs`. Each call is a separate activity and a separate file read, and each result goes into the workflow history.
|
|
18
|
+
|
|
19
|
+
The rule checks all the functions of the file. In an activity class, it checks only the `constructor`, `toInput` and `toOutput`. It checks only the call site, not a function that the loop calls. The core docs and skills, and the `framework-fs-split` skill of `@t4h.framework/fs`, tell you to build an index one time and call `lookup` in the loop.
|
|
20
|
+
|
|
21
|
+
- [#253](https://github.com/tech4humans-brasil/framework/pull/253) [`d9f5640`](https://github.com/tech4humans-brasil/framework/commit/d9f56403f90ffa1e04640b244f8c9247a119c084) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The fs docs and skills no longer describe how the dev server or a runtime stores a hand-rolled `Binary`. They say that such a class can pass in one environment and fail in another.
|
|
22
|
+
|
|
23
|
+
- [#257](https://github.com/tech4humans-brasil/framework/pull/257) [`586bfb4`](https://github.com/tech4humans-brasil/framework/commit/586bfb4663f4a478527ee0c8db360603f034d615) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The fs site pages now hold the full contract, the README is short, and each skill gives only the steps and traps for a consumer app. The docs now name the `split` output `WorkflowBatchCollectionRef` and no longer name a runtime limit.
|
|
24
|
+
|
|
25
|
+
- [#258](https://github.com/tech4humans-brasil/framework/pull/258) [`421f163`](https://github.com/tech4humans-brasil/framework/commit/421f16390834a26b87da5936dfa7c30c669785ed) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - `join` now fails the file stream when the batch fails before the end. Before, the stream stayed open and the write of the host did not end. `read` now rejects a range with an `end` that is not an integer. The other changes are internal and the public API does not change.
|
|
26
|
+
|
|
27
|
+
- [#246](https://github.com/tech4humans-brasil/framework/pull/246) [`b99b41f`](https://github.com/tech4humans-brasil/framework/commit/b99b41f60d69b3037187e9fcdc27ab0d47ff18a2) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Adds byte windows to `SftpBinary`. `binary.slice(range)` returns a view of a byte window of the remote file that reuses the stream of `binary`. The new `range` field is absolute in the file, with an exclusive `end`, and `contentLength` is `range.end - range.start`. A slice of a slice composes. `toJSON()` includes `range` on a slice only, so the JSON of a whole file does not change. `slice` throws a `RangeError` when the window is not inside the binary. In `@t4h.framework/fs`, the docs no longer give an SFTP reference as an example of a binary that cannot be sliced.
|
|
28
|
+
|
|
29
|
+
## 0.13.1
|
|
30
|
+
|
|
31
|
+
### Patch Changes
|
|
32
|
+
|
|
33
|
+
- [#229](https://github.com/tech4humans-brasil/framework/pull/229) [`d4d7d97`](https://github.com/tech4humans-brasil/framework/commit/d4d7d973233ec1f4d78628a69283701b9a55fbf9) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Fixes the published packages:
|
|
34
|
+
- harness: the published types import `typings/PublicProperties.js`, which was not in `dist`. `uuidv7` is now a dependency.
|
|
35
|
+
- dev: `tar` is now a dependency.
|
|
36
|
+
- fs: the published types of `FileSplitActivity` no longer import `typebox`, which `fs` does not depend on.
|
|
37
|
+
|
|
38
|
+
- [#241](https://github.com/tech4humans-brasil/framework/pull/241) [`f6b8454`](https://github.com/tech4humans-brasil/framework/commit/f6b845484d22e7c8e7240fe2e113f1cdea7c8ce3) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Adds seven rules to `@t4h.framework/core/eslint` and turns them on in `configs.recommended`:
|
|
39
|
+
- `no-io-in-workflow` reports `fetch` and calls to network, file, database and mail modules in a workflow and in the `constructor`, `toInput` and `toOutput` of an activity. It also reports `zlib` and `stream` calls there, because they work on the content in memory on each replay.
|
|
40
|
+
- `no-binary-subclass` reports a class that extends `Binary`.
|
|
41
|
+
- `no-framework-activity-in-app` reports `new` and `extends` on an activity of a framework package other than the core.
|
|
42
|
+
- `no-testing-import-in-source` reports an import of a `@t4h.framework/<package>/testing` entry out of a test file.
|
|
43
|
+
- `require-workflow-id` reports a `Workflow` with no `id`.
|
|
44
|
+
- `no-secret-to-string` reports a `Secret` that becomes a string.
|
|
45
|
+
- `no-literal-secret-in-authorization` reports a string literal in the `secret` or `clientSecret` field of an `Authorization`.
|
|
46
|
+
|
|
47
|
+
The package skills now name these rules in place of the text that the rules enforce. The docs and skills give each `Workflow` an `id`, read the HMAC secret from `EnvDesign`, and do not document a custom HTTP activity.
|
|
48
|
+
|
|
49
|
+
- [#238](https://github.com/tech4humans-brasil/framework/pull/238) [`8567806`](https://github.com/tech4humans-brasil/framework/commit/8567806ec537288076c3a18a4816f26d58a67905) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The `framework-fs` skill says to call `Binary.stream()` only in a method of an activity, not in the workflow.
|
|
50
|
+
|
|
51
|
+
- [#240](https://github.com/tech4humans-brasil/framework/pull/240) [`0606115`](https://github.com/tech4humans-brasil/framework/commit/0606115e2e0baa994e9f0ed3559ee54ecac88e44) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The skills do not repeat a rule that a lint rule, `tsc` or a runtime error already enforces. Each such rule is now one line that names the gate. The examples that broke a gate (`process.env`, `as any`, an inline secret, an `EnvDesign` in a workflow file, `ref.output` before `wait()`) are correct now.
|
|
52
|
+
|
|
53
|
+
- [#228](https://github.com/tech4humans-brasil/framework/pull/228) [`d29e1ab`](https://github.com/tech4humans-brasil/framework/commit/d29e1ab29a039b13c3e4b075472bd615566ae75e) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - Uses exact types and `unknown` in place of `any`, and checks external data with guards.
|
|
54
|
+
- harness: the fix-issues prompt lists each sensor as `- checkTypes: PASS`. Before, it printed `- 0: [object Object]`.
|
|
55
|
+
- hmac: an algorithm name such as `constructor` throws `Unsupported algorithm`.
|
|
56
|
+
- oidc: a discovery response with no `introspection_endpoint`, or a null introspection body, throws a clear error.
|
|
57
|
+
- `HttpRequestActivity.toOutput` takes `HttpRequestActivityOutput` in place of `any`.
|
|
58
|
+
|
|
3
59
|
## 0.13.0
|
|
4
60
|
|
|
5
61
|
### Minor Changes
|