@sanity/workflow-cli 0.33.0 → 0.35.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/CHANGELOG.md CHANGED
@@ -1,5 +1,76 @@
1
1
  # @sanity/workflow-cli
2
2
 
3
+ ## 0.35.0
4
+
5
+ ### Minor Changes
6
+
7
+ - a3489d2: Workflows CLI commands now load `sanity.workflow.ts` in projects using
8
+ TypeScript 7. `blueprint generate` and `blueprint generate --check` work with
9
+ TypeScript 6, TypeScript 7, or no project TypeScript installation: the CLI
10
+ supplies its own TypeScript 6 compatibility compiler for editing an existing
11
+ `sanity.blueprint.ts`. Direct generator callers can pass that API through
12
+ `emissionWritePlan({compiler})` or as the second argument to `wireBlueprint`.
13
+ When no usable compiler is available, direct wiring reports how to supply one.
14
+ The Blueprint package root now exports `CONFIG_FILE_NAMES` so custom loaders
15
+ can share the same config discovery order without importing the generator.
16
+ The workflow engine and generated function runtimes do not acquire a compiler
17
+ dependency.
18
+
19
+ **No upgrade action required.** Install the updated Workflows release normally;
20
+ keep your project's TypeScript version and existing config files.
21
+
22
+ **Docs impact:** Update the Blueprint generation reference to explain the
23
+ optional compiler argument and root `CONFIG_FILE_NAMES` export for direct
24
+ callers, and the CLI installation guidance to say Blueprint commands work in
25
+ projects using TypeScript 6, TypeScript 7, or no installed TypeScript.
26
+
27
+ ### Patch Changes
28
+
29
+ - 2f040b6: The README's Telemetry section now states the payload policy as an explicit
30
+ collected / never-collected pair, governed by
31
+ [Sanity's telemetry policy](https://www.sanity.io/telemetry), replacing the
32
+ claim that payloads never include customer-authored strings. That claim was
33
+ wrong in three ways it is worth knowing about: the dataset name is sent as a
34
+ session property, effect events carry the author-chosen effect name, and the
35
+ deployment tag reaches telemetry inside `instanceId`, whose engine-minted form
36
+ is `<tag>.wf-instance.<random>`. A caller-supplied instance id is sent
37
+ verbatim. Nothing about what the CLI sends changes; only the description of it
38
+ does.
39
+
40
+ The never-collected list now separates what the company policy excludes from
41
+ what this package additionally chooses not to send. Flag values, definition
42
+ names, and stage names sit in the second group: the policy does not prohibit
43
+ them, so do not read their absence here as a company-wide guarantee. Error
44
+ messages sit there too, with the policy permitting error information that
45
+ excludes sensitive data while this package sends none.
46
+
47
+ **No upgrade action required.** Review the new lists if you assessed this
48
+ package's telemetry against the previous wording, in particular if your
49
+ deployment tags or instance ids encode something you would not want in an
50
+ analytics pipeline. Consent and opt-out are unchanged: account-level
51
+ `sanity telemetry disable`, `DO_NOT_TRACK`, and CI suppression all behave as
52
+ before.
53
+
54
+ **Docs impact:** The Telemetry section of the package README is the change.
55
+ Any internal analytics or privacy guidance quoting the old
56
+ "never include customer-authored strings" sentence needs the same correction,
57
+ and guidance that assumes deployment tags are absent from telemetry should be
58
+ revisited.
59
+
60
+ - Updated dependencies [a3489d2]
61
+ - Updated dependencies [7e24e4a]
62
+ - Updated dependencies [ab8754a]
63
+ - @sanity/workflow-blueprint@0.35.0
64
+ - @sanity/workflow-engine@0.35.0
65
+
66
+ ## 0.34.0
67
+
68
+ ### Patch Changes
69
+
70
+ - Updated dependencies [00bb88f]
71
+ - @sanity/workflow-blueprint@0.34.0
72
+ - @sanity/workflow-engine@0.34.0
73
+
3
74
  ## 0.33.0
4
75
 
5
76
  ### Minor Changes
package/README.md CHANGED
@@ -225,6 +225,9 @@ start instances from document writes. `blueprint generate` derives that runtime
225
225
  from the definitions and writes it next to `sanity.workflow.ts`, so
226
226
  `npx sanity blueprints deploy` has something to deploy. A purely interactive
227
227
  workflow needs none of it, and the command says so.
228
+ The CLI supplies its own compiler API for editing `sanity.blueprint.ts`, so your
229
+ project can use TypeScript 6 or 7 without changing versions and does not need
230
+ to install TypeScript for this command.
228
231
 
229
232
  Five prerequisites:
230
233
 
@@ -373,16 +376,60 @@ needs.
373
376
 
374
377
  ## Telemetry
375
378
 
376
- The CLI collects usage telemetry through Sanity's standard pipeline: a
377
- per-command trace (`Workflows CLI Command Executed` the command id, the
378
- names of declared flags used, never their values, and a success flag) plus
379
- the engine's adoption events from the operations it drives. Consent is the
380
- account-wide status managed by `npx sanity telemetry enable|disable|status`;
381
- CI and trueish `DO_NOT_TRACK` suppress everything (except a deploy that may share
379
+ The CLI collects usage telemetry through Sanity's standard pipeline. Consent
380
+ is the account-wide status managed by `npx sanity telemetry enable|disable|status`.
381
+ CI and trueish `DO_NOT_TRACK` suppress everything except a deploy that may share
382
382
  new definitions, which forces that deploy's telemetry unless `--no-share-defs`
383
- is passed — see [Definition sharing](#definition-sharing)),
384
- and a session that isn't logged in sends nothing. A one-time notice on stderr
385
- discloses collection on first use.
383
+ is passed — see [Definition sharing](#definition-sharing). A session that isn't
384
+ logged in sends nothing. A one-time notice on stderr discloses collection on
385
+ first use.
386
+
387
+ What may be collected is governed by [Sanity's telemetry
388
+ policy](https://www.sanity.io/telemetry). This package sends a subset of it.
389
+
390
+ Collected:
391
+
392
+ - Project id, dataset, and organization id, as session properties. The
393
+ organization id is best effort: it needs a lookup that can resolve to
394
+ nothing, and the event sends either way.
395
+ - Operating system, CPU architecture, JavaScript runtime and version, and the
396
+ CLI version.
397
+ - The command invoked, and the names of declared flags used on it.
398
+ - Structural counts and closed vocabulary values derived from a definition or
399
+ instance: stage and action counts, activity and field kinds, lifecycle,
400
+ status enums, and durations.
401
+ - Content fingerprints of definitions, and random run ids.
402
+ - `instanceId`, the instance document `_id`. Engine-minted ids embed the
403
+ deployment tag (`<tag>.wf-instance.<random>`), so the tag reaches telemetry
404
+ through this field. A caller-supplied instance id is sent verbatim.
405
+ - The author-chosen effect name, on effect events.
406
+
407
+ Never collected, because the policy excludes them:
408
+
409
+ - Environment variables, file paths, and file contents.
410
+ - Logs and serialized JavaScript stack traces.
411
+
412
+ Never collected, because this package goes further than the policy requires.
413
+ The policy does not prohibit any of these, so their absence here is this
414
+ package's choice and not a company-wide guarantee:
415
+
416
+ - Flag values and argv tokens. Only a declared flag's name is sent, so
417
+ `--tag=prod` reports `tag`.
418
+ - Error messages, and stack traces of any language. The policy permits error
419
+ information that excludes sensitive data, but this package's errors quote
420
+ definition names, tags, and argv, so none is sent. A failure is reported as
421
+ a success boolean and nothing else.
422
+ - Document content, GROQ, and field values.
423
+ - Definition names and stage names. A stage is reported by its position in
424
+ `stages[]`, never by name.
425
+
426
+ Note that a dataset name, a deployment tag, and an effect name are all
427
+ customer-authored. They are collected deliberately, as identifiers and as a
428
+ closed label, not as free text.
429
+
430
+ Definition sharing sends the definition document to a first-party feedback
431
+ endpoint, not through this pipeline; telemetry only records the content-free
432
+ markers below.
386
433
 
387
434
  Each event includes `context.surface: 'cli'` and its process execution mode
388
435
  in `context.environment`. `NODE_ENV=production` reports `production`;
@@ -400,6 +447,117 @@ One extension point: supply your own logger as `telemetry` in
400
447
  every event flows to your implementation unconditionally (CI included), and
401
448
  consent, suppression, and destination become its business.
402
449
 
450
+ ### Session properties
451
+
452
+ The built-in store attaches these user properties once per invocation (joined
453
+ to events by session id). User identity is not in the payload; the intake
454
+ service resolves the sender from the authenticated session.
455
+
456
+ | Property | What it is |
457
+ | ----------------- | ------------------------------------------------------------------------------------------------ |
458
+ | `surface` | Always `'cli'`. |
459
+ | `machinePlatform` | Node `process.platform` (for example `darwin`, `linux`). |
460
+ | `cpuArchitecture` | Node `process.arch`. |
461
+ | `runtime` | Always `'node'` for this CLI. |
462
+ | `runtimeVersion` | Node `process.version`. |
463
+ | `cliVersion` | The CLI package version, when oclif supplied it. |
464
+ | `projectId` | Project id of the first dataset-backed deployment in `sanity.workflow.ts`. |
465
+ | `dataset` | Dataset of that same deployment. |
466
+ | `orgId` | Organization id for that project, when the lookup succeeds before the command flushes. Optional. |
467
+
468
+ ### CLI events
469
+
470
+ These events are defined by this package.
471
+
472
+ #### `Workflows CLI Command Executed` (version 1)
473
+
474
+ One trace per workflows command. The built-in store starts the trace in the
475
+ prerun hook with `groupOrCommand` set to the oclif command id (for example
476
+ `workflows:deploy`, `workflows:definition:list`, `workflows:fire-action`) and
477
+ completes it in the finally hook. A config-supplied logger receives the same
478
+ payload as a log, with no trace. Host commands outside the `workflows` topic
479
+ do not emit.
480
+
481
+ | Field | Type | What is collected |
482
+ | --------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
483
+ | `command` | `string` | The oclif command id (`workflows:…`). Never argv free-text. |
484
+ | `flags` | `string[]` | Names of **declared** flags present on the invocation, sorted. Long form, `--no-name`, and short chars. Never values, never undeclared tokens, never tokens after `--`. |
485
+ | `success` | `boolean` | `true` when the command finished without an oclif error. |
486
+
487
+ #### `Workflows Definition Shared` (version 1)
488
+
489
+ One content-free marker per newly created definition version that actually
490
+ reached Sanity's definition-feedback endpoint. Unchanged redeploys, dry runs,
491
+ and `--check` never emit it. The document itself is not in this event.
492
+
493
+ | Field | Type | What is collected |
494
+ | ------------------ | ---------- | ---------------------------------------------------------------------------------------------------- |
495
+ | `contentHash` | `string` | Content fingerprint of the donated definition. |
496
+ | `deployId` | `string` | Random run id shared with that invocation's `Workflows Definition Deployed` events. |
497
+ | `stageCount` | `number` | Declared stages. |
498
+ | `activityCount` | `number` | Activities across those stages. |
499
+ | `actionCount` | `number` | Actions across those activities. |
500
+ | `transitionCount` | `number` | Declared transitions. |
501
+ | `fieldCount` | `number` | Declared field entries at workflow, stage, and activity scope. |
502
+ | `activityKinds` | `string[]` | Distinct effective activity kinds, sorted: `user`, `service`, `script`, `manual`, `receive`. |
503
+ | `fieldKinds` | `string[]` | Distinct declared field kinds, sorted (engine field kinds such as `string`, `subject`, `assignees`). |
504
+ | `guardCount` | `number` | Guards declared on stages. |
505
+ | `effectCount` | `number` | Effects declared on actions. |
506
+ | `subworkflowCount` | `number` | Actions that carry a `spawn` block. |
507
+ | `lifecycle` | `string` | `'standalone'` or `'child'`. |
508
+
509
+ #### `Workflows Definition Sharing Decided` (version 2)
510
+
511
+ One event per `deploy` that created at least one new definition version,
512
+ whether or not anything was donated. Measures opt-out rate without carrying
513
+ the document.
514
+
515
+ | Field | Type | What is collected |
516
+ | ----------------- | --------- | ----------------------------------------------------------------------------------------------------------------------------- |
517
+ | `decision` | `string` | `'opt-in'` (`--share-defs`), `'opt-out'` (`--no-share-defs`), or `'default'` (neither flag). |
518
+ | `shared` | `boolean` | Whether a donation POST reached the endpoint. `false` for any non-sharing decision, and for a chosen share whose POST failed. |
519
+ | `definitionCount` | `number` | Newly created definition versions this invocation could have donated. |
520
+
521
+ ### Engine events the CLI records
522
+
523
+ Write commands pass the CLI logger into the engine, so a successful operation
524
+ also records the engine's adoption events on the same session. Read commands
525
+ (`list`, `show`, `diagnose`, `tail`, `definition list` / `show` / `diff`) do
526
+ not emit engine events. `nuke` deletes engine-owned documents outside those
527
+ verbs and does not emit them either.
528
+
529
+ Every engine event includes:
530
+
531
+ | Field | Type | What is collected |
532
+ | ------------------ | -------- | --------------------------------------------------------------------------------------- |
533
+ | `executionRuntime` | `string` | The JavaScript runtime the engine detected around itself. Always `'node'` for this CLI. |
534
+ | `executionKind` | `string` | The host the engine was told it is running in. Always `'cli'` for this CLI. |
535
+
536
+ Every instance-scoped engine event additionally includes:
537
+
538
+ | Field | Type | What is collected |
539
+ | ----------------------- | -------- | -------------------------------------------------------------------------------------------------- |
540
+ | `definitionContentHash` | `string` | Content fingerprint of the pinned definition. Omitted when the definition predates fingerprinting. |
541
+ | `instanceId` | `string` | Instance document `_id`. |
542
+
543
+ | Event | Version | When the CLI emits it | Additional payload |
544
+ | ------------------------------- | ------- | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
545
+ | `Workflows Definition Deployed` | 2 | `deploy` for each definition (created or unchanged) | Same structural counts as `Workflows Definition Shared`, plus `status`: `'created'` or `'unchanged'`. |
546
+ | `Workflows Instance Started` | 2 | `start`, and a `fire-action` that spawns a child | `initialFieldCount` (number of caller-supplied initial fields), `viaSpawn` (`true` only for a spawned child), `lifecycle`. |
547
+ | `Workflows Stage Transitioned` | 2 | A committed hop from `fire-action`, `start` cascade, or `set-stage` | `fromStageIndex`, `toStageIndex` (indexes into `stages[]`, never names), `toIsTerminal`, `isRevisit`, `dwellMs` (milliseconds in the exited stage, omitted if that entry is missing), `via`: `'transition'` or `'setStage'`. Unsampled. |
548
+ | `Workflows Action Fired` | 2 | `fire-action` | `activityKind` (optional; derived kind of the fired activity), `hasParams` (whether params were supplied — not the params), `cascaded` (auto-transitions in the post-action cascade). |
549
+ | `Workflows Instance Aborted` | 2 | `abort` | `changed`: `false` if the instance was already terminal. |
550
+ | `Workflows Stage Set` | 2 | `set-stage` | `changed`: `false` if already at the target stage. |
551
+ | `Workflows Activity Reset` | 2 | `reset-activity` | `changed`: `false` if already at the target status, or the instance was terminal. |
552
+ | `Workflows Definition Deleted` | 2 | `definition delete` | `deletedVersionCount`, `cascadeAbortedCount`, `deletedGuardCount` (guards only when the last version goes). |
553
+ | `Workflows Effect Completed` | 2 | `abort` cancelling a pending effect | `effect` (author-chosen name), `status` (`'done'`, `'failed'`, or `'cancelled'`), `origin` (`'action'`), `cascaded`. |
554
+
555
+ The engine also defines `Workflows Field Edited`, `Workflows Instance Ticked`,
556
+ `Workflows Effects Drained`, and `Workflows Effect State Reported`. This CLI
557
+ does not call those verbs, so it does not record those events. Field-edit and
558
+ tick events are sampled at most once per 60 seconds when some other shell
559
+ does emit them.
560
+
403
561
  ## Definition sharing
404
562
 
405
563
  Separate from telemetry, a `deploy` that creates new definition versions
@@ -1,5 +1,6 @@
1
1
  import { styleText } from 'node:util';
2
2
  import { applyEmissionWritePlan, deploymentExportIdentifier, emissionDivergences, emissionWritePlan, GENERATED_BY, readGenerationRoot, runtimeEmissionPlan, } from '@sanity/workflow-blueprint/generate';
3
+ import ts from '@typescript/typescript6';
3
4
  import logSymbols from 'log-symbols';
4
5
  import { needsReportLines } from "./blueprint-needs.js";
5
6
  import { validateOrFail } from "./definitions.js";
@@ -33,7 +34,7 @@ function planGeneration(args) {
33
34
  validateEveryDeployment(args.config);
34
35
  const needs = failOnThrow('The definitions cannot produce a runtime:', () => runtimeEmissionPlan(args.config));
35
36
  const onDisk = readGenerationRoot(args.root);
36
- const writePlan = failOnThrow('Cannot plan the generated tree:', () => emissionWritePlan({ plan: needs, configFile: args.configFile, ...onDisk }));
37
+ const writePlan = failOnThrow('Cannot plan the generated tree:', () => emissionWritePlan({ plan: needs, configFile: args.configFile, compiler: ts, ...onDisk }));
37
38
  assertDeploymentsAreExported(args);
38
39
  return { needs, writePlan, existingPaths: onDisk.existingPaths };
39
40
  }
@@ -6,7 +6,7 @@ import { type WorkflowConfig } from '@sanity/workflow-engine';
6
6
  export interface LoadedWorkflowConfig {
7
7
  config: WorkflowConfig;
8
8
  /** The discovered file's name, so a diagnostic names the file the user
9
- * actually has out of {@link CONFIG_FILE_NAMES}. */
9
+ * actually has among the supported config filenames. */
10
10
  configFile: string;
11
11
  /** Every name the module exports, `default` included. `blueprint generate`
12
12
  * reads it because each generated module imports its deployment as a named
@@ -9,7 +9,7 @@ var __rewriteRelativeImportExtension = (this && this.__rewriteRelativeImportExte
9
9
  import { existsSync } from 'node:fs';
10
10
  import { basename, dirname, join } from 'node:path';
11
11
  import { pathToFileURL } from 'node:url';
12
- import { CONFIG_FILE_NAMES } from '@sanity/workflow-blueprint/generate';
12
+ import { CONFIG_FILE_NAMES } from '@sanity/workflow-blueprint';
13
13
  import { errorMessage } from '@sanity/workflow-engine';
14
14
  import { defineWorkflowConfig } from '@sanity/workflow-engine/define';
15
15
  import { createJiti } from 'jiti';
@@ -1,7 +1,7 @@
1
- /** Payload policy: no customer strings, ever — flag NAMES only (never values,
2
- * arguments, or error text); shared-definition events are content-free markers. */
1
+ /** Payload policy under https://www.sanity.io/telemetry: declared flag names
2
+ * only, never values, argv, or error text. README Telemetry has the lists. */
3
3
  import { type DefinedTelemetryTrace, type TelemetryStore } from '@sanity/telemetry';
4
- import { type TelemetryIntakeClient, type WorkflowDefinitionDeployedData, type WorkflowTelemetryLogger } from '@sanity/workflow-engine';
4
+ import { type DerivedEventData, type TelemetryIntakeClient, type WorkflowDefinitionDeployedData, type WorkflowTelemetryLogger } from '@sanity/workflow-engine';
5
5
  export interface WorkflowCliCommandData {
6
6
  /** The oclif command id — ours, never user free-text. */
7
7
  command: string;
@@ -11,11 +11,7 @@ export interface WorkflowCliCommandData {
11
11
  success: boolean;
12
12
  }
13
13
  export declare const WorkflowCliCommandExecuted: DefinedTelemetryTrace<WorkflowCliCommandData, void>;
14
- /** {@link WorkflowDefinitionDeployedData} minus the deploy status — the marker
15
- * is projected from the engine's own structural derivation so the two events
16
- * can never disagree about one definition, and only newly created versions
17
- * are ever shared, so status carries nothing. */
18
- export type WorkflowDefinitionSharedData = Omit<WorkflowDefinitionDeployedData, 'status'>;
14
+ export type WorkflowDefinitionSharedData = Omit<DerivedEventData<WorkflowDefinitionDeployedData>, 'status'>;
19
15
  export declare const WorkflowDefinitionShared: import("@sanity/telemetry").DefinedTelemetryLog<WorkflowDefinitionSharedData>;
20
16
  /**
21
17
  * How the donation decision was reached, and what it was. Paired with `shared`
@@ -1007,5 +1007,5 @@
1007
1007
  ]
1008
1008
  }
1009
1009
  },
1010
- "version": "0.33.0"
1010
+ "version": "0.35.0"
1011
1011
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sanity/workflow-cli",
3
- "version": "0.33.0",
3
+ "version": "0.35.0",
4
4
  "description": "Command-line tool for deploying, inspecting, and administering Sanity workflow definitions and instances.",
5
5
  "keywords": [
6
6
  "cli",
@@ -49,12 +49,12 @@
49
49
  "@oclif/plugin-help": "^6.2.50",
50
50
  "@sanity/client": "^7.22.1",
51
51
  "@sanity/telemetry": "^1.1.0",
52
+ "@typescript/typescript6": "^6.0.2",
52
53
  "boxen": "^8.0.1",
53
54
  "diff": "^9.0.0",
54
55
  "jiti": "^2.7.0",
55
56
  "log-symbols": "^7.0.1",
56
- "ora": "^9.4.0",
57
- "typescript": "^6.0.3"
57
+ "ora": "^9.4.0"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@sanity/blueprints": "^0.21.0",
@@ -64,16 +64,16 @@
64
64
  "@types/node": "^24.12.4",
65
65
  "oclif": "^4.23.16",
66
66
  "vitest": "^4.1.8",
67
- "@sanity/workflow-blueprint": "0.33.0",
68
- "@sanity/workflow-engine": "0.33.0",
69
- "@sanity/workflow-engine-test": "0.33.0",
70
- "@sanity/workflow-examples": "0.12.1",
67
+ "@sanity/workflow-blueprint": "0.35.0",
68
+ "@sanity/workflow-engine": "0.35.0",
69
+ "@sanity/workflow-engine-test": "0.35.0",
70
+ "@sanity/workflow-examples": "0.12.3",
71
71
  "@sanity/workflow-test-fixtures": "0.0.0"
72
72
  },
73
73
  "peerDependencies": {
74
74
  "@sanity/cli-core": "^3.6.0",
75
- "@sanity/workflow-blueprint": "0.33.0",
76
- "@sanity/workflow-engine": "0.33.0"
75
+ "@sanity/workflow-blueprint": "0.35.0",
76
+ "@sanity/workflow-engine": "0.35.0"
77
77
  },
78
78
  "oclif": {
79
79
  "bin": "sanity-workflows",