@effected/cli 0.21.0 → 0.22.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/Doc.js CHANGED
@@ -523,6 +523,11 @@ var Doc = class {
523
523
  * GitHub's log format only when it says GitHub Actions, and plain text otherwise, including when it is
524
524
  * absent. An explicit `format` is honoured whatever the audience.
525
525
  *
526
+ * The context is built here, at print time, so it carries the fiber's count of open Actions log groups
527
+ * (`RenderContext.groupDepth`): printed inside an `ActionLogger.group` from `@effected/github-actions`, a
528
+ * document's top-level collapsible renders as plain text rather than as a second `::group::`, which would end
529
+ * the open one at the runner.
530
+ *
526
531
  * @param doc - the document
527
532
  * @param options - the stream and the format
528
533
  */
package/Render.js CHANGED
@@ -8,11 +8,16 @@ import { renderAnsi } from "./internal/renderAnsi.js";
8
8
  import { renderPlain } from "./internal/renderPlain.js";
9
9
  import { renderGithubLog } from "./internal/renderGithubLog.js";
10
10
  import { renderMarkdown } from "./internal/renderMarkdown.js";
11
- import { Effect } from "effect";
11
+ import { Context, Effect } from "effect";
12
12
  import { Audience, TerminalEnv } from "@effected/env";
13
- import { CommandNeutralizer } from "@effected/github-commands";
13
+ import { CommandNeutralizer, WorkflowCommand } from "@effected/github-commands";
14
14
 
15
15
  // src/Render.ts
16
+ /**
17
+ * The fiber-local count of open Actions log groups, by the kit-wide key, so a group `@effected/github-actions`'
18
+ * `ActionLogger.group` opened is visible here without an edge between the two packages.
19
+ */
20
+ const GroupDepth = Context.Reference(WorkflowCommand.groupDepthKey, { defaultValue: () => 0 });
16
21
  /** A renderer's text, with workflow commands neutralized when the context says the runner is reading it. */
17
22
  const guarded = (text, ctx) => ctx.neutralizeWorkflowCommands === true ? CommandNeutralizer.text(text) : text;
18
23
  /**
@@ -53,7 +58,10 @@ var Render = class {
53
58
  * required), for every audience, since the runner reads whatever is written there;
54
59
  * - `width` is the option, else `TerminalEnv.width()` for a human whose stream is a terminal, and **unbounded**
55
60
  * (`Infinity`) for a human whose stream is not one (`tool | grep`, `tool > out.txt`), an agent or a CI, so nothing
56
- * a reader needs is truncated or wrapped for a terminal that is not there: a pipe has no width to honour.
61
+ * a reader needs is truncated or wrapped for a terminal that is not there: a pipe has no width to honour;
62
+ * - `groupDepth` is the fiber's count of open Actions log groups (the fiber-local keyed by
63
+ * `WorkflowCommand.groupDepthKey`, which `ActionLogger.group` provides), set when it is above `0`, so a
64
+ * document printed inside a group opens no second one; see {@link RenderContext.groupDepth}.
57
65
  *
58
66
  * @param stream - the stream the output is for
59
67
  * @param options - an explicit width and a path display function
@@ -64,8 +72,11 @@ var Render = class {
64
72
  const theme = (yield* CliTheme).forStream(stream);
65
73
  const seen = CliTheme.forAudience(theme, kind);
66
74
  const links = yield* CliLinks;
75
+ const underActions = yield* underGithubActions;
76
+ const groupDepth = yield* GroupDepth;
67
77
  return {
68
- ...(yield* underGithubActions) ? { neutralizeWorkflowCommands: true } : {},
78
+ ...underActions ? { neutralizeWorkflowCommands: true } : {},
79
+ ...groupDepth > 0 ? { groupDepth } : {},
69
80
  width: options?.width ?? (kind === "human" && terminal[stream].isTerminal ? terminal.width() : Number.POSITIVE_INFINITY),
70
81
  audience: kind,
71
82
  color: seen.color,
@@ -88,7 +99,8 @@ var Render = class {
88
99
  * with no escape of any kind. A colour level paints with the default token styles. An `agent` is colourless and
89
100
  * unlinked whatever `color` and `links` say, as in {@link Render.context}.
90
101
  *
91
- * @param options - the audience, and the colour, glyphs, width, path display, links, neutralizing and link base
102
+ * @param options - the audience, and the colour, glyphs, width, path display, links, neutralizing, link base and
103
+ * open group depth
92
104
  */
93
105
  static contextOf = (options) => {
94
106
  const agent = options.audience === "agent";
@@ -107,7 +119,8 @@ var Render = class {
107
119
  }),
108
120
  displayPath: options.displayPath ?? ((absolute) => absolute),
109
121
  ...options.neutralizeWorkflowCommands ?? options.audience === "ci" ? { neutralizeWorkflowCommands: true } : options.neutralizeWorkflowCommands === false ? { neutralizeWorkflowCommands: false } : {},
110
- ...options.linkBase === void 0 ? {} : { linkBase: options.linkBase }
122
+ ...options.linkBase === void 0 ? {} : { linkBase: options.linkBase },
123
+ ...options.groupDepth === void 0 ? {} : { groupDepth: options.groupDepth }
111
124
  };
112
125
  };
113
126
  /**
@@ -237,6 +250,15 @@ var Render = class {
237
250
  * top-level section. GitHub does not nest groups, so a collapsible inside a group, or inside a list or callout
238
251
  * (where it would not start a line), keeps plain's rendering: its title on a line and its body indented.
239
252
  *
253
+ * A group already open around the output counts the same way. When the context's `groupDepth` is above `0`
254
+ * ({@link RenderContext.groupDepth}, which `Render.context` reads from the fiber-local `ActionLogger.group` in
255
+ * `@effected/github-actions` provides, by the key `WorkflowCommand.groupDepthKey`), a top-level collapsible keeps
256
+ * plain's rendering too, so a document printed inside an `ActionLogger.group` does not open a second group, which
257
+ * would end the first at the runner. The depth is the context's, read when the context was built. What no depth
258
+ * can fix is two fibers writing groups at once: the runner has one log stream, so concurrent sibling groups, this
259
+ * renderer's or `ActionLogger`'s, interleave in it. Render and print a document from the fiber that owns the
260
+ * stream, not from a fiber racing another group.
261
+ *
240
262
  * The runner has two command parsers, and a line is a command if either accepts it: after its leading whitespace it
241
263
  * starts with `::`, or `##[` occurs ANYWHERE in it (a bare `##` is not one). A document's text must not be able to
242
264
  * do that (`::add-mask::`, `::error::`, `##[error]`), so such a `::` line gets a braille pattern blank (U+2800) in
package/index.d.ts CHANGED
@@ -1412,6 +1412,11 @@ export declare class Doc {
1412
1412
  * GitHub's log format only when it says GitHub Actions, and plain text otherwise, including when it is
1413
1413
  * absent. An explicit `format` is honoured whatever the audience.
1414
1414
  *
1415
+ * The context is built here, at print time, so it carries the fiber's count of open Actions log groups
1416
+ * (`RenderContext.groupDepth`): printed inside an `ActionLogger.group` from `@effected/github-actions`, a
1417
+ * document's top-level collapsible renders as plain text rather than as a second `::group::`, which would end
1418
+ * the open one at the runner.
1419
+ *
1415
1420
  * @param doc - the document
1416
1421
  * @param options - the stream and the format
1417
1422
  */
@@ -3209,6 +3214,20 @@ interface RenderContext {
3209
3214
  * cannot open. The other renderers do not read it.
3210
3215
  */
3211
3216
  readonly linkBase?: string | undefined;
3217
+ /**
3218
+ * How many GitHub Actions log groups are open around the output. Unset or `0`, none is: `Render.githubLog` then
3219
+ * writes a top-level collapsible as a `::group::`. Above `0` it writes the collapsible as plain does, its title on
3220
+ * a line and its body indented, because the runner does not nest groups and a second `::group::` would end the open
3221
+ * one. The other renderers do not read it.
3222
+ *
3223
+ * @remarks
3224
+ * `Render.context` reads it from the fiber-local keyed by `WorkflowCommand.groupDepthKey`
3225
+ * (`@effected/github-commands`), the count `ActionLogger.group` in `@effected/github-actions` provides around a
3226
+ * group's body, so a context built inside a group knows it. It is read when the context is built, not when a
3227
+ * document is rendered: a context built outside a group and used inside one still says none is open, so build it
3228
+ * where the document is printed, as `Doc.print` does.
3229
+ */
3230
+ readonly groupDepth?: number | undefined;
3212
3231
  }
3213
3232
  /**
3214
3233
  * Options for {@link Render.contextOf}.
@@ -3238,6 +3257,8 @@ interface RenderContextOfOptions {
3238
3257
  readonly neutralizeWorkflowCommands?: boolean | undefined;
3239
3258
  /** See {@link RenderContext.linkBase}; unset by default. */
3240
3259
  readonly linkBase?: string | undefined;
3260
+ /** See {@link RenderContext.groupDepth}; unset (no group open) by default. */
3261
+ readonly groupDepth?: number | undefined;
3241
3262
  }
3242
3263
  /**
3243
3264
  * Options for {@link Render.context}.
@@ -3292,7 +3313,10 @@ export declare class Render {
3292
3313
  * required), for every audience, since the runner reads whatever is written there;
3293
3314
  * - `width` is the option, else `TerminalEnv.width()` for a human whose stream is a terminal, and **unbounded**
3294
3315
  * (`Infinity`) for a human whose stream is not one (`tool | grep`, `tool > out.txt`), an agent or a CI, so nothing
3295
- * a reader needs is truncated or wrapped for a terminal that is not there: a pipe has no width to honour.
3316
+ * a reader needs is truncated or wrapped for a terminal that is not there: a pipe has no width to honour;
3317
+ * - `groupDepth` is the fiber's count of open Actions log groups (the fiber-local keyed by
3318
+ * `WorkflowCommand.groupDepthKey`, which `ActionLogger.group` provides), set when it is above `0`, so a
3319
+ * document printed inside a group opens no second one; see {@link RenderContext.groupDepth}.
3296
3320
  *
3297
3321
  * @param stream - the stream the output is for
3298
3322
  * @param options - an explicit width and a path display function
@@ -3307,7 +3331,8 @@ export declare class Render {
3307
3331
  * with no escape of any kind. A colour level paints with the default token styles. An `agent` is colourless and
3308
3332
  * unlinked whatever `color` and `links` say, as in {@link Render.context}.
3309
3333
  *
3310
- * @param options - the audience, and the colour, glyphs, width, path display, links, neutralizing and link base
3334
+ * @param options - the audience, and the colour, glyphs, width, path display, links, neutralizing, link base and
3335
+ * open group depth
3311
3336
  */
3312
3337
  static readonly contextOf: (options: RenderContextOfOptions) => RenderContext;
3313
3338
  /**
@@ -3437,6 +3462,15 @@ export declare class Render {
3437
3462
  * top-level section. GitHub does not nest groups, so a collapsible inside a group, or inside a list or callout
3438
3463
  * (where it would not start a line), keeps plain's rendering: its title on a line and its body indented.
3439
3464
  *
3465
+ * A group already open around the output counts the same way. When the context's `groupDepth` is above `0`
3466
+ * ({@link RenderContext.groupDepth}, which `Render.context` reads from the fiber-local `ActionLogger.group` in
3467
+ * `@effected/github-actions` provides, by the key `WorkflowCommand.groupDepthKey`), a top-level collapsible keeps
3468
+ * plain's rendering too, so a document printed inside an `ActionLogger.group` does not open a second group, which
3469
+ * would end the first at the runner. The depth is the context's, read when the context was built. What no depth
3470
+ * can fix is two fibers writing groups at once: the runner has one log stream, so concurrent sibling groups, this
3471
+ * renderer's or `ActionLogger`'s, interleave in it. Render and print a document from the fiber that owns the
3472
+ * stream, not from a fiber racing another group.
3473
+ *
3440
3474
  * The runner has two command parsers, and a line is a command if either accepts it: after its leading whitespace it
3441
3475
  * starts with `::`, or `##[` occurs ANYWHERE in it (a bare `##` is not one). A document's text must not be able to
3442
3476
  * do that (`::add-mask::`, `::error::`, `##[error]`), so such a `::` line gets a braille pattern blank (U+2800) in
@@ -32,6 +32,7 @@ const blockLines = (block, ctx) => {
32
32
  switch (block._tag) {
33
33
  case "Annotation": return [annotationLine(block)];
34
34
  case "Collapsible": {
35
+ if ((ctx.groupDepth ?? 0) > 0) return plainLines([block], ctx);
35
36
  const title = commandData(plainInline(block.title, ctx).map((span) => span.text).join(""));
36
37
  return [
37
38
  WorkflowCommand.group(title),
@@ -48,7 +49,8 @@ const blockLines = (block, ctx) => {
48
49
  }
49
50
  };
50
51
  /**
51
- * Render a document for a GitHub Actions log: plain text, with a top-level collapsible as a group.
52
+ * Render a document for a GitHub Actions log: plain text, with a top-level collapsible as a group when no group is
53
+ * open around the output (`ctx.groupDepth`).
52
54
  *
53
55
  * @internal
54
56
  */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@effected/cli",
3
- "version": "0.21.0",
3
+ "version": "0.22.0",
4
4
  "private": false,
5
5
  "description": "The presentation boundary of an effect/cli program: audience-aware output, a document IR and renderers, editor links, failure reports and logging, plus opt-in Ink screens, widgets and a live view",
6
6
  "keywords": [
@@ -57,10 +57,10 @@
57
57
  "./package.json": "./package.json"
58
58
  },
59
59
  "dependencies": {
60
- "@effected/github-commands": "^0.6.1"
60
+ "@effected/github-commands": "^0.6.2"
61
61
  },
62
62
  "peerDependencies": {
63
- "@effected/config-file": "^0.19.0",
63
+ "@effected/config-file": "^0.19.1",
64
64
  "@effected/env": "^0.5.0",
65
65
  "@effected/glob": "^0.14.0",
66
66
  "@effected/walker": "^0.19.0",
package/ui/UiKey.js CHANGED
@@ -7,6 +7,11 @@ const CONTROL = /[\u0000-\u001f\u007f]/;
7
7
  /**
8
8
  * Normalising Ink's input into {@link (UiKey:type)}s.
9
9
  *
10
+ * @remarks
11
+ * A typed `const` rather than the house static-class form by force, not by
12
+ * choice: a class cannot share its name with the {@link (UiKey:type)} union
13
+ * (TS2300, duplicate identifier), and that union is the key model itself.
14
+ *
10
15
  * @public
11
16
  */
12
17
  const UiKey = {
package/ui.d.ts CHANGED
@@ -621,6 +621,11 @@ export type UiKey = {
621
621
  /**
622
622
  * Normalising Ink's input into {@link (UiKey:type)}s.
623
623
  *
624
+ * @remarks
625
+ * A typed `const` rather than the house static-class form by force, not by
626
+ * choice: a class cannot share its name with the {@link (UiKey:type)} union
627
+ * (TS2300, duplicate identifier), and that union is the key model itself.
628
+ *
624
629
  * @public
625
630
  */
626
631
  export declare const UiKey: {