@uipath/maestro-builder-sdk 6.12.1 → 6.13.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/README.md +44 -4
- package/dist/bpmn/compile-cli.js +2 -1
- package/dist/bpmn/decompile-cli.js +2 -1
- package/dist/case/compile-cli.js +3 -2
- package/dist/case/decompile-cli.js +11 -7
- package/dist/check-cli.js +3 -3
- package/dist/cli/commands/registry.js +4 -4
- package/dist/cli-library.d.ts +1 -1
- package/dist/cli-library.js +3 -2
- package/dist/compile-cli.js +4 -3
- package/dist/core/connector-raw-node.js +1 -1
- package/dist/decompile-cli.js +13 -7
- package/dist/emit.d.ts +1 -1
- package/dist/emit.js +3 -2
- package/dist/registry/generators/markdown/sections/example.js +2 -2
- package/dist/registry/generators/markdown/sections/schema-dynamic.js +1 -1
- package/dist/registry/prepare/connections.js +3 -1
- package/dist/registry/prepare/handoff.js +2 -1
- package/dist/registry/prepare/pipeline.d.ts +13 -4
- package/dist/registry/prepare/pipeline.js +20 -6
- package/dist/registry/prepare/source-import.d.ts +7 -1
- package/dist/registry/prepare/source-import.js +16 -4
- package/dist/registry/prepare/source-labels.js +9 -3
- package/dist/registry/prepare-cli.js +2 -2
- package/dist/registry/pull-cli.js +7 -2
- package/dist/serialize.js +1 -1
- package/dist/workdir.d.ts +35 -0
- package/dist/workdir.js +96 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -128,9 +128,9 @@ reports its lookups as unresolved no matter how many times you prepare.
|
|
|
128
128
|
|
|
129
129
|
It does three things, all of them on disk:
|
|
130
130
|
|
|
131
|
-
- finds the connection and writes its ids into
|
|
131
|
+
- finds the connection and writes its ids into `.flow-sdk/bindings.json`, so the symbolic
|
|
132
132
|
`slack` and `shared` names in the code resolve;
|
|
133
|
-
- records each answered lookup in
|
|
133
|
+
- records each answered lookup in `.flow-sdk/connectors-local/`, so compiling stays
|
|
134
134
|
offline and repeatable;
|
|
135
135
|
- writes the connection-resolved field schema for that operation, which is how
|
|
136
136
|
a field the static library does not know about becomes compilable at all.
|
|
@@ -265,11 +265,51 @@ Exact signatures travel with the package, as TSDoc on the declarations in
|
|
|
265
265
|
symbol, surfaced by an editor on hover. The authoring guides carry the same
|
|
266
266
|
reference as Markdown.
|
|
267
267
|
|
|
268
|
+
## Where authoring files go
|
|
269
|
+
|
|
270
|
+
Authoring writes files that Studio Web never reads. By default they all go in
|
|
271
|
+
one hidden folder, `.flow-sdk/`, in the directory you run the command from:
|
|
272
|
+
|
|
273
|
+
| File | Written by |
|
|
274
|
+
| --- | --- |
|
|
275
|
+
| `.flow-sdk/<Name>.flow.ts` | `decompile` without `-o` |
|
|
276
|
+
| `.flow-sdk/<Name>.pipeline.mjs`, `<Name>.baseline.flow` / `.edited.flow` / `.merged.flow` | `decompile` (the brownfield helper and the candidates it writes) |
|
|
277
|
+
| `.flow-sdk/bindings.json` | `registry prepare` (read by `check` and `compile`) |
|
|
278
|
+
| `.flow-sdk/connectors/` | `registry pull` |
|
|
279
|
+
| `.flow-sdk/connectors-local/` | `registry prepare` (read by `check` and `compile`) |
|
|
280
|
+
|
|
281
|
+
The product files are written where `compile -o` points, as before: the
|
|
282
|
+
`.flow`, plus `bindings_v2.json` and an inline agent's folder beside it.
|
|
283
|
+
|
|
284
|
+
The reason is packaging. `uip solution pack` copies every root-level file of a
|
|
285
|
+
Flow project into the package, but no subfolder other than `content/`. So a
|
|
286
|
+
project authored in place used to ship its `.flow.ts`, `bindings.json` and
|
|
287
|
+
connector modules. Under `.flow-sdk/` they stay out.
|
|
288
|
+
|
|
289
|
+
For example, authoring inside a project folder:
|
|
290
|
+
|
|
291
|
+
```
|
|
292
|
+
MySolution/MyFlow/
|
|
293
|
+
├── MyFlow.flow ← compile -o MyFlow.flow (shipped)
|
|
294
|
+
├── project.uiproj, operate.json, bindings_v2.json (shipped)
|
|
295
|
+
└── .flow-sdk/ (not packed)
|
|
296
|
+
├── MyFlow.flow.ts, MyFlow.pipeline.mjs
|
|
297
|
+
├── bindings.json
|
|
298
|
+
└── connectors/, connectors-local/
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
A source kept in `.flow-sdk/` imports its connectors as `./connectors/<key>.ts`,
|
|
302
|
+
the same relative path as before. An explicit flag (`-o`, `--bindings`,
|
|
303
|
+
`--connectors`, `--connectors-local`, `--out`) still wins. A workspace that
|
|
304
|
+
already has a root-level `bindings.json`, `connectors/` or `connectors-local/`
|
|
305
|
+
keeps using it, so nothing moves under an existing project.
|
|
306
|
+
|
|
268
307
|
## Integration Service connectors
|
|
269
308
|
|
|
270
|
-
A flow that calls a connector needs a `bindings.json`
|
|
309
|
+
A flow that calls a connector needs a `bindings.json` mapping the
|
|
271
310
|
symbolic `connection` / `folder` names in the code — `slack` and `shared` in the
|
|
272
|
-
quick start — to real ids. `registry prepare` writes it
|
|
311
|
+
quick start — to real ids. `registry prepare` writes it to `.flow-sdk/bindings.json`
|
|
312
|
+
(see [Where authoring files go](#where-authoring-files-go)); this is the shape, if
|
|
273
313
|
you would rather fill it from
|
|
274
314
|
`uip is connections list --all-folders --output json`:
|
|
275
315
|
|
package/dist/bpmn/compile-cli.js
CHANGED
|
@@ -20,6 +20,7 @@ import { Bindings } from '../core/bindings.js';
|
|
|
20
20
|
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
21
21
|
import { ensureTypeScriptRuntime } from '../node-runtime.js';
|
|
22
22
|
import { resolveLibraryDir } from '../registry/cache.js';
|
|
23
|
+
import { defaultBindingsFile } from '../workdir.js';
|
|
23
24
|
function opt(argv, name) {
|
|
24
25
|
const i = argv.indexOf(name);
|
|
25
26
|
return i >= 0 ? argv[i + 1] : undefined;
|
|
@@ -49,7 +50,7 @@ export async function run(argv) {
|
|
|
49
50
|
// compile-cli); load it only when present, and bindings.json alongside the .ts.
|
|
50
51
|
const libDir = resolveLibraryDir(opt(argv, '--library'));
|
|
51
52
|
const library = libDir && existsSync(join(libDir, 'index.json')) ? new Library(libDir) : undefined;
|
|
52
|
-
const bindFile = opt(argv, '--bindings') ?? (
|
|
53
|
+
const bindFile = opt(argv, '--bindings') ?? defaultBindingsFile();
|
|
53
54
|
const bindings = new Bindings(bindFile);
|
|
54
55
|
const xml = await serialize(built, { library, bindings });
|
|
55
56
|
const base = basename(file).replace(/\.bpmn\.ts$|\.ts$/, '');
|
|
@@ -25,6 +25,7 @@ import { reportResult } from '../cli-result.js';
|
|
|
25
25
|
import { typeStripDecision } from '../node-runtime.js';
|
|
26
26
|
import { readFileSync, writeFileSync } from 'node:fs';
|
|
27
27
|
import { basename, resolve } from 'node:path';
|
|
28
|
+
import { defaultSourceOut } from '../workdir.js';
|
|
28
29
|
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
29
30
|
import { decompile } from './decompile.js';
|
|
30
31
|
import { sameGraph } from './lift-verify.js';
|
|
@@ -98,7 +99,7 @@ export async function run(argv) {
|
|
|
98
99
|
}
|
|
99
100
|
}
|
|
100
101
|
const base = basename(input).replace(/\.bpmn$/, '');
|
|
101
|
-
const out = opt(argv, '-o') ?? `${base}.bpmn.ts
|
|
102
|
+
const out = opt(argv, '-o') ?? defaultSourceOut(`${base}.bpmn.ts`);
|
|
102
103
|
writeFileSync(out, source);
|
|
103
104
|
console.log(`decompile: wrote ${out}`);
|
|
104
105
|
if (lifted) {
|
package/dist/case/compile-cli.js
CHANGED
|
@@ -20,6 +20,7 @@ import { entryPointIO } from './entry-points.js';
|
|
|
20
20
|
import { Library } from '../core/library.js';
|
|
21
21
|
import { Bindings } from '../core/bindings.js';
|
|
22
22
|
import { resolveLibraryDir } from '../registry/cache.js';
|
|
23
|
+
import { defaultBindingsFile, defaultOverlayDir } from '../workdir.js';
|
|
23
24
|
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
24
25
|
import { ensureTypeScriptRuntime } from '../node-runtime.js';
|
|
25
26
|
import { CASE_FORMAT_PROFILE } from './format-profile.js';
|
|
@@ -57,9 +58,9 @@ export async function run(argv) {
|
|
|
57
58
|
const libDir = resolveLibraryDir(opt(argv, '--library'));
|
|
58
59
|
// A `prepare-connector` overlay, auto-detected next to the case (like bindings.json).
|
|
59
60
|
const overlayDir = opt(argv, '--connectors-local')
|
|
60
|
-
?? (
|
|
61
|
+
?? defaultOverlayDir();
|
|
61
62
|
const library = libDir && existsSync(join(libDir, 'index.json')) ? new Library(libDir, { overlayDir }) : undefined;
|
|
62
|
-
const bindFile = opt(argv, '--bindings') ?? (
|
|
63
|
+
const bindFile = opt(argv, '--bindings') ?? defaultBindingsFile();
|
|
63
64
|
const bindings = new Bindings(bindFile);
|
|
64
65
|
const caseplan = serialize(built, { library, bindings });
|
|
65
66
|
const out = opt(argv, '-o') ?? 'caseplan.json';
|
|
@@ -16,9 +16,10 @@
|
|
|
16
16
|
* through the public Case CLI. Pass `--no-pipeline` to skip it.
|
|
17
17
|
*/
|
|
18
18
|
import { reportResult } from '../cli-result.js';
|
|
19
|
-
import { existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
19
|
+
import { mkdirSync, existsSync, readFileSync, writeFileSync } from 'node:fs';
|
|
20
20
|
import { resolveLibraryDir } from '../registry/cache.js';
|
|
21
|
-
import { basename, resolve } from 'node:path';
|
|
21
|
+
import { basename, join, resolve } from 'node:path';
|
|
22
|
+
import { defaultSourceOut, workDirBeside } from '../workdir.js';
|
|
22
23
|
import { runWhenInvokedDirectly } from '../cli-run.js';
|
|
23
24
|
import { Library } from '../core/library.js';
|
|
24
25
|
import { decompileWithDiagnostics } from './decompile.js';
|
|
@@ -64,7 +65,7 @@ export function run(argv) {
|
|
|
64
65
|
library,
|
|
65
66
|
bestEffort,
|
|
66
67
|
});
|
|
67
|
-
const out = opt(argv, '-o') ?? `${baseName(plan)}.case.ts
|
|
68
|
+
const out = opt(argv, '-o') ?? defaultSourceOut(`${baseName(plan)}.case.ts`);
|
|
68
69
|
writeFileSync(out, result.source);
|
|
69
70
|
console.log(`decompile: wrote ${basename(out)}`);
|
|
70
71
|
reportResult({ path: resolve(out), diagnostics: result.diagnostics.map((d) => ({ code: d.code, location: d.location, message: d.message })) });
|
|
@@ -72,8 +73,11 @@ export function run(argv) {
|
|
|
72
73
|
console.error(`decompile: [${diagnostic.code}] ${diagnostic.location}: ${diagnostic.message}`);
|
|
73
74
|
}
|
|
74
75
|
if (!argv.includes('--no-pipeline')) {
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
// The helper and the candidate caseplan it writes are never shipped.
|
|
77
|
+
const workDir = workDirBeside(out);
|
|
78
|
+
mkdirSync(workDir, { recursive: true });
|
|
79
|
+
const pipelinePath = join(workDir, basename(out).replace(/\.case\.ts$|\.ts$/, '') + '.pipeline.mjs');
|
|
80
|
+
writeFileSync(pipelinePath, pipelineScript(resolve(pos), resolve(out), resolve(pipelinePath), importSpecifier, bestEffort, libraryDir ? resolve(libraryDir) : undefined));
|
|
77
81
|
console.log(`decompile: wrote ${basename(pipelinePath)}`);
|
|
78
82
|
reportResult({ pipeline: resolve(pipelinePath) });
|
|
79
83
|
}
|
|
@@ -85,8 +89,8 @@ export function run(argv) {
|
|
|
85
89
|
* feeding the original caseplan back as the binding registry; this preserves
|
|
86
90
|
* the resource keys that the typed source deliberately names symbolically.
|
|
87
91
|
*/
|
|
88
|
-
function pipelineScript(originalPath, tsPath, importSpecifier, bestEffort, libraryDir) {
|
|
89
|
-
const base =
|
|
92
|
+
function pipelineScript(originalPath, tsPath, pipelinePath, importSpecifier, bestEffort, libraryDir) {
|
|
93
|
+
const base = pipelinePath.replace(/\.pipeline\.mjs$/, '');
|
|
90
94
|
return `#!/usr/bin/env node
|
|
91
95
|
// Generated by case decompile — edit ${basename(tsPath)}, then run this file.
|
|
92
96
|
import { execFileSync, spawnSync } from 'node:child_process';
|
package/dist/check-cli.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* Prints diagnostics; exits non-zero if any errors.
|
|
7
7
|
*/
|
|
8
8
|
import { reportDiagnostics } from './cli-result.js';
|
|
9
|
-
import {
|
|
9
|
+
import { defaultBindingsFile } from './workdir.js';
|
|
10
10
|
import { resolveFlowFile, loadBuiltFlow } from './load.js';
|
|
11
11
|
import { check } from './check.js';
|
|
12
12
|
import { byoaCheckOpts, eventResolveErrorFor, openCliLibrary } from './cli-library.js';
|
|
@@ -28,10 +28,10 @@ const VALUE_FLAGS = new Set(['--library', '--bindings', '--connectors-local']);
|
|
|
28
28
|
* through the same `openCliLibrary`.
|
|
29
29
|
*/
|
|
30
30
|
function checkOpts(argv) {
|
|
31
|
-
// bindings.json
|
|
31
|
+
// The default bindings.json (workdir.ts), exactly as compile-cli finds it — so the
|
|
32
32
|
// own-name refusal compile would raise is reported here first.
|
|
33
33
|
const bindFlag = argv.indexOf('--bindings');
|
|
34
|
-
const bindFile = bindFlag >= 0 ? argv[bindFlag + 1] : (
|
|
34
|
+
const bindFile = bindFlag >= 0 ? argv[bindFlag + 1] : defaultBindingsFile();
|
|
35
35
|
const bindings = bindFile ? new Bindings(bindFile) : undefined;
|
|
36
36
|
// The overlay matters here as much as it does for compile: `resolutions.json`
|
|
37
37
|
// lives in it, and without it every already-resolved lookup would be reported
|
|
@@ -19,7 +19,7 @@ export function registerRegistryCommands(program) {
|
|
|
19
19
|
.description('Download the published connector library and generate its Markdown and TypeScript views.')
|
|
20
20
|
.option('--library <dir>', 'where library-json lands (default: ./library)')
|
|
21
21
|
.option('--library-md <dir>', 'markdown output (default: ./library-md)')
|
|
22
|
-
.option('--connectors <dir>', 'TypeScript descriptor output (default:
|
|
22
|
+
.option('--connectors <dir>', 'TypeScript descriptor output (default: ./.flow-sdk/connectors)')
|
|
23
23
|
.option('--connector <key>', 'only generate this connector (repeatable; default: whatever the project references)', collect, [])
|
|
24
24
|
.option('--url <url>', 'archive URL to pull from')
|
|
25
25
|
.option('--archive <zip>', 'use a zip already on disk instead of downloading')
|
|
@@ -122,7 +122,7 @@ export function registerRegistryCommands(program) {
|
|
|
122
122
|
await invoke('registry build-library', () => loadTool(import.meta.url, '../../registry/library-build/cli.js'), argv);
|
|
123
123
|
});
|
|
124
124
|
family.command('prepare')
|
|
125
|
-
.description("Resolve one operation's schema against a live connection into
|
|
125
|
+
.description("Resolve one operation's schema against a live connection into ./.flow-sdk/connectors-local.")
|
|
126
126
|
.argument('<connector-key>', 'connector key, e.g. uipath-salesforce')
|
|
127
127
|
.option('--action <name>', '(required) operation to resolve, e.g. InsertRecord')
|
|
128
128
|
.allowExcessArguments()
|
|
@@ -131,7 +131,7 @@ export function registerRegistryCommands(program) {
|
|
|
131
131
|
.option('--connection-id <id>', 'connection to read the schema through')
|
|
132
132
|
.option('--connection <name>', 'pick the connection by name when several match')
|
|
133
133
|
.option('--connection-folder <folder>', 'pick the connection in the folder the flow runs in (name or key) when several match')
|
|
134
|
-
.option('--bindings <file>', 'bindings file to update (default:
|
|
134
|
+
.option('--bindings <file>', 'bindings file to update (default: ./.flow-sdk/bindings.json)')
|
|
135
135
|
.option('--bind-connection <name>', 'symbolic connection name (default: the one label the source uses for this connector, else the connector suffix)')
|
|
136
136
|
.option('--bind-folder <name>', 'symbolic folder name (default: the one folder label the source uses, else shared)')
|
|
137
137
|
// A SEPARATE key, not commander's negation of `--bindings`: sharing one key
|
|
@@ -142,7 +142,7 @@ export function registerRegistryCommands(program) {
|
|
|
142
142
|
.option('--object <name>', 'one connection-discovered object')
|
|
143
143
|
.option('--all-objects', 'every connection-discovered object')
|
|
144
144
|
.option('-f, --field <name=value>', 'parent field that selects the schema (repeatable)', collect, [])
|
|
145
|
-
.option('--out <dir>', 'overlay directory (default:
|
|
145
|
+
.option('--out <dir>', 'overlay directory (default: ./.flow-sdk/connectors-local)')
|
|
146
146
|
// Not `--version`: the program's own version option shadows a subcommand's,
|
|
147
147
|
// so `prepare --version 2.0` printed the package version instead of parsing.
|
|
148
148
|
.option('--connector-version <version>', 'connector version to resolve against')
|
package/dist/cli-library.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { Library } from './library.js';
|
|
|
5
5
|
*
|
|
6
6
|
* `--library <dir>`, else `$FLOW_SDK_LIBRARY_JSON`, else the cache `registry
|
|
7
7
|
* pull` filled (`resolveLibraryDir`). The overlay is `--connectors-local <dir>`,
|
|
8
|
-
* else `./connectors-local` when it has an `index.json` — the directory
|
|
8
|
+
* else `.flow-sdk/connectors-local` (or a legacy `./connectors-local`) when it has an `index.json` — the directory
|
|
9
9
|
* `registry prepare` writes by default.
|
|
10
10
|
*/
|
|
11
11
|
export declare function openCliLibrary(argv: readonly string[]): Library | undefined;
|
package/dist/cli-library.js
CHANGED
|
@@ -13,6 +13,7 @@ import { existsSync } from 'node:fs';
|
|
|
13
13
|
import { join } from 'node:path';
|
|
14
14
|
import { Library } from './library.js';
|
|
15
15
|
import { resolveLibraryDir } from './registry/cache.js';
|
|
16
|
+
import { defaultOverlayDir } from './workdir.js';
|
|
16
17
|
/** The value after `name` in `argv`, or `undefined`. */
|
|
17
18
|
function flagValue(argv, name) {
|
|
18
19
|
const i = argv.indexOf(name);
|
|
@@ -23,7 +24,7 @@ function flagValue(argv, name) {
|
|
|
23
24
|
*
|
|
24
25
|
* `--library <dir>`, else `$FLOW_SDK_LIBRARY_JSON`, else the cache `registry
|
|
25
26
|
* pull` filled (`resolveLibraryDir`). The overlay is `--connectors-local <dir>`,
|
|
26
|
-
* else `./connectors-local` when it has an `index.json` — the directory
|
|
27
|
+
* else `.flow-sdk/connectors-local` (or a legacy `./connectors-local`) when it has an `index.json` — the directory
|
|
27
28
|
* `registry prepare` writes by default.
|
|
28
29
|
*/
|
|
29
30
|
export function openCliLibrary(argv) {
|
|
@@ -31,7 +32,7 @@ export function openCliLibrary(argv) {
|
|
|
31
32
|
if (!libDir || !existsSync(join(libDir, 'index.json')))
|
|
32
33
|
return undefined;
|
|
33
34
|
const overlayDir = flagValue(argv, '--connectors-local')
|
|
34
|
-
?? (
|
|
35
|
+
?? defaultOverlayDir();
|
|
35
36
|
return new Library(libDir, { overlayDir });
|
|
36
37
|
}
|
|
37
38
|
/**
|
package/dist/compile-cli.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* [--no-check]
|
|
9
9
|
*
|
|
10
10
|
* --library defaults to $FLOW_SDK_LIBRARY_JSON; --bindings defaults to
|
|
11
|
-
* ./bindings.json when present. Connector actions require a library.
|
|
11
|
+
* .flow-sdk/bindings.json (or a legacy ./bindings.json) when present. Connector actions require a library.
|
|
12
12
|
*
|
|
13
13
|
* `--no-check` skips the SDK's static `check()` pass and emits whatever
|
|
14
14
|
* `.build()` produced. It exists for loops whose verification is somewhere else
|
|
@@ -28,6 +28,7 @@ import { Bindings } from './bindings.js';
|
|
|
28
28
|
import { runWhenInvokedDirectly } from './cli-run.js';
|
|
29
29
|
import { connectionResources, mergeBindingsV2, readBindingsV2 } from './bindings-v2.js';
|
|
30
30
|
import { ensureTypeScriptRuntime } from './node-runtime.js';
|
|
31
|
+
import { defaultBindingsFile } from './workdir.js';
|
|
31
32
|
import { BindingRefusal } from './core/binding-messages.js';
|
|
32
33
|
import { ByoaRefusal } from './core/byoa.js';
|
|
33
34
|
function opt(argv, name) {
|
|
@@ -75,7 +76,7 @@ export async function run(argv) {
|
|
|
75
76
|
// filled. Resolving through one helper is what stops `pull` and `compile`
|
|
76
77
|
// disagreeing about where the library is — they did, and a pulled library was
|
|
77
78
|
// invisible to this command. The `prepare-connector`/`prepare-trigger` overlay
|
|
78
|
-
// is `--connectors-local`, else
|
|
79
|
+
// is `--connectors-local`, else `.flow-sdk/connectors-local` (like bindings.json); it
|
|
79
80
|
// shadows the baked library with full, connection-resolved field schemas. See
|
|
80
81
|
// core/library.ts (LibraryOpts.overlayDir). `check-cli` opens it the same way.
|
|
81
82
|
//
|
|
@@ -88,7 +89,7 @@ export async function run(argv) {
|
|
|
88
89
|
// library, and answering it from an assumption instead is what made
|
|
89
90
|
// EVENT_NO_SCOPE an error for HTTP Webhook, whose only correct `where` is empty.
|
|
90
91
|
const library = openCliLibrary(argv);
|
|
91
|
-
const bindFile = opt(argv, '--bindings') ?? (
|
|
92
|
+
const bindFile = opt(argv, '--bindings') ?? defaultBindingsFile();
|
|
92
93
|
const bindings = new Bindings(bindFile);
|
|
93
94
|
if (!noCheck) {
|
|
94
95
|
const diags = check(built, library
|
|
@@ -42,6 +42,6 @@ export function connectorRawNodeRefusal(nodeType) {
|
|
|
42
42
|
+ `Author it as connector('${key}', '${action}', { ...inputs }, { connection: '<binding>', folder: '<binding>' }). `
|
|
43
43
|
+ `If compile then refuses an input the static library does not carry, run `
|
|
44
44
|
+ `\`${prepareCommand(key, action)}\` — it discovers the connection, writes bindings.json `
|
|
45
|
-
+ `and loads the connection-resolved fields into
|
|
45
|
+
+ `and loads the connection-resolved fields into ./.flow-sdk/connectors-local/ (add \`-f <parent>=<value>\`, e.g. `
|
|
46
46
|
+ `\`-f entityName=<Entity>\`, when the operation's fields depend on a parent input).`);
|
|
47
47
|
}
|
package/dist/decompile-cli.js
CHANGED
|
@@ -18,8 +18,9 @@
|
|
|
18
18
|
* `--no-pipeline` to skip it.
|
|
19
19
|
*/
|
|
20
20
|
import { reportResult } from './cli-result.js';
|
|
21
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
-
import { basename, resolve } from 'node:path';
|
|
21
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
22
|
+
import { basename, join, resolve } from 'node:path';
|
|
23
|
+
import { defaultSourceOut, workDirBeside } from './workdir.js';
|
|
23
24
|
import { decompile } from './decompile.js';
|
|
24
25
|
import { resolveFlowRefs } from './ref-resolve.js';
|
|
25
26
|
import { runWhenInvokedDirectly } from './cli-run.js';
|
|
@@ -65,13 +66,18 @@ export function run(argv) {
|
|
|
65
66
|
// reads them before compile refuses.
|
|
66
67
|
warn: (message) => console.error(`flow-decompile: warning: ${message}`),
|
|
67
68
|
});
|
|
68
|
-
const out = opt(argv, '-o') ?? `${baseName(flow)}.flow.ts
|
|
69
|
+
const out = opt(argv, '-o') ?? defaultSourceOut(`${baseName(flow)}.flow.ts`);
|
|
69
70
|
writeFileSync(out, ts);
|
|
70
71
|
console.log(`flow-decompile: wrote ${basename(out)}`);
|
|
71
72
|
reportResult({ path: resolve(out) });
|
|
72
73
|
if (!argv.includes('--no-pipeline')) {
|
|
73
|
-
|
|
74
|
-
|
|
74
|
+
// The helper and the baseline/edited/merged candidates it writes are never
|
|
75
|
+
// shipped, so they go in the work directory even when `-o` put the source
|
|
76
|
+
// somewhere visible.
|
|
77
|
+
const workDir = workDirBeside(out);
|
|
78
|
+
mkdirSync(workDir, { recursive: true });
|
|
79
|
+
const pipelinePath = join(workDir, basename(out).replace(/\.flow\.ts$|\.ts$/, '') + '.pipeline.mjs');
|
|
80
|
+
writeFileSync(pipelinePath, pipelineScript(resolve(pos), resolve(out), resolve(pipelinePath)));
|
|
75
81
|
console.log(`flow-decompile: wrote ${basename(pipelinePath)}`);
|
|
76
82
|
reportResult({ pipeline: resolve(pipelinePath) });
|
|
77
83
|
}
|
|
@@ -86,8 +92,8 @@ export function run(argv) {
|
|
|
86
92
|
* CLI carrying those preview commands is installed, it falls back to the SDK's
|
|
87
93
|
* retained `flow-sdk` bin from this workspace.
|
|
88
94
|
*/
|
|
89
|
-
function pipelineScript(originalPath, tsPath) {
|
|
90
|
-
const base =
|
|
95
|
+
function pipelineScript(originalPath, tsPath, pipelinePath) {
|
|
96
|
+
const base = pipelinePath.replace(/\.pipeline\.mjs$/, '');
|
|
91
97
|
return `#!/usr/bin/env node
|
|
92
98
|
// Generated by flow-decompile — the brownfield read/modify/write pipeline for
|
|
93
99
|
// ${basename(originalPath)}. Run it, edit ${basename(tsPath)}, run it again.
|
package/dist/emit.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import type { SerializeOpts } from './serialize.js';
|
|
|
3
3
|
export interface EmitFlowOpts extends SerializeOpts {
|
|
4
4
|
/** Connector library dir; defaults to `$FLOW_SDK_LIBRARY_JSON`. */
|
|
5
5
|
libraryDir?: string;
|
|
6
|
-
/** bindings.json path; defaults to `./bindings.json` when it exists. */
|
|
6
|
+
/** bindings.json path; defaults to `.flow-sdk/bindings.json` (or a legacy `./bindings.json`) when it exists. */
|
|
7
7
|
bindingsFile?: string;
|
|
8
8
|
}
|
|
9
9
|
/** Serialize `built` and write it to `path`; returns the `.flow` JSON. */
|
package/dist/emit.js
CHANGED
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
*
|
|
15
15
|
* `emitFlow(built, path)` is that, with the two resolutions defaulted the same
|
|
16
16
|
* way `compile-cli` defaults them — library from `$FLOW_SDK_LIBRARY_JSON`,
|
|
17
|
-
* bindings from `./bindings.json` when it exists:
|
|
17
|
+
* bindings from `.flow-sdk/bindings.json` (or a legacy `./bindings.json`) when it exists:
|
|
18
18
|
*
|
|
19
19
|
* ```ts
|
|
20
20
|
* export default emitFlow(flow('release-rollup')…build(), 'ReleaseRollup/ReleaseRollup.flow');
|
|
@@ -31,6 +31,7 @@ import { serialize } from './serialize.js';
|
|
|
31
31
|
import { Library } from './library.js';
|
|
32
32
|
import { Bindings } from './bindings.js';
|
|
33
33
|
import { resolveLibraryDir } from './registry/cache.js';
|
|
34
|
+
import { defaultBindingsFile } from './workdir.js';
|
|
34
35
|
/**
|
|
35
36
|
* Resolve the connector library the same way `compile-cli` does: only load it
|
|
36
37
|
* when it is actually there, so a flow with no connectors emits fine without a
|
|
@@ -45,7 +46,7 @@ function defaultLibrary(dir) {
|
|
|
45
46
|
}
|
|
46
47
|
/** Serialize `built` and write it to `path`; returns the `.flow` JSON. */
|
|
47
48
|
export function emitFlow(built, path, opts = {}) {
|
|
48
|
-
const bindFile = opts.bindingsFile ?? (
|
|
49
|
+
const bindFile = opts.bindingsFile ?? defaultBindingsFile();
|
|
49
50
|
const flowJson = serialize(built, {
|
|
50
51
|
library: opts.library ?? defaultLibrary(opts.libraryDir),
|
|
51
52
|
bindings: opts.bindings ?? new Bindings(bindFile),
|
|
@@ -206,7 +206,7 @@ export function exampleLines(j, fields, symbol, invariant, v1def) {
|
|
|
206
206
|
if (schemaDynamic && symbol) {
|
|
207
207
|
// ONE ordering per page: the import fact stays; authoring comes first.
|
|
208
208
|
if (pyTruthy(operation.objectFromDiscovery)) {
|
|
209
|
-
out.push("The descriptor comes from
|
|
209
|
+
out.push("The descriptor comes from `./.flow-sdk/connectors-local/` and this " +
|
|
210
210
|
"import resolves only after " +
|
|
211
211
|
`\`npx flow-sdk registry prepare ${connectorKey} --action ${action} ` +
|
|
212
212
|
"--object <name>` runs. That never blocks authoring: write " +
|
|
@@ -215,7 +215,7 @@ export function exampleLines(j, fields, symbol, invariant, v1def) {
|
|
|
215
215
|
"names this exact prepare — then switch to this import.");
|
|
216
216
|
}
|
|
217
217
|
else {
|
|
218
|
-
out.push("The descriptor comes from
|
|
218
|
+
out.push("The descriptor comes from `./.flow-sdk/connectors-local/` and this " +
|
|
219
219
|
"import resolves only after " +
|
|
220
220
|
`\`npx flow-sdk registry prepare ${connectorKey} --action ${action}\` ` +
|
|
221
221
|
"runs. That never blocks authoring: the fields in this " +
|
|
@@ -65,7 +65,7 @@ export function schemaDynamicLines(j, nodeType) {
|
|
|
65
65
|
}
|
|
66
66
|
out.push("> ```");
|
|
67
67
|
out.push(">");
|
|
68
|
-
let overlay = "> It writes a
|
|
68
|
+
let overlay = "> It writes a `./.flow-sdk/connectors-local/` overlay the compiler " +
|
|
69
69
|
"auto-detects (its fields are unioned onto this entry).";
|
|
70
70
|
if (!discovery) {
|
|
71
71
|
overlay +=
|
|
@@ -21,7 +21,7 @@
|
|
|
21
21
|
* a {@link UipClient} and hand the rows to them. Every refusal's text is kept
|
|
22
22
|
* verbatim — agents read these messages and follow them.
|
|
23
23
|
*/
|
|
24
|
-
import { existsSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
24
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
25
25
|
import { dirname, join, resolve as resolvePath } from "node:path";
|
|
26
26
|
import { pyJsonStringify } from "../codecs/pyjson.js";
|
|
27
27
|
import { Refusal, messageOf } from "../errors.js";
|
|
@@ -473,6 +473,8 @@ export function mergeBindings(path, symbolicConnection, symbolicFolder, connecti
|
|
|
473
473
|
}
|
|
474
474
|
}
|
|
475
475
|
const merged = mergeBindingsDocument(loaded, symbolicConnection, symbolicFolder, connection);
|
|
476
|
+
// The default lives in `.flow-sdk/`, which a fresh workspace does not have yet.
|
|
477
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
476
478
|
writeFileSync(path, formatBindings(merged.document), "utf8");
|
|
477
479
|
return [merged.wroteConnection, merged.wroteFolder];
|
|
478
480
|
}
|
|
@@ -17,6 +17,7 @@ import { readFileSync } from "node:fs";
|
|
|
17
17
|
import { join, resolve } from "node:path";
|
|
18
18
|
import { relativePosix, toPosix } from "../compat/paths.js";
|
|
19
19
|
import { pyStrip } from "../compat/pystr.js";
|
|
20
|
+
import { isRelativeSpecifier } from "./source-import.js";
|
|
20
21
|
import { descriptorUsageFallbackLines, descriptorUsageLines, descriptorUsageUnparsedLines } from "./messages.js";
|
|
21
22
|
/**
|
|
22
23
|
* `ConnectorValue<string>` → `string`, for the handoff skeleton. The generated
|
|
@@ -77,7 +78,7 @@ export function descriptorUsage(outDir, connectorKey, boundConnection = "<bindin
|
|
|
77
78
|
exports = [];
|
|
78
79
|
}
|
|
79
80
|
let importPath = relativePosix(cwd, resolve(cwd, source));
|
|
80
|
-
if (!importPath
|
|
81
|
+
if (!isRelativeSpecifier(importPath))
|
|
81
82
|
importPath = `./${importPath}`;
|
|
82
83
|
const sourcePosix = toPosix(source);
|
|
83
84
|
if (exports.length === 1) {
|
|
@@ -16,7 +16,7 @@ export interface PrepareOptions {
|
|
|
16
16
|
* already records are tried before the ambiguity refusal.
|
|
17
17
|
*/
|
|
18
18
|
connectionFolder?: string;
|
|
19
|
-
/** `--bindings` (default
|
|
19
|
+
/** `--bindings` (default `./.flow-sdk/bindings.json`, see {@link defaultBindingsOut}). */
|
|
20
20
|
bindings?: string;
|
|
21
21
|
/**
|
|
22
22
|
* `--bind-connection`. Default: the one `connection:` label the source already
|
|
@@ -31,7 +31,7 @@ export interface PrepareOptions {
|
|
|
31
31
|
allObjects?: boolean;
|
|
32
32
|
/** `-f NAME=VALUE`, repeatable, in the order given. */
|
|
33
33
|
fields?: readonly string[];
|
|
34
|
-
/** `--out` (default
|
|
34
|
+
/** `--out` (default `./.flow-sdk/connectors-local`, see {@link defaultOverlayOut}). */
|
|
35
35
|
out?: string;
|
|
36
36
|
/** `--source`: the `.flow.ts` whose import is repointed. */
|
|
37
37
|
source?: string;
|
|
@@ -56,8 +56,17 @@ export interface PreparePorts {
|
|
|
56
56
|
/** How the pasteable `registry prepare` is spelled in the notes. */
|
|
57
57
|
prepareCommand?: string;
|
|
58
58
|
}
|
|
59
|
-
/**
|
|
60
|
-
|
|
59
|
+
/**
|
|
60
|
+
* Where prepare writes its overlay when `--out` is not given, as shown to the
|
|
61
|
+
* author: `./.flow-sdk/connectors-local`, or a legacy `./connectors-local` the
|
|
62
|
+
* workspace already has (workdir.ts).
|
|
63
|
+
*/
|
|
64
|
+
export declare function defaultOverlayOut(cwd: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Where prepare records connection bindings when `--bindings` is not given:
|
|
67
|
+
* `./.flow-sdk/bindings.json`, or a legacy `./bindings.json` (workdir.ts).
|
|
68
|
+
*/
|
|
69
|
+
export declare function defaultBindingsOut(cwd: string): string;
|
|
61
70
|
export interface PrepareReport {
|
|
62
71
|
kind: "action" | "event";
|
|
63
72
|
/** The node type the overlay entry is stored under (the WAIT form for an event). */
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* file system is reached through paths resolved against `cwd`.
|
|
26
26
|
*/
|
|
27
27
|
import { existsSync, readFileSync } from "node:fs";
|
|
28
|
-
import { resolve } from "node:path";
|
|
28
|
+
import { relative, resolve } from "node:path";
|
|
29
29
|
import { GUID_RE } from "../../core/binding-messages.js";
|
|
30
30
|
import { PACKAGE_NAME } from "../../package-name.js";
|
|
31
31
|
import { afterLast } from "../compat/pystr.js";
|
|
@@ -49,8 +49,22 @@ import { retryOtherConnections } from "./retry.js";
|
|
|
49
49
|
import { repointSource } from "./source-import.js";
|
|
50
50
|
import { sourceBindingLabels } from "./source-labels.js";
|
|
51
51
|
import { isPlainObject, pyGet, pyOr, pyPathJoin, pyPathlibStr, pyStrAny, pyTruthy } from "./support.js";
|
|
52
|
-
|
|
53
|
-
|
|
52
|
+
import { workPath } from "../../workdir.js";
|
|
53
|
+
/**
|
|
54
|
+
* Where prepare writes its overlay when `--out` is not given, as shown to the
|
|
55
|
+
* author: `./.flow-sdk/connectors-local`, or a legacy `./connectors-local` the
|
|
56
|
+
* workspace already has (workdir.ts).
|
|
57
|
+
*/
|
|
58
|
+
export function defaultOverlayOut(cwd) {
|
|
59
|
+
return `./${relative(cwd, workPath("connectors-local", { cwd }))}`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Where prepare records connection bindings when `--bindings` is not given:
|
|
63
|
+
* `./.flow-sdk/bindings.json`, or a legacy `./bindings.json` (workdir.ts).
|
|
64
|
+
*/
|
|
65
|
+
export function defaultBindingsOut(cwd) {
|
|
66
|
+
return `./${relative(cwd, workPath("bindings.json", { cwd }))}`;
|
|
67
|
+
}
|
|
54
68
|
function memoryCaches() {
|
|
55
69
|
return { registry: new MemoryResponseCache(), is: new MemoryResponseCache(), connectors: new MemoryResponseCache() };
|
|
56
70
|
}
|
|
@@ -107,7 +121,7 @@ function chooseLabels(options, ports) {
|
|
|
107
121
|
const command = ports.prepareCommand ?? PREPARE_COMMAND;
|
|
108
122
|
const labels = sourceBindingLabels({
|
|
109
123
|
cwd: ports.cwd ?? process.cwd(),
|
|
110
|
-
out: options.out ??
|
|
124
|
+
out: options.out ?? defaultOverlayOut(ports.cwd ?? process.cwd()),
|
|
111
125
|
connectorKey: options.connectorKey,
|
|
112
126
|
source: options.source,
|
|
113
127
|
});
|
|
@@ -222,7 +236,7 @@ async function connect(options, ports) {
|
|
|
222
236
|
return { connectionId, row };
|
|
223
237
|
// Recorded on BOTH routes. Until 3.30.5 only discovery wrote it, and the
|
|
224
238
|
// explicit-id route left the author hand-writing the id and folder key.
|
|
225
|
-
const bindingsShown = options.bindings ??
|
|
239
|
+
const bindingsShown = options.bindings ?? defaultBindingsOut(ports.cwd ?? process.cwd());
|
|
226
240
|
const bindingsPath = resolve(ports.cwd ?? process.cwd(), bindingsShown);
|
|
227
241
|
if (labels.connectionFrom) {
|
|
228
242
|
await refuseLabelOfAnotherConnector(ports.client, options.connectorKey, labels.connection, connectionId, bindingsPath, bindingsShown);
|
|
@@ -321,7 +335,7 @@ async function prepareOnConnection(options, ports, connected) {
|
|
|
321
335
|
const { connectorKey, action } = options;
|
|
322
336
|
const fieldPairs = options.fields ?? [];
|
|
323
337
|
const parentFields = parseFields(fieldPairs);
|
|
324
|
-
const outShown = options.out ??
|
|
338
|
+
const outShown = options.out ?? defaultOverlayOut(cwd);
|
|
325
339
|
const out = resolve(cwd, outShown);
|
|
326
340
|
const importSpecifier = options.importSpecifier ?? PACKAGE_NAME;
|
|
327
341
|
const jsonOnly = options.jsonOnly ?? false;
|
|
@@ -3,7 +3,11 @@
|
|
|
3
3
|
* Anchored to a real import statement on purpose (see the module comment).
|
|
4
4
|
*/
|
|
5
5
|
export declare const IMPORT_PATTERN: RegExp;
|
|
6
|
-
/**
|
|
6
|
+
/**
|
|
7
|
+
* Where a `.flow.ts` will not be: generated output and installed packages.
|
|
8
|
+
* Matched by name at any depth, so `.flow-sdk/connectors/` is skipped too while
|
|
9
|
+
* a source kept in `.flow-sdk/` itself is found.
|
|
10
|
+
*/
|
|
7
11
|
export declare const SOURCE_SKIP_DIRS: ReadonlySet<string>;
|
|
8
12
|
/**
|
|
9
13
|
* `Path(p).resolve()` with `strict=False`: absolute, `..` collapsed, and
|
|
@@ -11,6 +15,8 @@ export declare const SOURCE_SKIP_DIRS: ReadonlySet<string>;
|
|
|
11
15
|
* go through this, so `/var/...` and `/private/var/...` name one file.
|
|
12
16
|
*/
|
|
13
17
|
export declare function canonicalPath(p: string): string;
|
|
18
|
+
/** `./x`, `../x`, `.` or `..`: a path relative to the importing file, as Node reads one. */
|
|
19
|
+
export declare function isRelativeSpecifier(specifier: string): boolean;
|
|
14
20
|
/**
|
|
15
21
|
* `_resolves_to`: does `specifier`, read from `source`, name the file `target`?
|
|
16
22
|
* A bare package specifier never does — it is not our overlay.
|
|
@@ -23,13 +23,18 @@ import { readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from
|
|
|
23
23
|
import { basename, dirname, join, resolve } from "node:path";
|
|
24
24
|
import { compareCodePoints } from "../compat/compare.js";
|
|
25
25
|
import { relativePosix } from "../compat/paths.js";
|
|
26
|
+
import { workPath } from "../../workdir.js";
|
|
26
27
|
import { repointedLine, severalSourcesLine, sourceNotAFileLine } from "./messages.js";
|
|
27
28
|
/**
|
|
28
29
|
* `import … from "<specifier>"` — the specifier is group 3, quotes preserved.
|
|
29
30
|
* Anchored to a real import statement on purpose (see the module comment).
|
|
30
31
|
*/
|
|
31
32
|
export const IMPORT_PATTERN = /(^\s*import\s[^;'"]*?\sfrom\s*)(['"])([^'"]+)(\2)/gm;
|
|
32
|
-
/**
|
|
33
|
+
/**
|
|
34
|
+
* Where a `.flow.ts` will not be: generated output and installed packages.
|
|
35
|
+
* Matched by name at any depth, so `.flow-sdk/connectors/` is skipped too while
|
|
36
|
+
* a source kept in `.flow-sdk/` itself is found.
|
|
37
|
+
*/
|
|
33
38
|
export const SOURCE_SKIP_DIRS = new Set(["node_modules", "connectors", "connectors-local", ".git"]);
|
|
34
39
|
/**
|
|
35
40
|
* `Path(p).resolve()` with `strict=False`: absolute, `..` collapsed, and
|
|
@@ -48,12 +53,16 @@ export function canonicalPath(p) {
|
|
|
48
53
|
return join(canonicalPath(parent), basename(absolute));
|
|
49
54
|
}
|
|
50
55
|
}
|
|
56
|
+
/** `./x`, `../x`, `.` or `..`: a path relative to the importing file, as Node reads one. */
|
|
57
|
+
export function isRelativeSpecifier(specifier) {
|
|
58
|
+
return /^\.\.?(\/|$)/.test(specifier);
|
|
59
|
+
}
|
|
51
60
|
/**
|
|
52
61
|
* `_resolves_to`: does `specifier`, read from `source`, name the file `target`?
|
|
53
62
|
* A bare package specifier never does — it is not our overlay.
|
|
54
63
|
*/
|
|
55
64
|
export function resolvesTo(specifier, source, target) {
|
|
56
|
-
if (!specifier
|
|
65
|
+
if (!isRelativeSpecifier(specifier))
|
|
57
66
|
return false;
|
|
58
67
|
return canonicalPath(resolve(dirname(source), specifier)) === canonicalPath(target);
|
|
59
68
|
}
|
|
@@ -134,7 +143,9 @@ export function repointImport(source, baked, prepared) {
|
|
|
134
143
|
return undefined;
|
|
135
144
|
}
|
|
136
145
|
let specifier = relativePosix(dirname(source), prepared);
|
|
137
|
-
|
|
146
|
+
// `.flow-sdk/…` starts with a dot but is not relative: without `./` Node
|
|
147
|
+
// resolves it as a package name.
|
|
148
|
+
if (!isRelativeSpecifier(specifier))
|
|
138
149
|
specifier = `./${specifier}`;
|
|
139
150
|
let changed = false;
|
|
140
151
|
const rewritten = text.replace(IMPORT_PATTERN, (whole, head, quote, spec, tail) => {
|
|
@@ -169,7 +180,8 @@ export function repointSource(options) {
|
|
|
169
180
|
if (options.noSourceRewrite || !isFile(prepared))
|
|
170
181
|
return [];
|
|
171
182
|
const root = canonicalPath(cwd);
|
|
172
|
-
|
|
183
|
+
// Where `registry pull` put the module: `.flow-sdk/connectors/`, or a legacy `connectors/`.
|
|
184
|
+
const baked = canonicalPath(join(workPath("connectors", { cwd: root }), `${options.connectorKey}.ts`));
|
|
173
185
|
let candidates;
|
|
174
186
|
if (options.source) {
|
|
175
187
|
candidates = [canonicalPath(resolve(cwd, options.source))];
|
|
@@ -44,7 +44,8 @@ import { basename, dirname, extname, resolve } from "node:path";
|
|
|
44
44
|
import * as ts from "typescript";
|
|
45
45
|
import { GUID_RE } from "../../core/binding-messages.js";
|
|
46
46
|
import { relativePosix } from "../compat/paths.js";
|
|
47
|
-
import { canonicalPath, flowSources } from "./source-import.js";
|
|
47
|
+
import { canonicalPath, flowSources, isRelativeSpecifier } from "./source-import.js";
|
|
48
|
+
import { inWorkDir } from "../../workdir.js";
|
|
48
49
|
const CALLEES = new Set(["connector", "onEvent", "waitForEvent"]);
|
|
49
50
|
function isFile(path) {
|
|
50
51
|
try {
|
|
@@ -58,7 +59,12 @@ function isFile(path) {
|
|
|
58
59
|
export function sourceBindingLabels(options) {
|
|
59
60
|
const result = { connection: new Map(), folder: new Map(), otherConnectors: new Map(), unreadable: { connection: [], folder: [] } };
|
|
60
61
|
const root = canonicalPath(options.cwd);
|
|
61
|
-
|
|
62
|
+
// `registry pull`'s modules in either layout (workdir.ts), and the overlay.
|
|
63
|
+
const moduleDirs = [
|
|
64
|
+
canonicalPath(inWorkDir("connectors", root)),
|
|
65
|
+
canonicalPath(resolve(root, "connectors")),
|
|
66
|
+
canonicalPath(resolve(options.cwd, options.out)),
|
|
67
|
+
];
|
|
62
68
|
let files;
|
|
63
69
|
if (options.source) {
|
|
64
70
|
const one = canonicalPath(resolve(options.cwd, options.source));
|
|
@@ -81,7 +87,7 @@ export function sourceBindingLabels(options) {
|
|
|
81
87
|
}
|
|
82
88
|
/** The connector key a module specifier names, when it is one of the generated connector modules. */
|
|
83
89
|
function connectorModuleKey(specifier, from, moduleDirs) {
|
|
84
|
-
if (!specifier
|
|
90
|
+
if (!isRelativeSpecifier(specifier))
|
|
85
91
|
return undefined;
|
|
86
92
|
let target = canonicalPath(resolve(dirname(from), specifier));
|
|
87
93
|
if (extname(target) === "")
|
|
@@ -3,7 +3,7 @@ import { reportResult } from '../cli-result.js';
|
|
|
3
3
|
import { PACKAGE_NAME } from "../package-name.js";
|
|
4
4
|
import { exitCodeOf } from "./errors.js";
|
|
5
5
|
import { exitText } from "./prepare/messages.js";
|
|
6
|
-
import {
|
|
6
|
+
import { defaultOverlayOut, prepareConnector as runPipeline } from "./prepare/pipeline.js";
|
|
7
7
|
import { consoleReporter } from "./reporter.js";
|
|
8
8
|
import { defaultUipClient } from "./uip/client.js";
|
|
9
9
|
// This mirrors the generator's own flags one for one, so a `--version` here is
|
|
@@ -187,7 +187,7 @@ export async function run(argv) {
|
|
|
187
187
|
}
|
|
188
188
|
try {
|
|
189
189
|
const report = await prepareConnector(options);
|
|
190
|
-
reportResult({ connector: options.connectorKey, action: options.action, overlay: resolve(options.outPath ??
|
|
190
|
+
reportResult({ connector: options.connectorKey, action: options.action, overlay: resolve(options.outPath ?? defaultOverlayOut(process.cwd())), ...report });
|
|
191
191
|
return 0;
|
|
192
192
|
}
|
|
193
193
|
catch (error) {
|
|
@@ -6,6 +6,7 @@ import { CURRENT_LINK, LIBRARY_JSON_DIR, LIBRARY_MARKDOWN_DIR, cacheEntry, libra
|
|
|
6
6
|
import { extractLibrary } from "./extractor.js";
|
|
7
7
|
import { materializeRegistry } from "./materializer.js";
|
|
8
8
|
import { curatedOverlayIdentity } from "./curated-overlay.js";
|
|
9
|
+
import { WORK_DIR, workPath } from "../workdir.js";
|
|
9
10
|
/**
|
|
10
11
|
* Fetch the published connector library into the shared cache, and generate the
|
|
11
12
|
* typed descriptors a project imports.
|
|
@@ -244,7 +245,8 @@ export async function run(argv) {
|
|
|
244
245
|
console.error(`registry pull: ${flag} is ignored — the generators run in-process now and the flag will be removed.`);
|
|
245
246
|
}
|
|
246
247
|
}
|
|
247
|
-
|
|
248
|
+
// `.flow-sdk/connectors`, or a legacy `connectors/` the workspace already has.
|
|
249
|
+
const connectorsPath = value(argv, "--connectors") ?? workPath("connectors");
|
|
248
250
|
try {
|
|
249
251
|
const archive = await resolveArchive(argv, cacheDir, force);
|
|
250
252
|
const archiveSha256 = await archiveIdentity(archive);
|
|
@@ -277,7 +279,10 @@ export async function run(argv) {
|
|
|
277
279
|
// Which descriptors this project will actually import. Generating all 30
|
|
278
280
|
// costs 1.1 MB in someone's repository for operations they never call.
|
|
279
281
|
const named = repeated(argv, "--connector");
|
|
280
|
-
|
|
282
|
+
// Sources sit in the project root or in the hidden work directory.
|
|
283
|
+
const referenced = named.length > 0
|
|
284
|
+
? named
|
|
285
|
+
: [...new Set([...referencedConnectorKeys("."), ...referencedConnectorKeys(WORK_DIR)])].sort();
|
|
281
286
|
// Generate only what is missing. The Markdown is 2,472 pages and a pure
|
|
282
287
|
// function of the library JSON, so regenerating it to add one descriptor is
|
|
283
288
|
// pure waste — and it is what the first run of this design did.
|
package/dist/serialize.js
CHANGED
|
@@ -6417,7 +6417,7 @@ function buildConnectorInputs(rc, inputs, rename = NO_RENAME, resolutions = {},
|
|
|
6417
6417
|
`static library does not contain this input. Run ` +
|
|
6418
6418
|
`\`${prepareCommand(rc.connectorKey, action)}\` ` +
|
|
6419
6419
|
`to load them ` +
|
|
6420
|
-
`(writes
|
|
6420
|
+
`(writes ./.flow-sdk/connectors-local/, which the compiler auto-detects). If that still ` +
|
|
6421
6421
|
`does not carry this input, the operation resolves its fields from the VALUES of ` +
|
|
6422
6422
|
`parent inputs: resolve every parent and re-run with ` +
|
|
6423
6423
|
`\`-f <parent-field>=<value>\` for each — too few parents is refused, and a ` +
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/** The hidden directory, relative to the current directory. */
|
|
2
|
+
export declare const WORK_DIR = ".flow-sdk";
|
|
3
|
+
/** `name` under {@link WORK_DIR}, relative to `cwd` when one is given. */
|
|
4
|
+
export declare function inWorkDir(name: string, cwd?: string): string;
|
|
5
|
+
/**
|
|
6
|
+
* Where the default `name` lives for this workspace, for reading or writing.
|
|
7
|
+
*
|
|
8
|
+
* `.flow-sdk/<name>` when it exists; else the legacy `./<name>` when THAT exists
|
|
9
|
+
* (a workspace laid out before the work directory); else `.flow-sdk/<name>`,
|
|
10
|
+
* where a new file goes. Pass `exists` to require more than presence (an
|
|
11
|
+
* overlay counts only once it has its `index.json`).
|
|
12
|
+
*/
|
|
13
|
+
export declare function workPath(name: string, options?: {
|
|
14
|
+
cwd?: string;
|
|
15
|
+
exists?: (path: string) => boolean;
|
|
16
|
+
}): string;
|
|
17
|
+
/** {@link workPath} for a file that is only read: `undefined` when neither exists. */
|
|
18
|
+
export declare function existingWorkPath(name: string, options?: {
|
|
19
|
+
cwd?: string;
|
|
20
|
+
exists?: (path: string) => boolean;
|
|
21
|
+
}): string | undefined;
|
|
22
|
+
/** The default author-side `bindings.json`, when there is one. */
|
|
23
|
+
export declare function defaultBindingsFile(cwd?: string): string | undefined;
|
|
24
|
+
/** The default `connectors-local/` overlay, once `registry prepare` has written its index. */
|
|
25
|
+
export declare function defaultOverlayDir(cwd?: string): string | undefined;
|
|
26
|
+
/** Create the work directory under `cwd` (default: the current directory). */
|
|
27
|
+
export declare function ensureWorkDir(cwd?: string): void;
|
|
28
|
+
/**
|
|
29
|
+
* The work directory that goes with an authored `path`: the directory `path` is
|
|
30
|
+
* already in when that is a work directory, else `.flow-sdk/` beside it. A
|
|
31
|
+
* decompile's `.pipeline.mjs` helper and the candidates it writes go here.
|
|
32
|
+
*/
|
|
33
|
+
export declare function workDirBeside(path: string): string;
|
|
34
|
+
/** The default path of a decompiled source named `file`, creating the work directory. */
|
|
35
|
+
export declare function defaultSourceOut(file: string): string;
|
package/dist/workdir.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The SDK's hidden work directory: where authoring files that never ship live.
|
|
3
|
+
*
|
|
4
|
+
* Authoring writes files the product never reads: the decompiled `<Name>.flow.ts`
|
|
5
|
+
* and its `.pipeline.mjs` helper, the `baseline`/`edited`/`merged` candidates, the
|
|
6
|
+
* author-side `bindings.json`, and the generated `connectors/` and
|
|
7
|
+
* `connectors-local/` modules. Studio Web needs none of them. The product files
|
|
8
|
+
* (`<Name>.flow`, `project.uiproj`, `operate.json`, `bindings_v2.json`, an inline
|
|
9
|
+
* agent's folder) are written where `compile -o` says, exactly as before.
|
|
10
|
+
*
|
|
11
|
+
* Every one of those defaults used to be a bare name in the current directory,
|
|
12
|
+
* so a project authored in place carried them into its package: `uip solution
|
|
13
|
+
* pack` copies every root-level file of a Flow project. Keeping them under one
|
|
14
|
+
* dot-folder keeps them out: pack copies no project subfolder but `content/`.
|
|
15
|
+
*
|
|
16
|
+
* Paths stay relative to the current directory, as the old defaults were, so
|
|
17
|
+
* `uip` (which spawns the SDK with the caller's cwd) and a direct `flow-sdk`
|
|
18
|
+
* call land in the same place. An explicit flag (`-o`, `--bindings`,
|
|
19
|
+
* `--connectors`, `--connectors-local`, `--out`) still wins.
|
|
20
|
+
*
|
|
21
|
+
* A workspace laid out before this directory existed keeps working: when only
|
|
22
|
+
* the old root-level entry exists, reads and writes use it (see
|
|
23
|
+
* {@link workPath}), so an existing `./connectors-local/` overlay is extended
|
|
24
|
+
* rather than split across two places. When both exist, `.flow-sdk/` wins and
|
|
25
|
+
* stderr says the root one is ignored.
|
|
26
|
+
*/
|
|
27
|
+
import { existsSync, mkdirSync } from 'node:fs';
|
|
28
|
+
import { basename, dirname, join } from 'node:path';
|
|
29
|
+
/** The hidden directory, relative to the current directory. */
|
|
30
|
+
export const WORK_DIR = '.flow-sdk';
|
|
31
|
+
/** `name` under {@link WORK_DIR}, relative to `cwd` when one is given. */
|
|
32
|
+
export function inWorkDir(name, cwd) {
|
|
33
|
+
return cwd === undefined ? join(WORK_DIR, name) : join(cwd, WORK_DIR, name);
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Where the default `name` lives for this workspace, for reading or writing.
|
|
37
|
+
*
|
|
38
|
+
* `.flow-sdk/<name>` when it exists; else the legacy `./<name>` when THAT exists
|
|
39
|
+
* (a workspace laid out before the work directory); else `.flow-sdk/<name>`,
|
|
40
|
+
* where a new file goes. Pass `exists` to require more than presence (an
|
|
41
|
+
* overlay counts only once it has its `index.json`).
|
|
42
|
+
*/
|
|
43
|
+
export function workPath(name, options = {}) {
|
|
44
|
+
const exists = options.exists ?? existsSync;
|
|
45
|
+
const current = inWorkDir(name, options.cwd);
|
|
46
|
+
const legacy = options.cwd === undefined ? name : join(options.cwd, name);
|
|
47
|
+
if (exists(current)) {
|
|
48
|
+
// Both present is how an edit goes missing: a guide still names the root
|
|
49
|
+
// file, the author edits it, and every command keeps reading this one.
|
|
50
|
+
if (exists(legacy))
|
|
51
|
+
noteShadowed(current, legacy);
|
|
52
|
+
return current;
|
|
53
|
+
}
|
|
54
|
+
return exists(legacy) ? legacy : current;
|
|
55
|
+
}
|
|
56
|
+
const noted = new Set();
|
|
57
|
+
/** Say once per process that a root-level `legacy` is being ignored. */
|
|
58
|
+
function noteShadowed(current, legacy) {
|
|
59
|
+
if (noted.has(legacy))
|
|
60
|
+
return;
|
|
61
|
+
noted.add(legacy);
|
|
62
|
+
console.error(`flow-sdk: using ${current}; ${legacy} is also present and is ignored. Move its contents into ${current}, or pass the path explicitly.`);
|
|
63
|
+
}
|
|
64
|
+
/** {@link workPath} for a file that is only read: `undefined` when neither exists. */
|
|
65
|
+
export function existingWorkPath(name, options = {}) {
|
|
66
|
+
const exists = options.exists ?? existsSync;
|
|
67
|
+
const path = workPath(name, options);
|
|
68
|
+
return exists(path) ? path : undefined;
|
|
69
|
+
}
|
|
70
|
+
/** The default author-side `bindings.json`, when there is one. */
|
|
71
|
+
export function defaultBindingsFile(cwd) {
|
|
72
|
+
return existingWorkPath('bindings.json', { cwd });
|
|
73
|
+
}
|
|
74
|
+
/** The default `connectors-local/` overlay, once `registry prepare` has written its index. */
|
|
75
|
+
export function defaultOverlayDir(cwd) {
|
|
76
|
+
const exists = (dir) => existsSync(join(dir, 'index.json'));
|
|
77
|
+
return existingWorkPath('connectors-local', { cwd, exists });
|
|
78
|
+
}
|
|
79
|
+
/** Create the work directory under `cwd` (default: the current directory). */
|
|
80
|
+
export function ensureWorkDir(cwd) {
|
|
81
|
+
mkdirSync(cwd === undefined ? WORK_DIR : join(cwd, WORK_DIR), { recursive: true });
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* The work directory that goes with an authored `path`: the directory `path` is
|
|
85
|
+
* already in when that is a work directory, else `.flow-sdk/` beside it. A
|
|
86
|
+
* decompile's `.pipeline.mjs` helper and the candidates it writes go here.
|
|
87
|
+
*/
|
|
88
|
+
export function workDirBeside(path) {
|
|
89
|
+
const dir = dirname(path);
|
|
90
|
+
return basename(dir) === WORK_DIR ? dir : join(dir, WORK_DIR);
|
|
91
|
+
}
|
|
92
|
+
/** The default path of a decompiled source named `file`, creating the work directory. */
|
|
93
|
+
export function defaultSourceOut(file) {
|
|
94
|
+
ensureWorkDir();
|
|
95
|
+
return inWorkDir(file);
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@uipath/maestro-builder-sdk",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.13.0",
|
|
4
4
|
"description": "Build UiPath Flow, Case, and BPMN artifacts by writing TypeScript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"homepage": "https://docs.uipath.com/maestro",
|
|
@@ -92,5 +92,5 @@
|
|
|
92
92
|
"@types/node": "^22.7.0",
|
|
93
93
|
"esbuild": "^0.28.1"
|
|
94
94
|
},
|
|
95
|
-
"gitref": "
|
|
95
|
+
"gitref": "bf85d17e1d820f584329913c9ac836a2fbc23dec"
|
|
96
96
|
}
|