@openworkflow/cli 0.5.0 → 0.5.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.
package/dist/cli.js CHANGED
@@ -2,14 +2,18 @@
2
2
  /* v8 ignore file -- @preserve */
3
3
  import { dashboard, doctor, getVersion, init, workerStart, } from "./commands.js";
4
4
  import { withErrorHandling } from "./errors.js";
5
- import { Command, Option } from "commander";
5
+ import { initializeTelemetry, shutdownTelemetry, trackCommand, } from "./telemetry.js";
6
+ import { Command, CommanderError, Option } from "commander";
6
7
  // openworkflow
7
8
  const program = new Command();
9
+ initializeTelemetry(program);
8
10
  program
9
11
  .name("openworkflow")
10
12
  .description("OpenWorkflow CLI - learn more at https://openworkflow.dev")
11
13
  .usage("<command> [options]")
12
- .version(getVersion());
14
+ .exitOverride()
15
+ .version(getVersion())
16
+ .option("--no-telemetry", "disable telemetry");
13
17
  // init
14
18
  program
15
19
  .command("init")
@@ -49,4 +53,15 @@ program
49
53
  .option("--config <path>", "path to OpenWorkflow config file")
50
54
  .option("--env-file <path>", "load environment variables from file")
51
55
  .action(withErrorHandling(dashboard));
52
- await program.parseAsync(process.argv);
56
+ try {
57
+ await program.parseAsync(process.argv);
58
+ }
59
+ catch (error) {
60
+ if (!(error instanceof CommanderError))
61
+ throw error;
62
+ process.exitCode = error.exitCode;
63
+ trackCommand();
64
+ }
65
+ finally {
66
+ await shutdownTelemetry();
67
+ }
@@ -20,6 +20,7 @@ export declare function getVersion(): string;
20
20
  /**
21
21
  * openworkflow init
22
22
  * @param options - Command options
23
+ * @returns Resolves when setup finishes.
23
24
  */
24
25
  export declare function init(options?: InitOptions): Promise<void>;
25
26
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../commands.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAIb,MAAM,aAAa,CAAC;AAwCrB,KAAK,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAEpD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAY,SAAQ,cAAc;IAC1C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,gBAAiB,SAAQ,cAAc;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED;;;GAGG;AAEH,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAqJnE;AA8BD;;;GAGG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DxE;AAED,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,cAAc,CAAC;AAE/D;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA8Ef;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE;QACZ,KAAK,EAAE,SAAS,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACzB,CAAC;CACH,CAYA;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAavE;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D7E;AA4PD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,MAAM,EAAO,GAC5B,MAAM,EAAE,CA8CV;AA2WD,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAoCD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../commands.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,YAAY,EAIb,MAAM,aAAa,CAAC;AAyCrB,KAAK,aAAa,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,CAAC;AAEpD,UAAU,cAAc;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,UAAU,WAAY,SAAQ,cAAc;IAC1C,OAAO,CAAC,EAAE,aAAa,CAAC;IACxB,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,WAAW,CAAC,EAAE,OAAO,CAAC;CACvB;AAED,UAAU,gBAAiB,SAAQ,cAAc;IAC/C,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED;;;;GAIG;AAEH,wBAAsB,IAAI,CAAC,OAAO,GAAE,WAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAsJnE;AA8BD;;;GAGG;AACH,wBAAsB,MAAM,CAAC,OAAO,GAAE,cAAmB,GAAG,OAAO,CAAC,IAAI,CAAC,CA2DxE;AAED,MAAM,MAAM,kBAAkB,GAAG,YAAY,GAAG,cAAc,CAAC;AAE/D;;;GAGG;AACH,wBAAsB,WAAW,CAC/B,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC,IAAI,CAAC,CA8Ef;AAED;;;;;GAKG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG;IACvD,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,YAAY,EAAE;QACZ,KAAK,EAAE,SAAS,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC,UAAU,CAAC;KACzB,CAAC;CACH,CAYA;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAavE;AAED;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA6D7E;AA4PD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,MAAM,EACf,cAAc,GAAE,MAAM,EAAO,GAC5B,MAAM,EAAE,CA8CV;AA+WD,UAAU,oBAAoB;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAoCD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAER"}
package/dist/commands.js CHANGED
@@ -1,6 +1,7 @@
1
1
  import { findConfigFile, loadConfigFromPath, } from "./config.js";
2
2
  import { CLIError, exit } from "./errors.js";
3
3
  import { createModuleLoader } from "./module-loader.js";
4
+ import { trackCommand } from "./telemetry.js";
4
5
  import { CONFIG, HELLO_WORLD_RUNNER, HELLO_WORLD_WORKFLOW, POSTGRES_CLIENT, POSTGRES_PROD_SQLITE_DEV_CLIENT, SQLITE_CLIENT, } from "./templates.js";
5
6
  import * as p from "@clack/prompts";
6
7
  import { consola } from "consola";
@@ -40,6 +41,7 @@ export function getVersion() {
40
41
  /**
41
42
  * openworkflow init
42
43
  * @param options - Command options
44
+ * @returns Resolves when setup finishes.
43
45
  */
44
46
  // oxlint-disable-next-line complexity
45
47
  export async function init(options = {}) {
@@ -61,7 +63,7 @@ export async function init(options = {}) {
61
63
  initialValue: false,
62
64
  });
63
65
  if (!shouldOverride || p.isCancel(shouldOverride))
64
- cancelSetup();
66
+ return cancelSetup();
65
67
  configFileToDelete = configFile;
66
68
  }
67
69
  const backendChoice = options.backend ??
@@ -87,7 +89,8 @@ export async function init(options = {}) {
87
89
  initialValue: "sqlite",
88
90
  }));
89
91
  if (typeof backendChoice === "symbol")
90
- cancelSetup();
92
+ return cancelSetup();
93
+ trackCommand(backendChoice);
91
94
  const spinner = p.spinner();
92
95
  // detect package manager & install packages
93
96
  spinner.start("Detecting package manager...");
@@ -114,7 +117,7 @@ export async function init(options = {}) {
114
117
  initialValue: true,
115
118
  }));
116
119
  if (p.isCancel(shouldSetup))
117
- cancelSetup();
120
+ return cancelSetup();
118
121
  if (!shouldSetup) {
119
122
  p.outro("Setup skipped.");
120
123
  return;
@@ -380,11 +383,11 @@ export async function dashboard(options = {}) {
380
383
  // -----------------------------------------------------------------------------
381
384
  /**
382
385
  * Show a canceled-setup message and exit the process with status 0.
386
+ * @returns Never resolves because the process exits.
383
387
  */
384
388
  function cancelSetup() {
385
389
  p.cancel("Setup canceled.");
386
- // oxlint-disable-next-line unicorn/no-process-exit
387
- process.exit(0);
390
+ return exit(0);
388
391
  }
389
392
  /**
390
393
  * Exercise backend initialization, connectivity, and workflow table access.
@@ -861,7 +864,9 @@ function findConfigWithEnv(options) {
861
864
  async function loadConfigWithEnv(options) {
862
865
  const configPath = findConfigWithEnv(options);
863
866
  try {
864
- return await loadConfigFromPath(configPath ?? "openworkflow.config.ts");
867
+ const loaded = await loadConfigFromPath(configPath ?? "openworkflow.config.ts");
868
+ trackCommand(loaded.config.backend);
869
+ return loaded;
865
870
  }
866
871
  catch (error) {
867
872
  const message = error instanceof Error ? error.message : String(error);
@@ -1 +1 @@
1
- {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../errors.ts"],"names":[],"mappings":"AAGA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAK7C;AAED;;;GAGG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAWvD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,EACnD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACvC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAiB/B"}
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../errors.ts"],"names":[],"mappings":"AAIA;;GAEG;AACH,qBAAa,QAAS,SAAQ,KAAK;IACjC,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC;gBAExB,OAAO,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM;CAK7C;AAED;;;GAGG;AACH,wBAAsB,IAAI,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAYvD;AAED;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,CAAC,SAAS,OAAO,EAAE,EACnD,EAAE,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GACvC,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,OAAO,CAAC,IAAI,CAAC,CAiB/B"}
package/dist/errors.js CHANGED
@@ -1,4 +1,5 @@
1
1
  /* v8 ignore file -- @preserve */
2
+ import { shutdownTelemetry } from "./telemetry.js";
2
3
  import { consola } from "consola";
3
4
  /**
4
5
  * User-facing CLI error.
@@ -16,6 +17,7 @@ export class CLIError extends Error {
16
17
  * @param code - Process exit code
17
18
  */
18
19
  export async function exit(code) {
20
+ await shutdownTelemetry();
19
21
  await Promise.all([process.stdout, process.stderr].map((stream) => new Promise((resolve) => {
20
22
  stream.end(resolve);
21
23
  })));
@@ -0,0 +1,16 @@
1
+ import type { Command } from "commander";
2
+ import type { Backend } from "openworkflow/internal";
3
+ /**
4
+ * Set up telemetry before the CLI prints output.
5
+ * @param program - Root CLI command
6
+ */
7
+ export declare function initializeTelemetry(program: Command): void;
8
+ /**
9
+ * Track after loading config or choosing an init backend.
10
+ * Help, version, and argument errors are tracked without a backend.
11
+ * @param backend - Configured backend or init selection
12
+ */
13
+ export declare function trackCommand(backend?: Backend | "sqlite" | "postgres" | "both"): void;
14
+ /** Send queued events before the CLI exits. */
15
+ export declare function shutdownTelemetry(): Promise<void>;
16
+ //# sourceMappingURL=telemetry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telemetry.d.ts","sourceRoot":"","sources":["../telemetry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKzC,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAoBrD;;;GAGG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAsC1D;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,OAAO,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,UAAU,GAAG,MAAM,GACjD,IAAI,CAoCN;AAED,+CAA+C;AAC/C,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC,CAMvD"}
@@ -0,0 +1,101 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
3
+ import { homedir } from "node:os";
4
+ import path from "node:path";
5
+ import { PostHog } from "posthog-node";
6
+ let telemetry;
7
+ const backendTypes = new Map([
8
+ ["BackendSqlite", "sqlite"],
9
+ ["BackendPostgres", "postgres"],
10
+ ["sqlite", "sqlite"],
11
+ ["postgres", "postgres"],
12
+ ["both", "both"],
13
+ ]);
14
+ /**
15
+ * Set up telemetry before the CLI prints output.
16
+ * @param program - Root CLI command
17
+ */
18
+ export function initializeTelemetry(program) {
19
+ telemetry = undefined;
20
+ if (process.env["DO_NOT_TRACK"] ||
21
+ process.env["OPENWORKFLOW_TELEMETRY_DISABLED"] ||
22
+ process.env["CI"] ||
23
+ process.argv.includes("--no-telemetry"))
24
+ return;
25
+ try {
26
+ const directory = path.join(homedir(), ".openworkflow");
27
+ const file = path.join(directory, "telemetry-id");
28
+ mkdirSync(directory, { recursive: true });
29
+ if (!existsSync(file)) {
30
+ writeFileSync(file, randomUUID(), { flag: "wx", mode: 0o600 });
31
+ console.error("OpenWorkflow collects CLI usage via PostHog. Set DO_NOT_TRACK=1 to opt out.\n" +
32
+ "https://openworkflow.dev/docs/cli#telemetry\n");
33
+ }
34
+ const distinctId = readFileSync(file, "utf8").trim();
35
+ if (!distinctId)
36
+ return;
37
+ const state = {
38
+ program,
39
+ distinctId,
40
+ client: new PostHog("phc_C1Cm1NAKHDFA3eKLVqcYzR5wUk8WhSbMMXltk5Qj1Ye"),
41
+ };
42
+ program.on("beforeAllHelp", ({ command }) => {
43
+ state.helpCommand = command;
44
+ });
45
+ program.on("option:version", () => {
46
+ state.version = true;
47
+ });
48
+ telemetry = state;
49
+ }
50
+ catch {
51
+ // ignore, telemetry is optional
52
+ }
53
+ }
54
+ /**
55
+ * Track after loading config or choosing an init backend.
56
+ * Help, version, and argument errors are tracked without a backend.
57
+ * @param backend - Configured backend or init selection
58
+ */
59
+ export function trackCommand(backend) {
60
+ const state = telemetry;
61
+ if (!state)
62
+ return;
63
+ try {
64
+ let command = state.helpCommand ?? state.program;
65
+ let child;
66
+ while ((child = command.commands.find((candidate) => candidate.name() === command.args[0]))) {
67
+ command = child;
68
+ }
69
+ const backendName = typeof backend === "string" ? backend : backend?.constructor.name;
70
+ const commandName = command.parent?.parent
71
+ ? `${command.parent.name()} ${command.name()}`
72
+ : command.name();
73
+ state.client.capture({
74
+ distinctId: state.distinctId,
75
+ event: "cli_command_invoked",
76
+ properties: {
77
+ command: state.version ? "version" : commandName,
78
+ backend: backendName
79
+ ? (backendTypes.get(backendName) ?? "custom")
80
+ : undefined,
81
+ help: state.helpCommand ? true : undefined,
82
+ cli_version: state.program.version(),
83
+ os: process.platform,
84
+ arch: process.arch,
85
+ node_version: process.versions.node,
86
+ },
87
+ });
88
+ }
89
+ catch {
90
+ // ignore, telemetry is optional
91
+ }
92
+ }
93
+ /** Send queued events before the CLI exits. */
94
+ export async function shutdownTelemetry() {
95
+ try {
96
+ await telemetry?.client.shutdown();
97
+ }
98
+ catch {
99
+ // ignore, telemetry is optional
100
+ }
101
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@openworkflow/cli",
3
- "version": "0.5.0",
3
+ "version": "0.5.1",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": {
@@ -32,7 +32,8 @@
32
32
  "consola": "^3.4.2",
33
33
  "dotenv": "^17.4.2",
34
34
  "jiti": "^2.7.0",
35
- "nypm": "^0.6.10"
35
+ "nypm": "^0.6.10",
36
+ "posthog-node": "~5.21.2"
36
37
  },
37
38
  "devDependencies": {
38
39
  "openworkflow": "*",