@dagucloud/dagu 2.6.4

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/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @dagucloud/dagu
2
+
3
+ > A powerful Workflow Orchestration Engine with simple declarative YAML API
4
+
5
+ [![npm version](https://img.shields.io/npm/v/%40dagucloud%2Fdagu.svg)](https://www.npmjs.com/package/@dagucloud/dagu)
6
+ [![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0)
7
+
8
+ ## Installation
9
+
10
+ ```bash
11
+ npm install -g @dagucloud/dagu
12
+ ```
13
+
14
+ Or add to your project:
15
+
16
+ ```bash
17
+ npm install @dagucloud/dagu
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ### Command Line
23
+
24
+ After installation, the `dagu` command will be available:
25
+
26
+ ```bash
27
+ # Start the web UI and scheduler
28
+ dagu start-all
29
+
30
+ # Run a workflow
31
+ dagu start my-workflow.yaml
32
+
33
+ # Check workflow status
34
+ dagu status my-workflow.yaml
35
+ ```
36
+
37
+ ### Programmatic Usage
38
+
39
+ ```javascript
40
+ const { execute, getDaguPath } = require('@dagucloud/dagu');
41
+
42
+ // Get path to the binary
43
+ const daguPath = getDaguPath();
44
+
45
+ // Execute dagu commands
46
+ const child = execute(['start', 'workflow.yaml']);
47
+
48
+ // Or use async/await
49
+ const { executeAsync } = require('@dagucloud/dagu');
50
+
51
+ async function runWorkflow() {
52
+ const result = await executeAsync(['start', 'workflow.yaml']);
53
+ console.log('Exit code:', result.code);
54
+ console.log('Output:', result.stdout);
55
+ }
56
+ ```
57
+
58
+ ## Supported Platforms
59
+
60
+ This package provides pre-built binaries for:
61
+
62
+ - **Linux**: x64, arm64, arm (v6/v7), ia32, ppc64le, s390x
63
+ - **macOS**: x64 (Intel), arm64 (Apple Silicon)
64
+ - **Windows**: x64, ia32, arm64
65
+ - **FreeBSD**: x64, arm64
66
+ - **OpenBSD**: x64, arm64
67
+
68
+ If your platform is not supported, please build from source: https://github.com/dagucloud/dagu#building-from-source
69
+
70
+ ## Features
71
+
72
+ - **Zero Dependencies** - Single binary, no runtime requirements
73
+ - **Declarative YAML** - Define workflows in simple YAML format
74
+ - **Web UI** - Beautiful dashboard for monitoring and management
75
+ - **Powerful Scheduling** - Cron expressions, dependencies, and complex workflows
76
+ - **Language Agnostic** - Run any command, script, or executable
77
+
78
+ ## Documentation
79
+
80
+ For detailed documentation, visit: https://github.com/dagucloud/dagu
81
+
82
+ ## License
83
+
84
+ GNU General Public License v3.0
package/bin/cli ADDED
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+
3
+ const path = require("path");
4
+ const childProcess = require("child_process");
5
+
6
+ const { getPlatformPackage } = require("../lib/platform");
7
+
8
+ const binaryName = process.platform === "win32" ? "dagu.exe" : "dagu";
9
+
10
+ function getBinaryPath() {
11
+ const platformSpecificPackageName = getPlatformPackage();
12
+
13
+ try {
14
+ return require.resolve(`@dagucloud/${platformSpecificPackageName}/bin/${binaryName}`);
15
+ } catch (e) {
16
+ return path.join(__dirname, "..", binaryName);
17
+ }
18
+ }
19
+
20
+ function exitForError(error) {
21
+ if (error && typeof error.status === "number") {
22
+ process.exit(error.status);
23
+ }
24
+
25
+ if (error && error.signal) {
26
+ process.kill(process.pid, error.signal);
27
+ return;
28
+ }
29
+
30
+ const message = error && typeof error.message === "string" ? error.message : "dagu execution failed";
31
+ if (message) {
32
+ process.stderr.write(`${message}\n`);
33
+ }
34
+
35
+ process.exit(1);
36
+ }
37
+
38
+ try {
39
+ childProcess.execFileSync(getBinaryPath(), process.argv.slice(2), {
40
+ stdio: "inherit",
41
+ });
42
+ } catch (error) {
43
+ exitForError(error);
44
+ }
package/index.js ADDED
@@ -0,0 +1,48 @@
1
+ /**
2
+ * Copyright (C) 2026 Yota Hamada
3
+ * SPDX-License-Identifier: GPL-3.0-or-later
4
+ */
5
+
6
+ const path = require("path");
7
+ const childProcess = require("child_process");
8
+
9
+ const { getPlatformPackage } = require("./lib/platform");
10
+
11
+ const binaryName = process.platform === "win32" ? "dagu.exe" : "dagu";
12
+
13
+ function getBinaryPath() {
14
+ try {
15
+ const platformSpecificPackageName = getPlatformPackage();
16
+ return require.resolve(`@dagucloud/${platformSpecificPackageName}/bin/${binaryName}`);
17
+ } catch (e) {
18
+ return path.join(__dirname, binaryName);
19
+ }
20
+ }
21
+
22
+ function exitForError(error) {
23
+ if (error && typeof error.status === "number") {
24
+ process.exit(error.status);
25
+ }
26
+
27
+ if (error && error.signal) {
28
+ process.kill(process.pid, error.signal);
29
+ return;
30
+ }
31
+
32
+ const message = error && typeof error.message === "string" ? error.message : "dagu execution failed";
33
+ if (message) {
34
+ process.stderr.write(`${message}\n`);
35
+ }
36
+
37
+ process.exit(1);
38
+ }
39
+
40
+ module.exports.runBinary = function (...args) {
41
+ try {
42
+ childProcess.execFileSync(getBinaryPath(), args, {
43
+ stdio: "inherit",
44
+ });
45
+ } catch (error) {
46
+ exitForError(error);
47
+ }
48
+ };
package/install.js ADDED
@@ -0,0 +1,117 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Copyright (C) 2026 Yota Hamada
4
+ * SPDX-License-Identifier: GPL-3.0-or-later
5
+ */
6
+
7
+
8
+ const fs = require("fs");
9
+ const path = require("path");
10
+ const zlib = require("zlib");
11
+ const https = require("https");
12
+
13
+ const { getPlatformPackage, isPlatformSpecificPackageInstalled } = require("./lib/platform");
14
+
15
+ // Windows binaries end with .exe so we need to special case them.
16
+ const binaryName = process.platform === "win32" ? "dagu.exe" : "dagu";
17
+
18
+ // Adjust the version you want to install. You can also make this dynamic.
19
+ const PACKAGE_VERSION = require("./package.json").version;
20
+
21
+ // Compute the path we want to emit the fallback binary to
22
+ const fallbackBinaryPath = path.join(__dirname, binaryName);
23
+
24
+ function makeRequest(url) {
25
+ return new Promise((resolve, reject) => {
26
+ https
27
+ .get(url, (response) => {
28
+ if (response.statusCode >= 200 && response.statusCode < 300) {
29
+ const chunks = [];
30
+ response.on("data", (chunk) => chunks.push(chunk));
31
+ response.on("end", () => {
32
+ resolve(Buffer.concat(chunks));
33
+ });
34
+ } else if (
35
+ response.statusCode >= 300 &&
36
+ response.statusCode < 400 &&
37
+ response.headers.location
38
+ ) {
39
+ // Follow redirects
40
+ makeRequest(response.headers.location).then(resolve, reject);
41
+ } else {
42
+ reject(
43
+ new Error(
44
+ `npm responded with status code ${response.statusCode} when downloading the package!`
45
+ )
46
+ );
47
+ }
48
+ })
49
+ .on("error", (error) => {
50
+ reject(error);
51
+ });
52
+ });
53
+ }
54
+
55
+ function extractFileFromTarball(tarballBuffer, filepath) {
56
+ // Tar archives are organized in 512 byte blocks.
57
+ // Blocks can either be header blocks or data blocks.
58
+ // Header blocks contain file names of the archive in the first 100 bytes, terminated by a null byte.
59
+ // The size of a file is contained in bytes 124-135 of a header block and in octal format.
60
+ // The following blocks will be data blocks containing the file.
61
+ let offset = 0;
62
+ while (offset < tarballBuffer.length) {
63
+ const header = tarballBuffer.subarray(offset, offset + 512);
64
+ offset += 512;
65
+
66
+ const fileName = header.toString("utf-8", 0, 100).replace(/\0.*/g, "");
67
+ const fileSize = parseInt(
68
+ header.toString("utf-8", 124, 136).replace(/\0.*/g, ""),
69
+ 8
70
+ );
71
+
72
+ if (fileName === filepath) {
73
+ return tarballBuffer.subarray(offset, offset + fileSize);
74
+ }
75
+
76
+ // Clamp offset to the uppoer multiple of 512
77
+ offset = (offset + fileSize + 511) & ~511;
78
+ }
79
+ }
80
+
81
+ async function downloadBinaryFromNpm() {
82
+ console.log({
83
+ getPlatformPackage,
84
+ });
85
+ // Determine package name for this platform
86
+ const platformSpecificPackageName = getPlatformPackage();
87
+ if (!platformSpecificPackageName) {
88
+ throw new Error(`Unsupported platform: ${process.platform}/${process.arch}`);
89
+ }
90
+
91
+ const url = `https://registry.npmjs.org/@dagucloud/${platformSpecificPackageName}/-/${platformSpecificPackageName}-${PACKAGE_VERSION}.tgz`;
92
+ console.log(`Downloading binary distribution package from ${url}...`);
93
+ // Download the tarball of the right binary distribution package
94
+ const tarballDownloadBuffer = await makeRequest(url);
95
+ const tarballBuffer = zlib.unzipSync(tarballDownloadBuffer);
96
+
97
+ console.log(fallbackBinaryPath);
98
+
99
+ // Extract binary from package and write to disk
100
+ fs.writeFileSync(
101
+ fallbackBinaryPath,
102
+ extractFileFromTarball(tarballBuffer, `package/bin/${binaryName}`),
103
+ { mode: 0o755 } // Make binary file executable
104
+ );
105
+ }
106
+
107
+ // Skip downloading the binary if it was already installed via optionalDependencies
108
+ if (!isPlatformSpecificPackageInstalled()) {
109
+ console.log(
110
+ "Platform specific package not found. Will manually download binary."
111
+ );
112
+ downloadBinaryFromNpm();
113
+ } else {
114
+ console.log(
115
+ "Platform specific package already installed. Skipping manual binary download."
116
+ );
117
+ }
@@ -0,0 +1,179 @@
1
+ /**
2
+ * Copyright (C) 2026 Yota Hamada
3
+ * SPDX-License-Identifier: GPL-3.0-or-later
4
+ */
5
+
6
+ const path = require("path");
7
+ const fs = require("fs");
8
+
9
+ // Platform mapping from Node.js to npm package names
10
+ const PLATFORM_MAP = {
11
+ // Tier 1 - Most common platforms
12
+ "linux-x64": "dagu-linux-x64",
13
+ "linux-arm64": "dagu-linux-arm64",
14
+ "darwin-x64": "dagu-darwin-x64",
15
+ "darwin-arm64": "dagu-darwin-arm64",
16
+ "win32-x64": "dagu-win32-x64",
17
+
18
+ // Tier 2 - Common but less frequent
19
+ "linux-ia32": "dagu-linux-ia32",
20
+ "win32-ia32": "dagu-win32-ia32",
21
+ "freebsd-x64": "dagu-freebsd-x64",
22
+
23
+ // Tier 3 - Rare platforms
24
+ "win32-arm64": "dagu-win32-arm64",
25
+ "linux-ppc64": "dagu-linux-ppc64",
26
+ "linux-s390x": "dagu-linux-s390x",
27
+ "freebsd-arm64": "dagu-freebsd-arm64",
28
+ "openbsd-x64": "dagu-openbsd-x64",
29
+ "openbsd-arm64": "dagu-openbsd-arm64",
30
+ };
31
+
32
+ // Cache for binary path
33
+ let cachedBinaryPath = null;
34
+
35
+ /**
36
+ * Detect ARM variant on Linux systems
37
+ * @returns {string} ARM variant ('6' or '7')
38
+ */
39
+ function getArmVariant() {
40
+ // First try process.config
41
+ if (
42
+ process.config &&
43
+ process.config.variables &&
44
+ process.config.variables.arm_version
45
+ ) {
46
+ return String(process.config.variables.arm_version);
47
+ }
48
+
49
+ // On Linux, check /proc/cpuinfo
50
+ if (process.platform === "linux") {
51
+ try {
52
+ const cpuinfo = fs.readFileSync("/proc/cpuinfo", "utf8");
53
+
54
+ // Check for specific ARM architecture indicators
55
+ if (
56
+ cpuinfo.includes("ARMv6") ||
57
+ cpuinfo.includes("ARM926") ||
58
+ cpuinfo.includes("ARM1176")
59
+ ) {
60
+ return "6";
61
+ }
62
+ if (cpuinfo.includes("ARMv7") || cpuinfo.includes("Cortex-A")) {
63
+ return "7";
64
+ }
65
+
66
+ // Check CPU architecture field
67
+ const archMatch = cpuinfo.match(/^CPU architecture:\s*(\d+)/m);
68
+ if (archMatch && archMatch[1]) {
69
+ const arch = parseInt(archMatch[1], 10);
70
+ if (arch >= 7) return "7";
71
+ if (arch === 6) return "6";
72
+ }
73
+ } catch (e) {
74
+ // Ignore errors, fall through to default
75
+ }
76
+ }
77
+
78
+ // Default to ARMv7 (more common)
79
+ return "7";
80
+ }
81
+
82
+ /**
83
+ * Get the npm package name for the current platform
84
+ * @returns {string|null} Package name or null if unsupported
85
+ */
86
+ function getPlatformPackage() {
87
+ let platform = process.platform;
88
+ let arch = process.arch;
89
+
90
+ // Special handling for ARM on Linux
91
+ if (platform === "linux" && arch === "arm") {
92
+ const variant = getArmVariant();
93
+ return `dagu-linux-armv${variant}`;
94
+ }
95
+
96
+ const key = `${platform}-${arch}`;
97
+ return PLATFORM_MAP[key] || null;
98
+ }
99
+
100
+ /**
101
+ * Get the path to the Dagu binary
102
+ * @returns {string|null} Path to binary or null if not found
103
+ */
104
+ function getBinaryPath() {
105
+ // Return cached path if available
106
+ if (cachedBinaryPath && fs.existsSync(cachedBinaryPath)) {
107
+ return cachedBinaryPath;
108
+ }
109
+
110
+ const binaryName = process.platform === "win32" ? "dagu.exe" : "dagu";
111
+
112
+ // First, try platform-specific package
113
+ const platformPackage = getPlatformPackage();
114
+ if (platformPackage) {
115
+ try {
116
+ // Try to resolve the binary using require.resolve (Sentry approach)
117
+ const binaryPath = require.resolve(
118
+ `@dagucloud/${platformPackage}/bin/${binaryName}`
119
+ );
120
+ if (fs.existsSync(binaryPath)) {
121
+ cachedBinaryPath = binaryPath;
122
+ return binaryPath;
123
+ }
124
+ } catch (e) {
125
+ // Package not installed or binary not found
126
+ }
127
+ }
128
+
129
+ // Fallback to local binary in main package
130
+ const localBinary = path.join(__dirname, "..", binaryName);
131
+ if (fs.existsSync(localBinary)) {
132
+ cachedBinaryPath = localBinary;
133
+ return localBinary;
134
+ }
135
+
136
+ return null;
137
+ }
138
+
139
+ /**
140
+ * Set the cached binary path
141
+ * @param {string} binaryPath Path to the binary
142
+ */
143
+ function setPlatformBinary(binaryPath) {
144
+ cachedBinaryPath = binaryPath;
145
+ }
146
+
147
+ /**
148
+ * Check if platform-specific package is installed
149
+ * @returns {boolean} True if installed, false otherwise
150
+ */
151
+ function isPlatformSpecificPackageInstalled() {
152
+ const platformPackage = getPlatformPackage();
153
+ if (!platformPackage) {
154
+ return false;
155
+ }
156
+
157
+ const binaryName = process.platform === "win32" ? "dagu.exe" : "dagu";
158
+
159
+ try {
160
+ // Resolving will fail if the optionalDependency was not installed
161
+ require.resolve(`@dagucloud/${platformPackage}/bin/${binaryName}`);
162
+ return true;
163
+ } catch (e) {
164
+ return false;
165
+ }
166
+ }
167
+
168
+ module.exports = {
169
+ getPlatformPackage,
170
+ getBinaryPath,
171
+ setPlatformBinary,
172
+ isPlatformSpecificPackageInstalled,
173
+ getPlatformInfo: () => ({
174
+ platform: process.platform,
175
+ arch: process.arch,
176
+ nodeVersion: process.version,
177
+ detectedPackage: getPlatformPackage(),
178
+ }),
179
+ };
package/package.json ADDED
@@ -0,0 +1,65 @@
1
+ {
2
+ "name": "@dagucloud/dagu",
3
+ "version": "2.6.4",
4
+ "description": "A powerful Workflow Orchestration Engine with simple declarative YAML API. Zero-dependency, single binary for Linux, macOS, and Windows.",
5
+ "keywords": [
6
+ "workflow",
7
+ "automation",
8
+ "orchestration",
9
+ "dag",
10
+ "pipeline",
11
+ "scheduler",
12
+ "task-runner",
13
+ "workflow-engine",
14
+ "devops",
15
+ "ci-cd"
16
+ ],
17
+ "homepage": "https://github.com/dagucloud/dagu",
18
+ "bugs": {
19
+ "url": "https://github.com/dagucloud/dagu/issues"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "git+https://github.com/dagucloud/dagu.git"
24
+ },
25
+ "license": "GPL-3.0",
26
+ "author": "Dagu Contributors",
27
+ "bin": {
28
+ "dagu": "bin/cli"
29
+ },
30
+ "scripts": {
31
+ "postinstall": "node ./install.js"
32
+ },
33
+ "dependencies": {
34
+ "tar": "^7.4.3"
35
+ },
36
+ "optionalDependencies": {
37
+ "@dagucloud/dagu-darwin-arm64": "2.6.4",
38
+ "@dagucloud/dagu-darwin-x64": "2.6.4",
39
+ "@dagucloud/dagu-freebsd-arm64": "2.6.4",
40
+ "@dagucloud/dagu-freebsd-x64": "2.6.4",
41
+ "@dagucloud/dagu-linux-arm64": "2.6.4",
42
+ "@dagucloud/dagu-linux-armv6": "2.6.4",
43
+ "@dagucloud/dagu-linux-armv7": "2.6.4",
44
+ "@dagucloud/dagu-linux-ia32": "2.6.4",
45
+ "@dagucloud/dagu-linux-ppc64": "2.6.4",
46
+ "@dagucloud/dagu-linux-s390x": "2.6.4",
47
+ "@dagucloud/dagu-linux-x64": "2.6.4",
48
+ "@dagucloud/dagu-openbsd-arm64": "2.6.4",
49
+ "@dagucloud/dagu-openbsd-x64": "2.6.4",
50
+ "@dagucloud/dagu-win32-arm64": "2.6.4",
51
+ "@dagucloud/dagu-win32-ia32": "2.6.4",
52
+ "@dagucloud/dagu-win32-x64": "2.6.4"
53
+ },
54
+ "engines": {
55
+ "node": ">=14.0.0"
56
+ },
57
+ "files": [
58
+ "bin/",
59
+ "lib/",
60
+ "install.js",
61
+ "index.js",
62
+ "README.md",
63
+ "LICENSE"
64
+ ]
65
+ }