@t4h.framework/sftp 0.8.5 → 0.8.6
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-sftp/SKILL.md +22 -19
- package/CHANGELOG.md +25 -0
- package/README.md +14 -2
- package/package.json +4 -2
|
@@ -13,7 +13,7 @@ description: >-
|
|
|
13
13
|
|
|
14
14
|
SFTP **activities**, **`SftpClaim`**, and a high-level **`Sftp`** client for replayable remote file operations in workflows. Package path: `framework/packages/sftp`. Peer dependency: `@t4h.framework/core` (`Binary`, `SyncActivity`, `Claim`, `History`).
|
|
15
15
|
|
|
16
|
-
Import surface (
|
|
16
|
+
Import surface (the package entry; its `exports` map has only `.`, so `tsc` rejects a deep import):
|
|
17
17
|
|
|
18
18
|
```typescript
|
|
19
19
|
import {
|
|
@@ -108,17 +108,16 @@ Methods may return sync values or `Promise`s.
|
|
|
108
108
|
|
|
109
109
|
## Sftp client (preferred in workflows)
|
|
110
110
|
|
|
111
|
-
Instantiate with the `
|
|
111
|
+
Instantiate with the `EnvDesign` entry declared `type: Secret` (the constructor takes a `Secret`, so a string is a `tsc` error). The URL `sftp://user:pass@host:22` carries the password; the host reads the value where each activity runs:
|
|
112
112
|
|
|
113
113
|
```typescript
|
|
114
114
|
import { Sftp } from '@t4h.framework/sftp'
|
|
115
|
+
|
|
115
116
|
import { environments } from '../constants/environments.js'
|
|
116
117
|
|
|
117
118
|
const sftp = new Sftp(environments.SFTP_URL) // Secret
|
|
118
119
|
```
|
|
119
120
|
|
|
120
|
-
All calls run inside a workflow (the runtime, or `TestWorkflowEnvironment` in tests, provides the reconciler context).
|
|
121
|
-
|
|
122
121
|
### Methods
|
|
123
122
|
|
|
124
123
|
| Method | Args | Returns |
|
|
@@ -149,13 +148,24 @@ All calls run inside a workflow (the runtime, or `TestWorkflowEnvironment` in te
|
|
|
149
148
|
|
|
150
149
|
### Example workflow usage
|
|
151
150
|
|
|
151
|
+
```typescript
|
|
152
|
+
// src/constants/environments.ts
|
|
153
|
+
import { EnvDesign, Secret } from '@t4h.framework/core'
|
|
154
|
+
|
|
155
|
+
export const environments = EnvDesign({
|
|
156
|
+
SFTP_URL: { type: Secret },
|
|
157
|
+
})
|
|
158
|
+
```
|
|
159
|
+
|
|
152
160
|
```typescript
|
|
153
161
|
import { Workflow } from '@t4h.framework/core'
|
|
154
162
|
import { Sftp } from '@t4h.framework/sftp'
|
|
155
163
|
|
|
156
|
-
|
|
164
|
+
import { environments } from '../constants/environments.js'
|
|
165
|
+
|
|
166
|
+
const sftp = new Sftp(environments.SFTP_URL)
|
|
157
167
|
|
|
158
|
-
export const ingestRemoteFile = new Workflow(async () => {
|
|
168
|
+
export const ingestRemoteFile = new Workflow({ id: 'ingest-remote-file' }, async () => {
|
|
159
169
|
const remotePath = '/incoming/report.csv'
|
|
160
170
|
|
|
161
171
|
if ((await sftp.exists(remotePath)) === false) {
|
|
@@ -169,16 +179,15 @@ export const ingestRemoteFile = new Workflow(async () => {
|
|
|
169
179
|
})
|
|
170
180
|
```
|
|
171
181
|
|
|
172
|
-
Use **`Binary`** from `@t4h.framework/core` for upload/download content (`put`, `get`, `append`, `downloadDir`).
|
|
173
|
-
|
|
174
182
|
---
|
|
175
183
|
|
|
176
184
|
## Using SFTP in a workflow via `History.reconciler`
|
|
177
185
|
|
|
178
186
|
Prefer the **`Sftp`** client. When you need the exported activity directly,
|
|
179
187
|
drive the **shipped** `Sftp*Activity` class through `History.reconciler` — this
|
|
180
|
-
is a ready, replay-safe helper.
|
|
181
|
-
|
|
188
|
+
is a ready, replay-safe helper.
|
|
189
|
+
`@t4h.framework/core/no-framework-activity-in-app` rejects `new` and `extends`
|
|
190
|
+
on these classes; pass them as they are.
|
|
182
191
|
|
|
183
192
|
```typescript
|
|
184
193
|
import { History } from '@t4h.framework/core'
|
|
@@ -304,9 +313,6 @@ const output = await env.execute(workflow, input, {
|
|
|
304
313
|
expect(mockGet.mock.calls[0][0]).toMatchObject({ filepath: '/remote/file.txt' })
|
|
305
314
|
```
|
|
306
315
|
|
|
307
|
-
An unconfigured claim method throws a clear error, so mock every method the
|
|
308
|
-
workflow reaches.
|
|
309
|
-
|
|
310
316
|
---
|
|
311
317
|
|
|
312
318
|
## Checklist for agents
|
|
@@ -314,11 +320,8 @@ workflow reaches.
|
|
|
314
320
|
1. Prefer **`new Sftp(connectionString)`** in workflow code — not raw SSH/SFTP libraries.
|
|
315
321
|
2. Never perform non-replayable SFTP I/O inside workflows — use **`Sftp`** or **`History.reconciler(Sftp*Activity, ...)`**.
|
|
316
322
|
3. Ensure runtime provides **`SftpClaim`** (or pass a mock in tests).
|
|
317
|
-
4.
|
|
318
|
-
5. Use **`
|
|
319
|
-
6.
|
|
320
|
-
7. Use **`mkdir(..., true)`** / **`rmdir(..., true)`** only when recursive tree ops are intended.
|
|
321
|
-
8. Test workflows with **`TestWorkflowEnvironment`** + **`mockClaim(SftpClaim, ...)`**; assert on the mock's `mock.calls`.
|
|
322
|
-
9. Do not document or import APIs not exported from `@t4h.framework/sftp`.
|
|
323
|
+
4. Use **`exists`** before destructive ops when idempotency matters; use **`delete(..., true)`** for tolerant deletes.
|
|
324
|
+
5. Use **`mkdir(..., true)`** / **`rmdir(..., true)`** only when recursive tree ops are intended.
|
|
325
|
+
6. Test workflows with **`TestWorkflowEnvironment`** + **`mockClaim(SftpClaim, ...)`**; assert on the mock's `mock.calls`.
|
|
323
326
|
|
|
324
327
|
See also: `packages/sftp/README.md`; **framework-workflow-testing** for the test harness.
|
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @t4h.framework/sftp
|
|
2
2
|
|
|
3
|
+
## 0.8.6
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#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`:
|
|
8
|
+
- `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.
|
|
9
|
+
- `no-binary-subclass` reports a class that extends `Binary`.
|
|
10
|
+
- `no-framework-activity-in-app` reports `new` and `extends` on an activity of a framework package other than the core.
|
|
11
|
+
- `no-testing-import-in-source` reports an import of a `@t4h.framework/<package>/testing` entry out of a test file.
|
|
12
|
+
- `require-workflow-id` reports a `Workflow` with no `id`.
|
|
13
|
+
- `no-secret-to-string` reports a `Secret` that becomes a string.
|
|
14
|
+
- `no-literal-secret-in-authorization` reports a string literal in the `secret` or `clientSecret` field of an `Authorization`.
|
|
15
|
+
|
|
16
|
+
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.
|
|
17
|
+
|
|
18
|
+
- [#243](https://github.com/tech4humans-brasil/framework/pull/243) [`0ffd663`](https://github.com/tech4humans-brasil/framework/commit/0ffd663ce8369edd7b54206cb3216568ad1de471) Thanks [@gusteycamargo](https://github.com/gusteycamargo)! - The README examples read each value from `environments`, an `EnvDesign` in `src/constants/environments.ts`, and pass each credential as a `Secret`. They no longer use `process.env`, the raw `env` from the core or a literal in a `Secret` field. The jwks README describes the real context fields (`signature`, `rawPayload`) and says that a token that `jwt.verify` rejects throws.
|
|
19
|
+
|
|
20
|
+
- [#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.
|
|
21
|
+
|
|
22
|
+
- [#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.
|
|
23
|
+
- harness: the fix-issues prompt lists each sensor as `- checkTypes: PASS`. Before, it printed `- 0: [object Object]`.
|
|
24
|
+
- hmac: an algorithm name such as `constructor` throws `Unsupported algorithm`.
|
|
25
|
+
- oidc: a discovery response with no `introspection_endpoint`, or a null introspection body, throws a clear error.
|
|
26
|
+
- `HttpRequestActivity.toOutput` takes `HttpRequestActivityOutput` in place of `any`.
|
|
27
|
+
|
|
3
28
|
## 0.8.5
|
|
4
29
|
|
|
5
30
|
## 0.8.4
|
package/README.md
CHANGED
|
@@ -19,11 +19,23 @@ import { SftpClaim } from '@t4h.framework/sftp'
|
|
|
19
19
|
|
|
20
20
|
High-level SFTP client that wraps every activity behind a simple API. Instantiated with a connection string.
|
|
21
21
|
|
|
22
|
+
The connection string `sftp://user:pass@host:22` carries the password, so the constructor takes a `Secret` and `tsc` rejects a string. Declare it with `type: Secret` in the `EnvDesign` in `src/constants/environments.ts`:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// src/constants/environments.ts
|
|
26
|
+
import { EnvDesign, Secret } from '@t4h.framework/core'
|
|
27
|
+
|
|
28
|
+
export const environments = EnvDesign({
|
|
29
|
+
SFTP_URL: { type: Secret },
|
|
30
|
+
})
|
|
31
|
+
```
|
|
32
|
+
|
|
22
33
|
```typescript
|
|
23
34
|
import { Sftp } from '@t4h.framework/sftp'
|
|
24
|
-
import type { Binary } from '@t4h.framework/core'
|
|
25
35
|
|
|
26
|
-
|
|
36
|
+
import { environments } from './constants/environments.js'
|
|
37
|
+
|
|
38
|
+
const sftp = new Sftp(environments.SFTP_URL)
|
|
27
39
|
```
|
|
28
40
|
|
|
29
41
|
### append
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@t4h.framework/sftp",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.6",
|
|
4
4
|
"description": "SFTP module for the T4H Framework",
|
|
5
5
|
"homepage": "https://github.com/tech4humans-brasil/framework/tree/main/packages/sftp",
|
|
6
6
|
"bugs": "https://github.com/tech4humans-brasil/framework/issues",
|
|
@@ -26,12 +26,14 @@
|
|
|
26
26
|
"scripts": {
|
|
27
27
|
"build": "tsc --project tsconfig.build.json",
|
|
28
28
|
"check-types": "tsc --noEmit",
|
|
29
|
+
"check-package": "publint --strict && attw --pack . --profile esm-only",
|
|
30
|
+
"lint": "eslint . --max-warnings 0",
|
|
29
31
|
"prepublishOnly": "yarn build",
|
|
30
32
|
"test": "vitest run",
|
|
31
33
|
"test:watch": "vitest"
|
|
32
34
|
},
|
|
33
35
|
"devDependencies": {
|
|
34
|
-
"@t4h.framework/core": "^0.
|
|
36
|
+
"@t4h.framework/core": "^0.20.0",
|
|
35
37
|
"typescript": "^5.9.3",
|
|
36
38
|
"vitest": "^4.0.18"
|
|
37
39
|
},
|