@pipelex/sdk 0.47.0 → 0.48.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +9 -7
  2. package/dist/artifacts.d.ts +4 -3
  3. package/dist/artifacts.js +20 -14
  4. package/dist/artifacts.js.map +1 -1
  5. package/dist/cli/script.d.ts +1 -1
  6. package/dist/cli/source.d.ts +8 -7
  7. package/dist/cli/source.js +11 -5
  8. package/dist/cli/source.js.map +1 -1
  9. package/dist/client.d.ts +326 -213
  10. package/dist/client.js +829 -517
  11. package/dist/client.js.map +1 -1
  12. package/dist/codegen-check.d.ts +2 -3
  13. package/dist/codegen-check.js +2 -3
  14. package/dist/codegen-check.js.map +1 -1
  15. package/dist/errors.d.ts +5 -2
  16. package/dist/errors.js +5 -2
  17. package/dist/errors.js.map +1 -1
  18. package/dist/hooks/bundle-gather.d.ts +47 -40
  19. package/dist/hooks/bundle-gather.js +121 -219
  20. package/dist/hooks/bundle-gather.js.map +1 -1
  21. package/dist/hooks/check-core.d.ts +70 -6
  22. package/dist/hooks/check-core.js +188 -29
  23. package/dist/hooks/check-core.js.map +1 -1
  24. package/dist/hooks/claude-mthds-check.d.ts +19 -5
  25. package/dist/hooks/claude-mthds-check.js +20 -53
  26. package/dist/hooks/claude-mthds-check.js.map +1 -1
  27. package/dist/hooks/secret-guard.d.ts +38 -0
  28. package/dist/hooks/secret-guard.js +134 -0
  29. package/dist/hooks/secret-guard.js.map +1 -0
  30. package/dist/hooks/validate-stage.d.ts +29 -0
  31. package/dist/hooks/validate-stage.js +66 -0
  32. package/dist/hooks/validate-stage.js.map +1 -0
  33. package/dist/index.d.ts +3 -4
  34. package/dist/index.js +4 -3
  35. package/dist/index.js.map +1 -1
  36. package/dist/method-trees.d.ts +220 -74
  37. package/dist/method-trees.js +250 -37
  38. package/dist/method-trees.js.map +1 -1
  39. package/dist/models.d.ts +162 -59
  40. package/dist/node-host/node.d.ts +33 -0
  41. package/dist/node-host/node.js +27 -0
  42. package/dist/node-host/node.js.map +1 -0
  43. package/dist/node-host/unavailable.d.ts +8 -0
  44. package/dist/node-host/unavailable.js +8 -0
  45. package/dist/node-host/unavailable.js.map +1 -0
  46. package/dist/node-host.d.ts +53 -0
  47. package/dist/node-host.js +72 -0
  48. package/dist/node-host.js.map +1 -0
  49. package/dist/prepare-inputs.d.ts +46 -27
  50. package/dist/prepare-inputs.js +123 -42
  51. package/dist/prepare-inputs.js.map +1 -1
  52. package/dist/product-models.d.ts +14 -16
  53. package/dist/upload.d.ts +4 -9
  54. package/dist/upload.js +13 -16
  55. package/dist/upload.js.map +1 -1
  56. package/dist/version.d.ts +1 -1
  57. package/dist/version.js +1 -1
  58. package/docs/architecture.md +44 -21
  59. package/docs/cli.md +1 -1
  60. package/docs/crate-routes.md +43 -21
  61. package/docs/errors.md +5 -5
  62. package/docs/hook-bundle.md +27 -1
  63. package/docs/input-preparation.md +13 -13
  64. package/docs/method-trees.md +120 -22
  65. package/docs/run-results.md +5 -2
  66. package/package.json +8 -2
  67. package/dist/bundle-resources.d.ts +0 -62
  68. package/dist/bundle-resources.js +0 -165
  69. package/dist/bundle-resources.js.map +0 -1
  70. package/docs/bundle-resources.md +0 -107
package/dist/models.d.ts CHANGED
@@ -8,8 +8,8 @@
8
8
  * the model reference check. Built on the protocol wire types imported from the
9
9
  * `mthds/protocol` subpath.
10
10
  */
11
- import type { InputForm, OutputForm, PipeIOContracts, RunResultExecute, RunResultStart } from "mthds/protocol";
12
- import type { BundleResources } from "./bundle-resources.js";
11
+ import type { InputForm, MethodFiles, MethodTreeSource, OutputForm, PipeIOContracts, RunResultExecute, RunResultStart } from "mthds/protocol";
12
+ import type { MethodTreeForm, NoMethodTree } from "./method-trees.js";
13
13
  export interface DictStuff {
14
14
  concept: string;
15
15
  content: unknown;
@@ -75,7 +75,7 @@ export interface PipelexRunResultStart extends RunResultStart {
75
75
  * The hosted tooling routes' own selector — the layer-3 extension the platform
76
76
  * adds on `POST /v1/validate`, `/v1/resolve`, `/v1/codegen`, and `/v1/pipe-io`: a stored
77
77
  * method's catalog id (`mt_…`), optionally naming a version, resolved server-side against
78
- * the org's catalog, the `.mthds` files of the version it names injected as inline source
78
+ * the org's catalog, the tree of the version it names injected as the method's `files`
79
79
  * before the runner sees the request. A bare `mt_…` names the latest published version,
80
80
  * `mt_…@<n>` version `n` and `mt_…@draft` the draft. A **pass-through to the hosted API**:
81
81
  * nothing is expanded client-side, and it is meaningless off-platform (a bare runner
@@ -97,11 +97,11 @@ export interface PipelexHostedToolingExtensions {
97
97
  method_id?: string;
98
98
  }
99
99
  /**
100
- * The method selector the tooling routes take in place of inline contents: a
100
+ * The method selector the tooling routes take in place of the method's tree: a
101
101
  * `method_ref` address (server-resolved by the runner through the same fetch
102
102
  * path as a `method_ref` run) OR a hosted `method_id` (platform-resolved) —
103
103
  * never both. The tooling routes are stateless, so the strict XOR applies:
104
- * exactly one of inline contents / `method_ref` / `method_id` per request.
104
+ * exactly one of the tree / `method_ref` / `method_id` per request.
105
105
  *
106
106
  * Lives here, beside the other wire shapes, rather than on the client: it is
107
107
  * the request's shape, and a module that composes a `validate` call of its own
@@ -115,6 +115,23 @@ export type ValidateMethodSelector = {
115
115
  method_id: string;
116
116
  method_ref?: never;
117
117
  };
118
+ /**
119
+ * What `validate()` judges: the method's tree, in exactly one of the four forms of
120
+ * `MethodTreeForm` (a `directory`, `contents`, a `tree` or the `files` map), or one of the two
121
+ * selectors of `ValidateMethodSelector`. Each arm pins the others to `never`, so naming two is a
122
+ * compile error; an untyped caller naming none, or more than one, is refused with a
123
+ * `RequestArgumentError` before any request, as the route itself would refuse a second selector
124
+ * with a `422`. At run time a `null` member, an empty `directory` and an empty selector string
125
+ * are absent, and a `files` map or `contents` holding no file is refused, as the MTHDS standard
126
+ * refuses a tree holding no file.
127
+ *
128
+ * It widens the protocol's own `ValidateSource` (`{ files }` or `{ tree }`) with the two forms
129
+ * this client lists or encodes itself and the two selectors the Pipelex API resolves.
130
+ */
131
+ export type PipelexValidateSource = (MethodTreeForm & {
132
+ method_ref?: never;
133
+ method_id?: never;
134
+ }) | (ValidateMethodSelector & NoMethodTree);
118
135
  /** Per-pipe dry-run verdict in `validated_pipes[]` — mirror of pipelex's `DryRunStatus`. */
119
136
  export type DryRunStatus = "SUCCESS" | "FAILURE" | "SKIPPED";
120
137
  /** One entry of `PipelexValidationReport.validated_pipes` — `{pipe_ref, status}`. */
@@ -139,6 +156,35 @@ export interface LiftablePipeEntry {
139
156
  /** Where the possible absence originates (human-readable). */
140
157
  absence_source: string;
141
158
  }
159
+ /**
160
+ * What a step reads a file of its method tree as — mirror of pipelex's `TreeFileUse`:
161
+ * `template`, the template a `PipeDocGen` step fills, named by its `template_file`;
162
+ * `template_asset`, an image, a stylesheet or a font that step's HTML template names by a
163
+ * literal relative URL, or that one of its stylesheets names; `python_module`, the module
164
+ * defining the function a `PipeFunc` step calls, named by the import path of its
165
+ * `function_name`.
166
+ *
167
+ * A report reads it open (see {@link TreeFileRead.use}): a runner of a later version may add
168
+ * a use as another kind of step comes to read files of its tree.
169
+ */
170
+ export type TreeFileUse = "template" | "template_asset" | "python_module";
171
+ /**
172
+ * One file of its method tree a step reads — mirror of pipelex's `TreeFileRead`, an entry of
173
+ * {@link PipelexValidationReport.tree_files_read}.
174
+ */
175
+ export interface TreeFileRead {
176
+ /**
177
+ * The file's path from the root of the method's tree, with forward slashes, such as
178
+ * `templates/invoice.html`, never a path on the server.
179
+ */
180
+ tree_path: string;
181
+ /**
182
+ * What the step reads the file as. Read open: `string & {}` keeps the editor's completion
183
+ * on the uses this SDK knows, and a consumer that switches on this field has to say what a
184
+ * use it does not know does.
185
+ */
186
+ use: TreeFileUse | (string & {});
187
+ }
142
188
  /**
143
189
  * Pipelex's `POST /v1/validate` 200 body for a VALID bundle — the canonical
144
190
  * `PipelexValidationReport`, carrying the `is_valid: true` discriminant of the
@@ -209,6 +255,27 @@ export interface PipelexValidationReport {
209
255
  output_form?: OutputForm;
210
256
  /** Pipes the runtime may skip when an optional slot resolves absent. */
211
257
  liftable_pipes: LiftablePipeEntry[];
258
+ /**
259
+ * Per step, the files of the method's tree it reads, keyed by namespaced `pipe_ref` over
260
+ * the same set as `pipe_io_contracts`, each file by its tree path with what the step reads
261
+ * it as. A `PipeDocGen` step reads its template and the images, stylesheets and fonts its
262
+ * HTML template names by literal relative URLs; a `PipeFunc` step reads the module of its
263
+ * function when that module is a file of the tree. A step that reads no file of the tree,
264
+ * a controller included, has an empty list. The paths come from what each step already
265
+ * names, so a client can show which step uses a file without parsing the method.
266
+ *
267
+ * OPTIONAL because a runner predating the field sends nothing: an absent field says the
268
+ * server did not report the reads, where an empty list says that step reads no file.
269
+ */
270
+ tree_files_read?: Record<string, TreeFileRead[]>;
271
+ /**
272
+ * The per-file view of `tree_files_read`: each tree path a step reads, in sorted order, to
273
+ * the namespaced refs of the steps that read it, each listed once. A file of the tree with
274
+ * no entry is read by no step: the bundles themselves, a README, a package's `__init__.py`
275
+ * beside its modules. Optional for the same reason as `tree_files_read`, and present
276
+ * whenever it is.
277
+ */
278
+ tree_file_readers?: Record<string, string[]>;
212
279
  /**
213
280
  * The qualified ref of the pipe a selector-less run of THIS request would execute —
214
281
  * the primary blueprint's declared `main_pipe` qualified by its domain and, for a
@@ -326,9 +393,8 @@ export type ValidationErrorCategory = "blueprint_validation" | "pipe_factory" |
326
393
  * not, so the same item arrives with explicit `null`s there. A truthiness check reads
327
394
  * both; an `=== undefined` check would be wrong on one of them.
328
395
  *
329
- * `source` is the declaring file path (CLI) or the per-content `mthds_sources` name
330
- * the API threads onto the in-memory load path — the owning file for cross-file
331
- * diagnostics.
396
+ * `source` is the declaring file: its path (CLI), or its tree path in the tree the
397
+ * request sent — the owning file for cross-file diagnostics.
332
398
  *
333
399
  * An `unknown_model` item (a model reference the runner's model deck does not know)
334
400
  * carries the reference as written, the kind of model the field takes and the close
@@ -514,50 +580,84 @@ export interface FormatResponse {
514
580
  diagnostics: Diagnostic[];
515
581
  }
516
582
  /**
517
- * One MTHDS file in a crate closure. `source` is an optional provenance label (a
518
- * filename, a URI) that the server threads onto every diagnostic it raises from
519
- * this file, so an invalid verdict can point at the file that caused it.
583
+ * The method every crate route takes — `/v1/resolve`, `/v1/codegen` and `/v1/pipe-io`
584
+ * (mirror of the runner's `MethodTreeRequest`).
520
585
  *
521
- * NOT the same type as `MthdsFile` (the one `validateFiles()` takes), which the
522
- * client adapts into `/v1/validate`'s parallel `mthds_contents` + `mthds_sources`
523
- * arrays: that route spells the label `uri`, this envelope spells it `source`. The
524
- * two collapse into one only if `/v1/validate` ever migrates onto `files[]` — a
525
- * protocol-level change owned by the MTHDS standard, not ours to make here.
526
- */
527
- export interface MthdsFileItem {
528
- content: string;
529
- source?: string;
530
- }
531
- /**
532
- * The closure selector every crate route shares — `/v1/resolve`, `/v1/codegen` and
533
- * `/v1/pipe-io` (mirror of the server's `MthdsFilesRequest`).
586
+ * Supply the method EITHER as its tree OR as a `method_ref` — never both, and never neither
587
+ * (both arms are a request-shape `422`); the hosted `method_id` joins them as a third form on
588
+ * each route's own request (see {@link PipelexHostedToolingExtensions}). The tree is the MTHDS
589
+ * protocol's map of file entries, keyed by tree path, given in exactly one of the four forms
590
+ * every route takes (`MethodTreeForms`):
534
591
  *
535
- * Supply the closure EITHER as inline `files` OR as a `method_ref` — never both, and
536
- * never neither (both arms are a request-shape `422`); the hosted `method_id` joins
537
- * them as a third form on each route's own request (see
538
- * {@link PipelexHostedToolingExtensions}). An **address-form** `method_ref`
539
- * (`github.com/<owner>/<repo>[/<selector>][@<tag>]`) is resolved by the server
540
- * (pipelex-api >= 0.21.0): the repository is fetched at the tag, the package is
541
- * located by manifest identity, and its `.mthds` files feed the closure with their
542
- * real relative paths as per-file sources. The **registry form** (any non-address
543
- * reference) stays reserved and answers `501` until a method registry exists.
592
+ * - `directory`, the method's directory on disk, listed by the `mthds` package's lister under
593
+ * the standard's membership rule and the deployment's limits (Node only);
594
+ * - `contents`, each file's bytes or text by tree path;
595
+ * - `tree`, a `MethodTreeSource`, such as the `MethodTree` the `mthds` package's
596
+ * `listMethodTree` returns;
597
+ * - `files`, the map itself, each value the file's text, `{ base64 }` or `{ sha256, size }` for
598
+ * bytes the runner already holds, sent as given.
544
599
  *
545
- * The XOR is a server-side invariant, not a type-level one: expressing it as a union
546
- * here would make the common `{ files }` call site pick a branch for no gain, and the
547
- * server rejects the illegal shapes with a typed `ApiResponseError` either way.
600
+ * The client sends a `directory`, `contents` or `tree` inline when its inline map weighs 256 KiB
601
+ * or less and no more than the inline limit the API announces, or whatever its weight when the
602
+ * API keeps no blob store, and otherwise every file by hash, after uploading the files the API
603
+ * lacks, exactly as `createMethod` sends one (see `docs/method-trees.md`). Every `.mthds` file of
604
+ * the tree is one of the method's bundles, named by its tree path in diagnostics and in the
605
+ * crate's `source_map`, and every other file is one a step may read, such as a `PipeDocGen`
606
+ * template.
548
607
  *
549
- * `resources` accompanies inline `files`: the files the closure's steps read, such as a
550
- * `PipeDocGen` step's `template_file`, keyed by the path the step names, each as its bytes,
551
- * which the client encodes into the wire's base64 map before posting (see
552
- * `docs/bundle-resources.md`). It is the one member the client does not post verbatim. Beside
553
- * a `method_ref` it is the server's `422`, a published method's files being its package's
554
- * own; a step whose template file was not sent makes the closure invalid.
608
+ * An **address-form** `method_ref` (`github.com/<owner>/<repo>[/<selector>][@<tag>]`) is
609
+ * resolved by the server (pipelex-api >= 0.21.0): the package's whole tree is fetched at the tag
610
+ * and read as a tree sent in `files` is. The **registry form** (any non-address reference) stays
611
+ * reserved and answers `501` until a method registry exists.
612
+ *
613
+ * The XOR is a server-side invariant, not a type-level one: expressing it as a union here would
614
+ * make the common `{ files }` call site pick a branch for no gain, and the server rejects the
615
+ * illegal shapes with a typed `ApiResponseError` either way. Two forms of the tree at once are
616
+ * the one shape the client refuses itself, with a `RequestArgumentError`, since it prepares the
617
+ * tree before posting. An empty map or string is absent, as in the Python SDK: `files: {}`,
618
+ * `files: null`, `contents: {}`, `directory: ""` and `dependencies: {}` select and send nothing,
619
+ * so an empty one beside another selector never reaches the wire as a second selector.
620
+ *
621
+ * `dependencies` accompanies the tree: the method packages it calls by address that the runner
622
+ * cannot fetch, each a map of file entries keyed by its address, sent as given. These routes load
623
+ * a package the method calls only from what was shipped with it, so a call into one nothing
624
+ * shipped is the invalid verdict.
625
+ *
626
+ * The files the closure's steps read, such as a `PipeDocGen` step's `template_file`, are files of
627
+ * the tree like any other, so a directory sends them with its bundles.
628
+ *
629
+ * `read_scope` is the Pipelex API's scope the request reads the method under: a hash entry of
630
+ * `files` resolves in that scope's blob store, else in the caller's own. A tree sent by hash asks
631
+ * `POST /v1/blobs/missing` under the same scope, so its blobs are uploaded into the store the
632
+ * request reads. **The hosted platform ignores it**: it stamps the caller's organization as the
633
+ * read scope of every crate request and drops the one the caller sent, so it only reaches a
634
+ * runner called directly.
555
635
  */
556
636
  export interface CrateRequestBase {
557
- files?: MthdsFileItem[];
637
+ /** The method's directory, listed by the standard's lister and sent as `tree` is. Node only. */
638
+ directory?: string | null;
639
+ /** The method's files, each one's bytes or text by tree path, sent as `tree` is. */
640
+ contents?: Readonly<Record<string, Uint8Array | string>> | null;
641
+ /** The method's tree as a listed source, sent inline when small and by hash otherwise. */
642
+ tree?: MethodTreeSource | null;
643
+ /** The method's tree as the protocol's map of file entries, sent as given. */
644
+ files?: MethodFiles | null;
645
+ /** The method packages the tree calls by address, each a map of file entries keyed by its address. */
646
+ dependencies?: Record<string, MethodFiles>;
558
647
  method_ref?: string;
559
- /** The files the closure's steps read, keyed by the path a step names, each as its bytes. */
560
- resources?: BundleResources | null;
648
+ /** The scope the runner reads the tree under; the hosted platform replaces it with the caller's organization. */
649
+ read_scope?: string;
650
+ }
651
+ /**
652
+ * What a crate route call — `resolve`, `codegen`, `pipeIo` — takes beside its request.
653
+ *
654
+ * `signal` is read between the steps a `tree` or `contents` costs before the request, and before
655
+ * the request itself: once it has aborted, no further file of the tree is read, neither the blob
656
+ * route nor an upload starts, and the route is not asked, and the call throws the abort. A request
657
+ * already sent runs to its end, as in `prepareInputs`, which passes its own `signal` here.
658
+ */
659
+ export interface CrateRouteOptions {
660
+ signal?: AbortSignal;
561
661
  }
562
662
  /**
563
663
  * The `is_valid: false` arm shared by every crate route — `/v1/resolve`,
@@ -578,7 +678,7 @@ export interface CrateInvalidReport {
578
678
  }
579
679
  /**
580
680
  * `POST /v1/resolve` request — the crate envelope (no projection axes) plus the
581
- * hosted `method_id` selector. Exactly one of `files` / `method_ref` /
681
+ * hosted `method_id` selector. Exactly one of the tree / `method_ref` /
582
682
  * `method_id` — the strict tooling XOR; see {@link PipelexHostedToolingExtensions}.
583
683
  */
584
684
  export type ResolveRequest = CrateRequestBase & PipelexHostedToolingExtensions;
@@ -626,7 +726,7 @@ export type CodegenKind = "types";
626
726
  export type CodegenTarget = "ts-zod" | "python-pydantic" | "python-structures";
627
727
  /**
628
728
  * `POST /v1/codegen` request — the crate envelope plus the two explicit projection
629
- * axes and the hosted `method_id` selector (exactly one of `files` / `method_ref` /
729
+ * axes and the hosted `method_id` selector (exactly one of the tree / `method_ref` /
630
730
  * `method_id`; see {@link PipelexHostedToolingExtensions}).
631
731
  */
632
732
  export interface CodegenRequest extends CrateRequestBase, PipelexHostedToolingExtensions {
@@ -677,7 +777,7 @@ export interface CodegenValidReport {
677
777
  export type CodegenResponse = CodegenValidReport | CrateInvalidReport;
678
778
  /**
679
779
  * `POST /v1/pipe-io` request — the crate envelope plus the hosted `method_id` selector
680
- * (exactly one of `files` / `method_ref` / `method_id`; see
780
+ * (exactly one of the tree / `method_ref` / `method_id`; see
681
781
  * {@link PipelexHostedToolingExtensions}), a pipe selector, and two opt-ins.
682
782
  *
683
783
  * There is no `views` field: the valid arm always carries all three artifacts.
@@ -685,8 +785,9 @@ export type CodegenResponse = CodegenValidReport | CrateInvalidReport;
685
785
  export interface PipeIORequest extends CrateRequestBase, PipelexHostedToolingExtensions {
686
786
  /**
687
787
  * The pipe to describe, as a QUALIFIED `domain.pipe_code` ref. Omit it and the
688
- * server's selection chain decides: a fetched package's manifest `main_pipe`, else
689
- * the closure's single `main_pipe` declaration. A selection the server refuses is a
788
+ * server's selection chain decides: the `main_pipe` of the `METHODS.toml` at the tree's
789
+ * root, whether the tree was sent or fetched, else the closure's single `main_pipe`
790
+ * declaration. A selection the server refuses is a
690
791
  * `422` typed by what went wrong, with `error_domain: "input"` and the candidates, where
691
792
  * there are some, in its `detail`: `EntryPipeNotFoundError` for a ref that names no pipe
692
793
  * or (without `all_pipes`) a method with no entry pipe, `EntryPipeAmbiguousError` for a
@@ -705,9 +806,9 @@ export interface PipeIORequest extends CrateRequestBase, PipelexHostedToolingExt
705
806
  */
706
807
  all_pipes?: boolean;
707
808
  /**
708
- * Echo the resolved closure's `.mthds` files on the valid arm as `files`, in the
709
- * request's own `files[]` shape. Defaults to `false` server-side, and the field is then
710
- * absent from the answer.
809
+ * Echo the text of the method's own `.mthds` bundles on the valid arm as `files`, keyed
810
+ * by tree path. Defaults to `false` server-side, and the field is then absent from the
811
+ * answer.
711
812
  */
712
813
  include_files?: boolean;
713
814
  }
@@ -739,7 +840,8 @@ export interface PipeIOValidReport {
739
840
  output_form: OutputForm;
740
841
  /**
741
842
  * The method's own entry pipe: the selection chain without the request's `pipe_ref` —
742
- * the fetched manifest's `main_pipe`, else the closure's single declaration. A request
843
+ * the `main_pipe` of the `METHODS.toml` at the tree's root, sent or fetched, else the
844
+ * closure's single declaration. A request
743
845
  * that omits `pipe_ref` always answers `pipe_ref === default_pipe_ref`. A stated `null`
744
846
  * when the chain finds none or several.
745
847
  *
@@ -752,12 +854,13 @@ export interface PipeIOValidReport {
752
854
  /** `pending_signatures` is empty, as on `validate`. No dry run backs it. */
753
855
  is_runnable: boolean;
754
856
  /**
755
- * The resolved closure's `.mthds` files, in the request's `files[]` shape. Present only
756
- * when the request passed `include_files: true`: the request's files for inline
757
- * `files`, the fetched package's `.mthds` files under their package-relative paths for
758
- * a `method_ref`, the stored files under their stored names for a hosted `method_id`.
857
+ * The text of each `.mthds` bundle of the method's own tree, keyed by its tree path.
858
+ * Present only when the request passed `include_files: true`: for a tree the request
859
+ * sent, its bundles, whatever entry form carried them; for a `method_ref`, the fetched
860
+ * package's, keyed by their path from the package root; for a hosted `method_id`, the
861
+ * stored tree's. The tree's other files and its dependencies' bundles are never included.
759
862
  */
760
- files?: MthdsFileItem[];
863
+ files?: Record<string, string>;
761
864
  }
762
865
  /** The `POST /v1/pipe-io` 200 response — pattern-match `is_valid` before reading the arm. */
763
866
  export type PipeIOResponse = PipeIOValidReport | CrateInvalidReport;
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The Node host as Node resolves it: the one module of the SDK that loads what only Node has,
3
+ * `node:fs/promises`, `node:path`, the `mthds` package's tree lister and `undici`'s `Agent`.
4
+ *
5
+ * Nothing imports this file by its path. `src/node-host.ts` reaches it through `#node-host`, the
6
+ * package's own subpath import, which `package.json` maps to this file under the `node` condition
7
+ * and to `./unavailable.ts` under every other condition set, so a bundler building for a browser
8
+ * or an edge runtime never follows it (see `src/node-host.ts`).
9
+ *
10
+ * The two built-ins load with the host. The `mthds` root entry and `undici` are heavier, and only
11
+ * listing a directory or fetching an artifact needs one of them, so each loads on its first use.
12
+ */
13
+ import * as fs from "node:fs/promises";
14
+ import * as path from "node:path";
15
+ import type { MethodTreeError, listMethodTree } from "mthds";
16
+ import type { Agent } from "undici";
17
+ /** The `mthds` package's lister of a method directory, and the error it refuses a tree with. */
18
+ export interface TreeLister {
19
+ readonly listMethodTree: typeof listMethodTree;
20
+ readonly MethodTreeError: typeof MethodTreeError;
21
+ }
22
+ /** What only Node has, as the SDK uses it. */
23
+ export interface NodeHost {
24
+ /** `node:fs/promises`. */
25
+ readonly fs: typeof fs;
26
+ /** `node:path`. */
27
+ readonly path: typeof path;
28
+ /** The `mthds` root entry's tree lister, loading that entry on the first call. */
29
+ loadTreeLister(): Promise<TreeLister>;
30
+ /** `undici`'s `Agent`, loading `undici` on the first call. */
31
+ loadAgent(): Promise<typeof Agent>;
32
+ }
33
+ export declare const nodeHost: NodeHost;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * The Node host as Node resolves it: the one module of the SDK that loads what only Node has,
3
+ * `node:fs/promises`, `node:path`, the `mthds` package's tree lister and `undici`'s `Agent`.
4
+ *
5
+ * Nothing imports this file by its path. `src/node-host.ts` reaches it through `#node-host`, the
6
+ * package's own subpath import, which `package.json` maps to this file under the `node` condition
7
+ * and to `./unavailable.ts` under every other condition set, so a bundler building for a browser
8
+ * or an edge runtime never follows it (see `src/node-host.ts`).
9
+ *
10
+ * The two built-ins load with the host. The `mthds` root entry and `undici` are heavier, and only
11
+ * listing a directory or fetching an artifact needs one of them, so each loads on its first use.
12
+ */
13
+ import * as fs from "node:fs/promises";
14
+ import * as path from "node:path";
15
+ export const nodeHost = {
16
+ fs,
17
+ path,
18
+ async loadTreeLister() {
19
+ const { listMethodTree, MethodTreeError } = await import("mthds");
20
+ return { listMethodTree, MethodTreeError };
21
+ },
22
+ async loadAgent() {
23
+ const { Agent } = await import("undici");
24
+ return Agent;
25
+ },
26
+ };
27
+ //# sourceMappingURL=node.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node.js","sourceRoot":"","sources":["../../src/node-host/node.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACvC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAC;AAsBlC,MAAM,CAAC,MAAM,QAAQ,GAAa;IAChC,EAAE;IACF,IAAI;IACJ,KAAK,CAAC,cAAc;QAClB,MAAM,EAAE,cAAc,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,OAAO,CAAC,CAAC;QAClE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,CAAC;IAC7C,CAAC;IACD,KAAK,CAAC,SAAS;QACb,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,MAAM,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,KAAK,CAAC;IACf,CAAC;CACF,CAAC"}
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The Node host as every runtime other than Node resolves it: absent. `package.json` maps
3
+ * `#node-host` to this file under every condition set without `node`, a browser's or an edge
4
+ * runtime's, so the graph a bundler follows there holds no Node built-in, no `undici` and not the
5
+ * `mthds` root entry (see `src/node-host.ts`). It imports nothing at run time.
6
+ */
7
+ import type { NodeHost } from "./node.js";
8
+ export declare const nodeHost: NodeHost | null;
@@ -0,0 +1,8 @@
1
+ /**
2
+ * The Node host as every runtime other than Node resolves it: absent. `package.json` maps
3
+ * `#node-host` to this file under every condition set without `node`, a browser's or an edge
4
+ * runtime's, so the graph a bundler follows there holds no Node built-in, no `undici` and not the
5
+ * `mthds` root entry (see `src/node-host.ts`). It imports nothing at run time.
6
+ */
7
+ export const nodeHost = null;
8
+ //# sourceMappingURL=unavailable.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"unavailable.js","sourceRoot":"","sources":["../../src/node-host/unavailable.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,MAAM,CAAC,MAAM,QAAQ,GAAoB,IAAI,CAAC"}
@@ -0,0 +1,53 @@
1
+ /**
2
+ * The Node host: what the SDK uses that only Node has, behind one import that a bundler building
3
+ * for any other runtime never follows. See `docs/architecture.md`, "The Node host".
4
+ *
5
+ * The operations that need Node, reading a local path (`upload.ts`), downloading a run's files and
6
+ * the undici dispatcher of an artifact fetch (`artifacts.ts`), listing a method directory and
7
+ * writing a saved tree to disk (`method-trees.ts`), get it from `loadNodeHost()`, and never import
8
+ * a Node built-in, `undici` or the `mthds` root entry themselves. `loadNodeHost()` imports
9
+ * `#node-host`, the package's own subpath import, which the `imports` map of `package.json`
10
+ * resolves by condition: under `node` to `node-host/node.ts`, which holds those modules, and under
11
+ * every other condition set, a browser's or an edge runtime's, to `node-host/unavailable.ts`,
12
+ * which holds none. A bundler building for the browser therefore follows no Node built-in from the
13
+ * barrel, statically or dynamically, and `tests/browser-bundle.test.ts` bundles the built package
14
+ * for the browser to hold it to that. Node resolves the same import under its own condition, so
15
+ * the Node-only operations work there as they always did. Where the host cannot be had, outside
16
+ * Node, inside it without the `node` condition, or where the import itself fails, `loadNodeHost()`
17
+ * answers why rather than throwing, so each operation refuses with its own class and verdict.
18
+ */
19
+ import type { NodeHost } from "./node-host/node.js";
20
+ export type { NodeHost, TreeLister } from "./node-host/node.js";
21
+ /** True when running under Node (has `process.versions.node`). */
22
+ export declare function isNodeRuntime(): boolean;
23
+ /**
24
+ * The Node host could not be had: why, for a refusal to say, and the error behind it when the
25
+ * host's import failed.
26
+ */
27
+ export interface NodeHostAbsence {
28
+ readonly host: null;
29
+ /**
30
+ * Why, as a clause a refusal puts after its own subject; `null` outside Node, where the
31
+ * operation's own "Node only" refusal is the right one.
32
+ */
33
+ readonly reason: string | null;
34
+ /** The import's own error, when the host's import failed rather than resolving to nothing. */
35
+ readonly cause?: unknown;
36
+ }
37
+ /** The Node host, or why it could not be had. */
38
+ export type NodeHostLoad = {
39
+ readonly host: NodeHost;
40
+ } | NodeHostAbsence;
41
+ /**
42
+ * The Node host, or its absence and why, in three cases: a runtime that is not Node; Node itself
43
+ * where the package was resolved without the `node` export condition, so `#node-host` resolved to
44
+ * the variant holding nothing; and Node where the import of `#node-host` failed, as in a
45
+ * toolchain that does not resolve the `imports` map of `package.json`, whose error is the
46
+ * absence's `cause`. It never throws, so every operation needing Node refuses with its own class
47
+ * and verdict. The runtime is checked first, so nothing is loaded where it is not Node.
48
+ */
49
+ export declare function loadNodeHost(): Promise<NodeHostLoad>;
50
+ /** The `cause` option of a refusal made for `absence`: the import's own error, when there is one. */
51
+ export declare function absenceCause(absence: NodeHostAbsence): {
52
+ cause?: unknown;
53
+ };
@@ -0,0 +1,72 @@
1
+ /**
2
+ * The Node host: what the SDK uses that only Node has, behind one import that a bundler building
3
+ * for any other runtime never follows. See `docs/architecture.md`, "The Node host".
4
+ *
5
+ * The operations that need Node, reading a local path (`upload.ts`), downloading a run's files and
6
+ * the undici dispatcher of an artifact fetch (`artifacts.ts`), listing a method directory and
7
+ * writing a saved tree to disk (`method-trees.ts`), get it from `loadNodeHost()`, and never import
8
+ * a Node built-in, `undici` or the `mthds` root entry themselves. `loadNodeHost()` imports
9
+ * `#node-host`, the package's own subpath import, which the `imports` map of `package.json`
10
+ * resolves by condition: under `node` to `node-host/node.ts`, which holds those modules, and under
11
+ * every other condition set, a browser's or an edge runtime's, to `node-host/unavailable.ts`,
12
+ * which holds none. A bundler building for the browser therefore follows no Node built-in from the
13
+ * barrel, statically or dynamically, and `tests/browser-bundle.test.ts` bundles the built package
14
+ * for the browser to hold it to that. Node resolves the same import under its own condition, so
15
+ * the Node-only operations work there as they always did. Where the host cannot be had, outside
16
+ * Node, inside it without the `node` condition, or where the import itself fails, `loadNodeHost()`
17
+ * answers why rather than throwing, so each operation refuses with its own class and verdict.
18
+ */
19
+ /** True when running under Node (has `process.versions.node`). */
20
+ export function isNodeRuntime() {
21
+ return (typeof process !== "undefined" && process.versions != null && process.versions.node != null);
22
+ }
23
+ /**
24
+ * Inside Node, the package was resolved without the `node` export condition, as a bundle built
25
+ * for the browser or for esbuild's `neutral` platform resolves it, so `#node-host` resolved to the
26
+ * variant holding nothing.
27
+ */
28
+ const NODE_CONDITION_MISSING = 'this copy of @pipelex/sdk runs in Node but was resolved without the "node" export ' +
29
+ "condition, which selects the part of the package that reaches Node's file system. Bundle " +
30
+ 'it for Node (esbuild platform "node", webpack target "node"), add "node" to the bundler\'s ' +
31
+ "conditions (esbuild conditions, webpack resolve.conditionNames, Vite resolve.conditions), " +
32
+ "or leave @pipelex/sdk out of the bundle.";
33
+ /**
34
+ * Inside Node, the import of `#node-host` itself failed: the toolchain loading the package does
35
+ * not resolve the `imports` map of `package.json`, as Jest before 29.4 does not, or the package is
36
+ * installed in part. `detail` is the import's own error message.
37
+ */
38
+ function hostImportFailed(detail) {
39
+ return (`the Node host of @pipelex/sdk could not be loaded (${detail}). The SDK reaches Node's file ` +
40
+ 'system through "#node-host", an entry of the "imports" map of its package.json, and a ' +
41
+ 'toolchain that does not resolve package "imports", such as Jest before 29.4, cannot load ' +
42
+ "it: run under one that does, such as Node's own loader, Jest 29.4 or later or a current " +
43
+ "bundler, or reinstall @pipelex/sdk if it is installed in part.");
44
+ }
45
+ /**
46
+ * The Node host, or its absence and why, in three cases: a runtime that is not Node; Node itself
47
+ * where the package was resolved without the `node` export condition, so `#node-host` resolved to
48
+ * the variant holding nothing; and Node where the import of `#node-host` failed, as in a
49
+ * toolchain that does not resolve the `imports` map of `package.json`, whose error is the
50
+ * absence's `cause`. It never throws, so every operation needing Node refuses with its own class
51
+ * and verdict. The runtime is checked first, so nothing is loaded where it is not Node.
52
+ */
53
+ export async function loadNodeHost() {
54
+ if (!isNodeRuntime())
55
+ return { host: null, reason: null };
56
+ let loaded;
57
+ try {
58
+ loaded = await import("#node-host");
59
+ }
60
+ catch (cause) {
61
+ const detail = cause instanceof Error ? cause.message : String(cause);
62
+ return { host: null, reason: hostImportFailed(detail), cause };
63
+ }
64
+ return loaded.nodeHost === null
65
+ ? { host: null, reason: NODE_CONDITION_MISSING }
66
+ : { host: loaded.nodeHost };
67
+ }
68
+ /** The `cause` option of a refusal made for `absence`: the import's own error, when there is one. */
69
+ export function absenceCause(absence) {
70
+ return absence.cause === undefined ? {} : { cause: absence.cause };
71
+ }
72
+ //# sourceMappingURL=node-host.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"node-host.js","sourceRoot":"","sources":["../src/node-host.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAMH,kEAAkE;AAClE,MAAM,UAAU,aAAa;IAC3B,OAAO,CACL,OAAO,OAAO,KAAK,WAAW,IAAI,OAAO,CAAC,QAAQ,IAAI,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,IAAI,IAAI,CAC5F,CAAC;AACJ,CAAC;AAoBD;;;;GAIG;AACH,MAAM,sBAAsB,GAC1B,oFAAoF;IACpF,2FAA2F;IAC3F,6FAA6F;IAC7F,4FAA4F;IAC5F,0CAA0C,CAAC;AAE7C;;;;GAIG;AACH,SAAS,gBAAgB,CAAC,MAAc;IACtC,OAAO,CACL,sDAAsD,MAAM,iCAAiC;QAC7F,wFAAwF;QACxF,2FAA2F;QAC3F,0FAA0F;QAC1F,gEAAgE,CACjE,CAAC;AACJ,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY;IAChC,IAAI,CAAC,aAAa,EAAE;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;IAC1D,IAAI,MAA8C,CAAC;IACnD,IAAI,CAAC;QACH,MAAM,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,CAAC;IACtC,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,MAAM,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QACtE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,gBAAgB,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;IACjE,CAAC;IACD,OAAO,MAAM,CAAC,QAAQ,KAAK,IAAI;QAC7B,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,sBAAsB,EAAE;QAChD,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,CAAC,QAAQ,EAAE,CAAC;AAChC,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,YAAY,CAAC,OAAwB;IACnD,OAAO,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;AACrE,CAAC"}