@openworkflow/cli 0.1.0 → 0.2.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
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env node
2
2
  /* v8 ignore file -- @preserve */
3
- import { doctor, getVersion, init, workerStart } from "./commands.js";
3
+ import { dashboard, doctor, getVersion, init, workerStart, } from "./commands.js";
4
4
  import { withErrorHandling } from "./errors.js";
5
5
  import { Command } from "commander";
6
6
  // openworkflow | ow
@@ -28,5 +28,9 @@ workerCmd
28
28
  .description("start a worker to process workflows")
29
29
  .option("-c, --concurrency <number>", "number of concurrent workflows to process", Number.parseInt)
30
30
  .action(withErrorHandling(workerStart));
31
+ // dashboard
32
+ program
33
+ .command("dashboard")
34
+ .description("start the dashboard to view workflow runs")
35
+ .action(withErrorHandling(dashboard));
31
36
  await program.parseAsync(process.argv);
32
- //# sourceMappingURL=cli.js.map
@@ -13,6 +13,11 @@ export declare function doctor(): Promise<void>;
13
13
  * @param cliOptions - Worker config overrides
14
14
  */
15
15
  export declare function workerStart(cliOptions: WorkerConfig): Promise<void>;
16
+ /**
17
+ * openworkflow dashboard
18
+ * Starts the dashboard by delegating to `@openworkflow/dashboard` via npx.
19
+ */
20
+ export declare function dashboard(): Promise<void>;
16
21
  interface PackageJsonForDoctor {
17
22
  dependencies?: Record<string, string>;
18
23
  devDependencies?: Record<string, string>;
@@ -29,5 +34,11 @@ export declare function getConfigFileName(packageJson: Readonly<PackageJsonForDo
29
34
  * @returns The example workflow file name to create
30
35
  */
31
36
  export declare function getExampleWorkflowFileName(packageJson: Readonly<PackageJsonForDoctor> | null): string;
37
+ /**
38
+ * Determine the client filename to write during init.
39
+ * @param packageJson - Parsed package.json (or null if missing)
40
+ * @returns The client file name to create
41
+ */
42
+ export declare function getClientFileName(packageJson: Readonly<PackageJsonForDoctor> | null): string;
32
43
  export {};
33
44
  //# sourceMappingURL=commands.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AA8BvD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED,wBAAwB;AACxB,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAqH1C;AAED,0BAA0B;AAC1B,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAiD5C;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqEzE;AA0dD,UAAU,oBAAoB;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAsBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAMR;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAKR"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../commands.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAc,MAAM,aAAa,CAAC;AAgCvD;;;GAGG;AACH,wBAAgB,UAAU,IAAI,MAAM,CAoBnC;AAED,wBAAwB;AACxB,wBAAsB,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CA8H1C;AAED,0BAA0B;AAC1B,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAiD5C;AAED;;;GAGG;AACH,wBAAsB,WAAW,CAAC,UAAU,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAqEzE;AAED;;;GAGG;AACH,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CA0D/C;AAqfD,UAAU,oBAAoB;IAC5B,YAAY,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACtC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC1C;AAsBD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAMR;AAED;;;;GAIG;AACH,wBAAgB,0BAA0B,CACxC,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAKR;AAED;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,WAAW,EAAE,QAAQ,CAAC,oBAAoB,CAAC,GAAG,IAAI,GACjD,MAAM,CAKR"}
package/dist/commands.js CHANGED
@@ -1,10 +1,11 @@
1
1
  import { loadConfig } from "./config.js";
2
2
  import { CLIError } from "./errors.js";
3
- import { HELLO_WORLD_WORKFLOW, POSTGRES_CONFIG, POSTGRES_PROD_SQLITE_DEV_CONFIG, SQLITE_CONFIG, } from "./templates.js";
3
+ import { CONFIG, HELLO_WORLD_WORKFLOW, POSTGRES_CLIENT, POSTGRES_PROD_SQLITE_DEV_CLIENT, SQLITE_CLIENT, } from "./templates.js";
4
4
  import * as p from "@clack/prompts";
5
5
  import { consola } from "consola";
6
6
  import { config as loadDotenv } from "dotenv";
7
7
  import { createJiti } from "jiti";
8
+ import { spawn } from "node:child_process";
8
9
  import { existsSync, mkdirSync, readdirSync, readFileSync, unlinkSync, writeFileSync, } from "node:fs";
9
10
  import path from "node:path";
10
11
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -85,7 +86,11 @@ export async function init() {
85
86
  const packageManager = pm?.name ?? "your package manager";
86
87
  spinner.stop(`Using ${packageManager}`);
87
88
  const packageJson = readPackageJsonForDoctor();
89
+ if (!packageJson) {
90
+ throw new CLIError("No package.json found.", "Please create a package.json file first by running `npm init` or `npm init -y`.");
91
+ }
88
92
  const configFileName = getConfigFileName(packageJson);
93
+ const clientFileName = getClientFileName(packageJson);
89
94
  const exampleWorkflowFileName = getExampleWorkflowFileName(packageJson);
90
95
  const shouldSetup = await p.confirm({
91
96
  message: `Install packages and set up project files (.env, .gitignore, package.json, ${configFileName}, openworkflow/${exampleWorkflowFileName})?`,
@@ -115,6 +120,7 @@ export async function init() {
115
120
  await addDependency(devDependencies, { silent: true, dev: true });
116
121
  spinner.stop(`Installed ${devDependencies.join(", ")}`);
117
122
  }
123
+ createClientFile(backendChoice, clientFileName);
118
124
  createExampleWorkflow(exampleWorkflowFileName);
119
125
  if (backendChoice === "sqlite" || backendChoice === "both") {
120
126
  updateGitignoreForSqlite();
@@ -125,7 +131,7 @@ export async function init() {
125
131
  addWorkerScriptToPackageJson();
126
132
  // write config file last, so canceling earlier doesn't leave a config file
127
133
  // which would prevent re-running init
128
- createConfigFile(backendChoice, configFileName);
134
+ createConfigFile(configFileName);
129
135
  // wrap up
130
136
  p.note(`➡️ Start a worker with:\n$ ${packageManager === "npm" ? "npm run" : packageManager} worker\n\nOr directly with:\n$ ow worker start`, "Next steps");
131
137
  p.outro("✅ Setup complete!");
@@ -224,6 +230,51 @@ export async function workerStart(cliOptions) {
224
230
  throw error;
225
231
  }
226
232
  }
233
+ /**
234
+ * openworkflow dashboard
235
+ * Starts the dashboard by delegating to `@openworkflow/dashboard` via npx.
236
+ */
237
+ export async function dashboard() {
238
+ consola.start("Starting dashboard...");
239
+ const { configFile } = await loadConfigWithEnv();
240
+ if (!configFile) {
241
+ throw new CLIError("No config file found.", "Run `ow init` to create a config file before starting the dashboard.");
242
+ }
243
+ consola.info(`Using config: ${configFile}`);
244
+ // eslint-disable-next-line sonarjs/no-os-command-from-path
245
+ const child = spawn("npx", ["@openworkflow/dashboard"], {
246
+ stdio: "inherit",
247
+ });
248
+ await new Promise((resolve, reject) => {
249
+ /** remove signal handlers after the child exits */
250
+ function cleanupSignalHandlers() {
251
+ process.off("SIGINT", signalHandler);
252
+ process.off("SIGTERM", signalHandler);
253
+ }
254
+ child.on("error", (error) => {
255
+ cleanupSignalHandlers();
256
+ reject(new CLIError("Failed to start dashboard.", `Could not spawn npx: ${error.message}`));
257
+ });
258
+ child.on("exit", (code) => {
259
+ cleanupSignalHandlers();
260
+ if (code === 0 || code === null) {
261
+ resolve();
262
+ }
263
+ else {
264
+ reject(new CLIError("Dashboard exited with an error.", `Exit code: ${String(code)}`));
265
+ }
266
+ });
267
+ /**
268
+ * Graceful shutdown on signals.
269
+ * @param signal - Signal
270
+ */
271
+ function signalHandler(signal) {
272
+ child.kill(signal);
273
+ }
274
+ process.on("SIGINT", signalHandler);
275
+ process.on("SIGTERM", signalHandler);
276
+ });
277
+ }
227
278
  // -----------------------------------------------------------------------------
228
279
  /**
229
280
  * Get workflow directories from config.
@@ -410,16 +461,21 @@ async function discoverWorkflowsInDirs(dirs, baseDir) {
410
461
  * @param backendChoice - The selected backend choice
411
462
  * @returns The config template string
412
463
  */
413
- function getConfigTemplate(backendChoice) {
464
+ /**
465
+ * Get the client template for a backend choice.
466
+ * @param backendChoice - The selected backend choice
467
+ * @returns The client template string
468
+ */
469
+ function getClientTemplate(backendChoice) {
414
470
  switch (backendChoice) {
415
471
  case "sqlite": {
416
- return SQLITE_CONFIG;
472
+ return SQLITE_CLIENT;
417
473
  }
418
474
  case "postgres": {
419
- return POSTGRES_CONFIG;
475
+ return POSTGRES_CLIENT;
420
476
  }
421
477
  case "both": {
422
- return POSTGRES_PROD_SQLITE_DEV_CONFIG;
478
+ return POSTGRES_PROD_SQLITE_DEV_CLIENT;
423
479
  }
424
480
  }
425
481
  }
@@ -447,17 +503,37 @@ function getDevDependenciesToInstall() {
447
503
  }
448
504
  /**
449
505
  * Create config file.
450
- * @param backendChoice - The selected backend choice
451
506
  * @param configFileName - The config file name to write
452
507
  */
453
- function createConfigFile(backendChoice, configFileName) {
508
+ function createConfigFile(configFileName) {
454
509
  const spinner = p.spinner();
455
510
  spinner.start("Writing config...");
456
- const configTemplate = getConfigTemplate(backendChoice);
457
511
  const configDestPath = path.join(process.cwd(), configFileName);
458
- writeFileSync(configDestPath, configTemplate, "utf8");
512
+ writeFileSync(configDestPath, CONFIG, "utf8");
459
513
  spinner.stop(`Config written to ${configDestPath}`);
460
514
  }
515
+ /**
516
+ * Create client file.
517
+ * @param backendChoice - The selected backend choice
518
+ * @param clientFileName - The client filename to write
519
+ */
520
+ function createClientFile(backendChoice, clientFileName) {
521
+ const spinner = p.spinner();
522
+ const workflowsDir = path.join(process.cwd(), "openworkflow");
523
+ if (!existsSync(workflowsDir)) {
524
+ mkdirSync(workflowsDir, { recursive: true });
525
+ }
526
+ const clientDestPath = path.join(workflowsDir, clientFileName);
527
+ if (existsSync(clientDestPath)) {
528
+ spinner.start("Checking client file...");
529
+ spinner.stop(`Client file already exists at ${clientDestPath}`);
530
+ return;
531
+ }
532
+ spinner.start("Creating client file...");
533
+ const clientTemplate = getClientTemplate(backendChoice);
534
+ writeFileSync(clientDestPath, clientTemplate, "utf8");
535
+ spinner.stop(`Created client file at ${clientDestPath}`);
536
+ }
461
537
  /**
462
538
  * Create example workflow.
463
539
  * @param exampleWorkflowFileName - The example workflow filename to write
@@ -507,7 +583,7 @@ function addWorkerScriptToPackageJson() {
507
583
  try {
508
584
  const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf8"));
509
585
  packageJson.scripts ??= {};
510
- packageJson.scripts["worker"] = "ow worker start";
586
+ packageJson.scripts["worker"] = "npx @openworkflow/cli worker start";
511
587
  writeFileSync(packageJsonPath, JSON.stringify(packageJson, null, 2) + "\n", "utf8");
512
588
  spinner.stop('Added "worker" script to package.json');
513
589
  }
@@ -613,6 +689,16 @@ export function getExampleWorkflowFileName(packageJson) {
613
689
  const extension = path.extname(configFileName) || ".js";
614
690
  return `hello-world${extension}`;
615
691
  }
692
+ /**
693
+ * Determine the client filename to write during init.
694
+ * @param packageJson - Parsed package.json (or null if missing)
695
+ * @returns The client file name to create
696
+ */
697
+ export function getClientFileName(packageJson) {
698
+ const configFileName = getConfigFileName(packageJson);
699
+ const extension = path.extname(configFileName) || ".js";
700
+ return `client${extension}`;
701
+ }
616
702
  /**
617
703
  * Check whether a dependency is declared in package.json.
618
704
  * @param packageJson - Parsed package.json.
@@ -715,4 +801,3 @@ function mergeDefinedOptions(base, overrides) {
715
801
  }
716
802
  return merged;
717
803
  }
718
- //# sourceMappingURL=commands.js.map
@@ -1,4 +1,4 @@
1
- import { getConfigFileName, getExampleWorkflowFileName } from "./commands.js";
1
+ import { getClientFileName, getConfigFileName, getExampleWorkflowFileName, } from "./commands.js";
2
2
  import { describe, expect, test } from "vitest";
3
3
  describe("getConfigFileName", () => {
4
4
  test("prefers TypeScript when it is in devDependencies", () => {
@@ -32,4 +32,21 @@ describe("getExampleWorkflowFileName", () => {
32
32
  expect(getExampleWorkflowFileName({ dependencies: {}, devDependencies: {} })).toBe("hello-world.js");
33
33
  });
34
34
  });
35
- //# sourceMappingURL=commands.test.js.map
35
+ describe("getClientFileName", () => {
36
+ test("uses TypeScript when it is in devDependencies", () => {
37
+ expect(getClientFileName({
38
+ devDependencies: { typescript: "^5.0.0" },
39
+ })).toBe("client.ts");
40
+ });
41
+ test("uses TypeScript when it is in dependencies", () => {
42
+ expect(getClientFileName({
43
+ dependencies: { typescript: "^5.0.0" },
44
+ })).toBe("client.ts");
45
+ });
46
+ test("falls back to JavaScript when package.json is missing", () => {
47
+ expect(getClientFileName(null)).toBe("client.js");
48
+ });
49
+ test("falls back to JavaScript when package.json has no TypeScript", () => {
50
+ expect(getClientFileName({ dependencies: {}, devDependencies: {} })).toBe("client.js");
51
+ });
52
+ });
package/dist/config.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { WorkerOptions } from "openworkflow";
1
+ import type { WorkerOptions } from "openworkflow";
2
2
  import type { Backend } from "openworkflow/internal";
3
3
  export interface OpenWorkflowConfig {
4
4
  backend: Backend;
@@ -25,10 +25,12 @@ interface LoadedConfig {
25
25
  }
26
26
  /**
27
27
  * Load the OpenWorkflow config at openworkflow.config.{ts,mts,cts,js,mjs,cjs}.
28
- * @param rootDir - Optional root directory to search from (defaults to
29
- * process.cwd())
28
+ * Searches up the directory tree from the starting directory to find the
29
+ * nearest config file.
30
+ * @param startDir - Optional starting directory to search from (defaults to
31
+ * process.cwd()). Will search this directory and all parent directories.
30
32
  * @returns The loaded configuration and metadata
31
33
  */
32
- export declare function loadConfig(rootDir?: string): Promise<LoadedConfig>;
34
+ export declare function loadConfig(startDir?: string): Promise<LoadedConfig>;
33
35
  export {};
34
36
  //# sourceMappingURL=config.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAIA,OAAO,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAC7C,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAE3E;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAMD;;;;;GAKG;AACH,wBAAsB,UAAU,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CAkCxE"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../config.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAErD,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,YAAY,CAAC;IACtB;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,MAAM,YAAY,GAAG,IAAI,CAAC,aAAa,EAAE,aAAa,CAAC,CAAC;AAE9D;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,kBAAkB,CAE3E;AAED,UAAU,YAAY;IACpB,MAAM,EAAE,kBAAkB,CAAC;IAC3B,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;CAChC;AAMD;;;;;;;GAOG;AACH,wBAAsB,UAAU,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,CAAC,CA8CzE"}
package/dist/config.js CHANGED
@@ -15,30 +15,42 @@ const CONFIG_EXTENSIONS = ["ts", "mts", "cts", "js", "mjs", "cjs"];
15
15
  const jiti = createJiti(import.meta.url);
16
16
  /**
17
17
  * Load the OpenWorkflow config at openworkflow.config.{ts,mts,cts,js,mjs,cjs}.
18
- * @param rootDir - Optional root directory to search from (defaults to
19
- * process.cwd())
18
+ * Searches up the directory tree from the starting directory to find the
19
+ * nearest config file.
20
+ * @param startDir - Optional starting directory to search from (defaults to
21
+ * process.cwd()). Will search this directory and all parent directories.
20
22
  * @returns The loaded configuration and metadata
21
23
  */
22
- export async function loadConfig(rootDir) {
23
- const cwd = rootDir ?? process.cwd();
24
- for (const ext of CONFIG_EXTENSIONS) {
25
- const fileName = `${CONFIG_NAME}.${ext}`;
26
- const filePath = path.join(cwd, fileName);
27
- if (existsSync(filePath)) {
28
- try {
29
- const fileUrl = pathToFileURL(filePath).href;
30
- const config = await jiti.import(fileUrl, {
31
- default: true,
32
- });
33
- return {
34
- config,
35
- configFile: filePath,
36
- };
37
- }
38
- catch (error) {
39
- throw new Error(`Failed to load config file ${filePath}: ${String(error)}`);
24
+ export async function loadConfig(startDir) {
25
+ let currentDir = path.resolve(startDir ?? process.cwd());
26
+ // search up the directory tree
27
+ // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
28
+ while (true) {
29
+ for (const ext of CONFIG_EXTENSIONS) {
30
+ const fileName = `${CONFIG_NAME}.${ext}`;
31
+ const filePath = path.join(currentDir, fileName);
32
+ if (existsSync(filePath)) {
33
+ try {
34
+ const fileUrl = pathToFileURL(filePath).href;
35
+ const config = await jiti.import(fileUrl, {
36
+ default: true,
37
+ });
38
+ return {
39
+ config,
40
+ configFile: filePath,
41
+ };
42
+ }
43
+ catch (error) {
44
+ throw new Error(`Failed to load config file ${filePath}: ${String(error)}`);
45
+ }
40
46
  }
41
47
  }
48
+ const parentDir = path.dirname(currentDir);
49
+ if (parentDir === currentDir) {
50
+ // reached filesystem root without finding config
51
+ break;
52
+ }
53
+ currentDir = parentDir;
42
54
  }
43
55
  return {
44
56
  // not great, but meant to match the c12 api since that is what was used in
@@ -48,4 +60,3 @@ export async function loadConfig(rootDir) {
48
60
  configFile: undefined, // no config found
49
61
  };
50
62
  }
51
- //# sourceMappingURL=config.js.map
@@ -86,4 +86,3 @@ describe("loadConfig", () => {
86
86
  }
87
87
  });
88
88
  });
89
- //# sourceMappingURL=config.test.js.map
package/dist/errors.js CHANGED
@@ -40,4 +40,3 @@ export function withErrorHandling(fn) {
40
40
  }
41
41
  };
42
42
  }
43
- //# sourceMappingURL=errors.js.map
package/dist/index.js CHANGED
@@ -1,2 +1 @@
1
1
  export { defineConfig } from "./config.js";
2
- //# sourceMappingURL=index.js.map
@@ -0,0 +1,2 @@
1
+ export { loadConfig } from "./config.js";
2
+ //# sourceMappingURL=internal.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../internal.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1 @@
1
+ export { loadConfig } from "./config.js";
@@ -1,5 +1,6 @@
1
- export declare const SQLITE_CONFIG = "import { BackendSqlite } from \"@openworkflow/backend-sqlite\";\nimport { defineConfig } from \"@openworkflow/cli\";\n\nexport default defineConfig({\n // Use SQLite as the backend\n backend: BackendSqlite.connect(\"openworkflow/backend.db\"),\n\n // The directories where your workflows are defined\n dirs: \"./openworkflow\",\n});\n";
2
- export declare const POSTGRES_CONFIG = "import { BackendPostgres } from \"@openworkflow/backend-postgres\";\nimport { defineConfig } from \"@openworkflow/cli\";\n\nexport default defineConfig({\n // Use Postgres as the backend\n backend: await BackendPostgres.connect(\n process.env[\"OPENWORKFLOW_POSTGRES_URL\"],\n ),\n\n // The directories where your workflows are defined\n dirs: \"./openworkflow\",\n});\n";
3
- export declare const POSTGRES_PROD_SQLITE_DEV_CONFIG = "import { BackendPostgres } from \"@openworkflow/backend-postgres\";\nimport { BackendSqlite } from \"@openworkflow/backend-sqlite\";\nimport { defineConfig } from \"@openworkflow/cli\";\n\nexport default defineConfig({\n // Use Postgres as the backend in production, otherwise use SQLite\n backend:\n process.env[\"NODE_ENV\"] === \"production\"\n ? await BackendPostgres.connect(process.env[\"OPENWORKFLOW_POSTGRES_URL\"])\n : BackendSqlite.connect(\"openworkflow/backend.db\"),\n\n // The directories where your workflows are defined\n dirs: \"./openworkflow\",\n});\n";
4
- export declare const HELLO_WORLD_WORKFLOW = "import { defineWorkflow } from \"openworkflow\";\n\nexport const helloWorld = defineWorkflow(\n { name: \"hello-world\" },\n async ({ step }) => {\n const greeting = await step.run({ name: \"greet\" }, () => {\n return \"Hello, World!\";\n });\n\n await step.sleep(\"wait-a-bit\", \"1s\");\n\n return { greeting };\n },\n);\n";
1
+ export declare const SQLITE_CLIENT = "import { BackendSqlite } from \"@openworkflow/backend-sqlite\";\nimport { OpenWorkflow } from \"openworkflow\";\n\nexport const backend = BackendSqlite.connect(\"openworkflow/backend.db\");\nexport const ow = new OpenWorkflow({ backend });\n";
2
+ export declare const POSTGRES_CLIENT = "import { BackendPostgres } from \"@openworkflow/backend-postgres\";\nimport { OpenWorkflow } from \"openworkflow\";\n\nexport const backend = await BackendPostgres.connect(\n process.env[\"OPENWORKFLOW_POSTGRES_URL\"],\n);\nexport const ow = new OpenWorkflow({ backend });\n";
3
+ export declare const POSTGRES_PROD_SQLITE_DEV_CLIENT = "import { BackendPostgres } from \"@openworkflow/backend-postgres\";\nimport { BackendSqlite } from \"@openworkflow/backend-sqlite\";\nimport { OpenWorkflow } from \"openworkflow\";\n\nexport const backend =\n process.env[\"NODE_ENV\"] === \"production\"\n ? await BackendPostgres.connect(process.env[\"OPENWORKFLOW_POSTGRES_URL\"])\n : BackendSqlite.connect(\"openworkflow/backend.db\");\nexport const ow = new OpenWorkflow({ backend });\n";
4
+ export declare const CONFIG = "import { backend } from \"./openworkflow/client.js\";\nimport { defineConfig } from \"@openworkflow/cli\";\n\nexport default defineConfig({\n backend,\n dirs: \"./openworkflow\",\n});\n";
5
+ export declare const HELLO_WORLD_WORKFLOW = "import { defineWorkflow } from \"openworkflow\";\n\n/**\n * Example workflow that greets the world.\n *\n * This workflow is auto-discovered by the CLI worker.\n * To trigger it, use ow.runWorkflow() from your app:\n * ```ts\n * import { ow } from \"./openworkflow/client.js\";\n * import { helloWorld } from \"./openworkflow/hello-world.js\";\n * const handle = await ow.runWorkflow(helloWorld.spec, {});\n * const result = await handle.result();\n * ```\n */\nexport const helloWorld = defineWorkflow(\n { name: \"hello-world\" },\n async ({ step }) => {\n const greeting = await step.run({ name: \"greet\" }, () => {\n return \"Hello, World!\";\n });\n\n await step.sleep(\"wait-a-bit\", \"1s\");\n\n return { greeting };\n },\n);\n";
5
6
  //# sourceMappingURL=templates.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../templates.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,uVAUzB,CAAC;AAEF,eAAO,MAAM,eAAe,+XAY3B,CAAC;AAEF,eAAO,MAAM,+BAA+B,glBAc3C,CAAC;AAEF,eAAO,MAAM,oBAAoB,8VAchC,CAAC"}
1
+ {"version":3,"file":"templates.d.ts","sourceRoot":"","sources":["../templates.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,aAAa,sPAKzB,CAAC;AAEF,eAAO,MAAM,eAAe,wRAO3B,CAAC;AAEF,eAAO,MAAM,+BAA+B,mcAS3C,CAAC;AAEF,eAAO,MAAM,MAAM,gMAOlB,CAAC;AAEF,eAAO,MAAM,oBAAoB,wvBA0BhC,CAAC"}
package/dist/templates.js CHANGED
@@ -1,44 +1,49 @@
1
- export const SQLITE_CONFIG = `import { BackendSqlite } from "@openworkflow/backend-sqlite";
2
- import { defineConfig } from "@openworkflow/cli";
3
-
4
- export default defineConfig({
5
- // Use SQLite as the backend
6
- backend: BackendSqlite.connect("openworkflow/backend.db"),
1
+ export const SQLITE_CLIENT = `import { BackendSqlite } from "@openworkflow/backend-sqlite";
2
+ import { OpenWorkflow } from "openworkflow";
7
3
 
8
- // The directories where your workflows are defined
9
- dirs: "./openworkflow",
10
- });
4
+ export const backend = BackendSqlite.connect("openworkflow/backend.db");
5
+ export const ow = new OpenWorkflow({ backend });
11
6
  `;
12
- export const POSTGRES_CONFIG = `import { BackendPostgres } from "@openworkflow/backend-postgres";
13
- import { defineConfig } from "@openworkflow/cli";
14
-
15
- export default defineConfig({
16
- // Use Postgres as the backend
17
- backend: await BackendPostgres.connect(
18
- process.env["OPENWORKFLOW_POSTGRES_URL"],
19
- ),
7
+ export const POSTGRES_CLIENT = `import { BackendPostgres } from "@openworkflow/backend-postgres";
8
+ import { OpenWorkflow } from "openworkflow";
20
9
 
21
- // The directories where your workflows are defined
22
- dirs: "./openworkflow",
23
- });
10
+ export const backend = await BackendPostgres.connect(
11
+ process.env["OPENWORKFLOW_POSTGRES_URL"],
12
+ );
13
+ export const ow = new OpenWorkflow({ backend });
24
14
  `;
25
- export const POSTGRES_PROD_SQLITE_DEV_CONFIG = `import { BackendPostgres } from "@openworkflow/backend-postgres";
15
+ export const POSTGRES_PROD_SQLITE_DEV_CLIENT = `import { BackendPostgres } from "@openworkflow/backend-postgres";
26
16
  import { BackendSqlite } from "@openworkflow/backend-sqlite";
17
+ import { OpenWorkflow } from "openworkflow";
18
+
19
+ export const backend =
20
+ process.env["NODE_ENV"] === "production"
21
+ ? await BackendPostgres.connect(process.env["OPENWORKFLOW_POSTGRES_URL"])
22
+ : BackendSqlite.connect("openworkflow/backend.db");
23
+ export const ow = new OpenWorkflow({ backend });
24
+ `;
25
+ export const CONFIG = `import { backend } from "./openworkflow/client.js";
27
26
  import { defineConfig } from "@openworkflow/cli";
28
27
 
29
28
  export default defineConfig({
30
- // Use Postgres as the backend in production, otherwise use SQLite
31
- backend:
32
- process.env["NODE_ENV"] === "production"
33
- ? await BackendPostgres.connect(process.env["OPENWORKFLOW_POSTGRES_URL"])
34
- : BackendSqlite.connect("openworkflow/backend.db"),
35
-
36
- // The directories where your workflows are defined
29
+ backend,
37
30
  dirs: "./openworkflow",
38
31
  });
39
32
  `;
40
33
  export const HELLO_WORLD_WORKFLOW = `import { defineWorkflow } from "openworkflow";
41
34
 
35
+ /**
36
+ * Example workflow that greets the world.
37
+ *
38
+ * This workflow is auto-discovered by the CLI worker.
39
+ * To trigger it, use ow.runWorkflow() from your app:
40
+ * \`\`\`ts
41
+ * import { ow } from "./openworkflow/client.js";
42
+ * import { helloWorld } from "./openworkflow/hello-world.js";
43
+ * const handle = await ow.runWorkflow(helloWorld.spec, {});
44
+ * const result = await handle.result();
45
+ * \`\`\`
46
+ */
42
47
  export const helloWorld = defineWorkflow(
43
48
  { name: "hello-world" },
44
49
  async ({ step }) => {
@@ -52,4 +57,3 @@ export const helloWorld = defineWorkflow(
52
57
  },
53
58
  );
54
59
  `;
55
- //# sourceMappingURL=templates.js.map
@@ -1,20 +1,26 @@
1
- import { POSTGRES_CONFIG, POSTGRES_PROD_SQLITE_DEV_CONFIG, SQLITE_CONFIG, } from "./templates.js";
1
+ import { CONFIG_TEMPLATE, POSTGRES_CLIENT, POSTGRES_PROD_SQLITE_DEV_CLIENT, SQLITE_CLIENT, } from "./templates.js";
2
2
  import { describe, expect, test } from "vitest";
3
- describe("config templates", () => {
4
- const templates = [
5
- SQLITE_CONFIG,
6
- POSTGRES_CONFIG,
7
- POSTGRES_PROD_SQLITE_DEV_CONFIG,
8
- ];
9
- test("import defineConfig from the CLI entrypoint", () => {
10
- for (const template of templates) {
11
- expect(template).toContain('import { defineConfig } from "@openworkflow/cli";');
12
- }
3
+ describe("client templates", () => {
4
+ test("sqlite client exports backend and ow", () => {
5
+ expect(SQLITE_CLIENT).toContain("export const backend");
6
+ expect(SQLITE_CLIENT).toContain("new OpenWorkflow");
7
+ expect(SQLITE_CLIENT).toContain("BackendSqlite");
8
+ });
9
+ test("postgres client exports backend and ow", () => {
10
+ expect(POSTGRES_CLIENT).toContain("export const backend");
11
+ expect(POSTGRES_CLIENT).toContain("new OpenWorkflow");
12
+ expect(POSTGRES_CLIENT).toContain("BackendPostgres");
13
+ });
14
+ test("prod postgres dev sqlite client exports backend and ow", () => {
15
+ expect(POSTGRES_PROD_SQLITE_DEV_CLIENT).toContain("export const backend");
16
+ expect(POSTGRES_PROD_SQLITE_DEV_CLIENT).toContain("new OpenWorkflow");
17
+ expect(POSTGRES_PROD_SQLITE_DEV_CLIENT).toContain("BackendSqlite");
18
+ expect(POSTGRES_PROD_SQLITE_DEV_CLIENT).toContain("BackendPostgres");
13
19
  });
14
- test("do not import the config subpath", () => {
15
- for (const template of templates) {
16
- expect(template).not.toContain('from "@openworkflow/cli/config";');
17
- }
20
+ });
21
+ describe("config templates", () => {
22
+ test("config references backend from client file", () => {
23
+ expect(CONFIG_TEMPLATE).toContain('import { backend } from "./openworkflow/client.js"');
24
+ expect(CONFIG_TEMPLATE).toContain("backend,");
18
25
  });
19
26
  });
20
- //# sourceMappingURL=templates.test.js.map