@heetmehta18/autodev 0.1.6 → 0.3.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/.turbo/turbo-test.log +49 -0
- package/README.md +17 -0
- package/bin/index.js +167 -67
- package/package.json +6 -6
- package/LICENSE +0 -21
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
|
|
2
|
+
|
|
3
|
+
> @heetmehta18/autodev@0.1.6 test /media/heet18/Futuristic/Heet/Github/Autodev/packages/npm-cli
|
|
4
|
+
> node bin/index.js --help
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
█████╗ ██╗ ██╗████████╗ ██████╗ ██████╗ ███████╗██╗ ██╗
|
|
8
|
+
██╔══██╗██║ ██║╚══██╔══╝██╔═══██╗██╔══██╗██╔════╝██║ ██║
|
|
9
|
+
███████║██║ ██║ ██║ ██║ ██║██║ ██║█████╗ ██║ ██║
|
|
10
|
+
██╔══██║██║ ██║ ██║ ██║ ██║██║ ██║██╔══╝ ╚██╗ ██╔╝
|
|
11
|
+
██║ ██║╚██████╔╝ ██║ ╚██████╔╝██████╔╝███████╗ ╚████╔╝
|
|
12
|
+
╚═╝ ╚═╝ ╚═════╝ ╚═╝ ╚══════╝ ╚═════╝ ╚══════╝ ╚═══╝
|
|
13
|
+
|
|
14
|
+
The App Store for Developers.
|
|
15
|
+
Run with no arguments to open the interactive installer.
|
|
16
|
+
|
|
17
|
+
Usage:
|
|
18
|
+
autodev [flags]
|
|
19
|
+
autodev [command]
|
|
20
|
+
|
|
21
|
+
Available Commands:
|
|
22
|
+
audit Audit repository dependencies for security vulnerabilities
|
|
23
|
+
clean Remove AutoDev cache and temp files
|
|
24
|
+
clone Clone a Git repository, scan it, and install all missing dependencies
|
|
25
|
+
completion Generate the autocompletion script for the specified shell
|
|
26
|
+
doctor Check the health of your development environment
|
|
27
|
+
export Export environment as a reproducible JSON lockfile
|
|
28
|
+
github Scan all public repositories for a GitHub user
|
|
29
|
+
help Help about any command
|
|
30
|
+
install Install a specific package by ID
|
|
31
|
+
mcp Start a Model Context Protocol (MCP) server
|
|
32
|
+
profile Install a pre-defined developer profile (role-based tool set)
|
|
33
|
+
report Generate a detailed environment report (HTML, JSON, Markdown)
|
|
34
|
+
scan Scan a repository for languages, frameworks, and dependencies
|
|
35
|
+
setup Detect and install all missing runtimes and dependencies
|
|
36
|
+
skills Generate a personalized learning roadmap based on detected technologies
|
|
37
|
+
ui Start the local AutoDev interactive web dashboard
|
|
38
|
+
update Check for and apply updates to managed packages
|
|
39
|
+
|
|
40
|
+
Flags:
|
|
41
|
+
--config string config file (default: .autodev.yaml)
|
|
42
|
+
--dry-run preview actions without executing
|
|
43
|
+
-h, --help help for autodev
|
|
44
|
+
--json output results as JSON
|
|
45
|
+
--no-color disable color output
|
|
46
|
+
-v, --verbose verbose output
|
|
47
|
+
--version version for autodev
|
|
48
|
+
|
|
49
|
+
Use "autodev [command] --help" for more information about a command.
|
package/README.md
CHANGED
|
@@ -5,24 +5,41 @@ This package provides a lightweight Node.js wrapper around the native Go compile
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
|
7
7
|
### Run via npx (No Installation Needed)
|
|
8
|
+
|
|
8
9
|
```bash
|
|
9
10
|
npx @heetmehta18/autodev --help
|
|
10
11
|
```
|
|
11
12
|
|
|
12
13
|
### Install Globally
|
|
14
|
+
|
|
13
15
|
```bash
|
|
14
16
|
npm install -g @heetmehta18/autodev
|
|
15
17
|
autodev --help
|
|
16
18
|
```
|
|
17
19
|
|
|
20
|
+
### Run Model Context Protocol (MCP) Server (Continuous Server)
|
|
21
|
+
|
|
22
|
+
The wrapper fully supports long-running stream-based commands like the AutoDev MCP server. To start the server and connect your AI coding tools (e.g. Claude Desktop, Cursor) to your local environment:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
# Run directly via npx
|
|
26
|
+
npx @heetmehta18/autodev mcp start
|
|
27
|
+
|
|
28
|
+
# Run globally (if installed)
|
|
29
|
+
autodev mcp start
|
|
30
|
+
```
|
|
31
|
+
|
|
18
32
|
## How It Works
|
|
33
|
+
|
|
19
34
|
1. **Platform Detection:** The JavaScript wrapper reads `process.platform` and `process.arch` to map the user's platform to the target release asset names (e.g. `linux/amd64`, `windows/arm64`, `darwin/arm64`).
|
|
20
35
|
2. **Dynamic Download:** If the native binary is not yet cached locally in this package's `bin/` directory, the wrapper automatically downloads the correct compressed release (`.tar.gz` or `.zip`) directly from the corresponding GitHub Release tag (matching the `package.json` version).
|
|
21
36
|
3. **Execution Delegation:** The wrapper spawns the native binary as a subprocess, forwarding all arguments, stdio streams, and exit codes. Future runs bypass the download step entirely for instant execution.
|
|
22
37
|
4. **Development DX Mode:** During local development, if a compiled binary is found under `packages/cli/bin/autodev`, the wrapper forwards execution directly to the local dev build, bypassing remote GitHub requests.
|
|
23
38
|
|
|
24
39
|
## Publishing
|
|
40
|
+
|
|
25
41
|
To publish updates to the npm registry:
|
|
42
|
+
|
|
26
43
|
1. Ensure the package version matches the GitHub release tag:
|
|
27
44
|
```bash
|
|
28
45
|
pnpm --filter=@heetmehta18/autodev version <new-version>
|
package/bin/index.js
CHANGED
|
@@ -1,49 +1,72 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const {
|
|
4
|
-
const path = require(
|
|
5
|
-
const fs = require(
|
|
6
|
-
const os = require(
|
|
7
|
-
const https = require(
|
|
8
|
-
const http = require(
|
|
3
|
+
const { spawn, execSync, execFileSync } = require("child_process");
|
|
4
|
+
const path = require("path");
|
|
5
|
+
const fs = require("fs");
|
|
6
|
+
const os = require("os");
|
|
7
|
+
const https = require("https");
|
|
8
|
+
const http = require("http");
|
|
9
9
|
|
|
10
10
|
// Determine OS & Arch mapping
|
|
11
11
|
const platformMap = {
|
|
12
|
-
darwin:
|
|
13
|
-
linux:
|
|
14
|
-
win32:
|
|
12
|
+
darwin: "darwin",
|
|
13
|
+
linux: "linux",
|
|
14
|
+
win32: "windows",
|
|
15
15
|
};
|
|
16
16
|
|
|
17
17
|
const archMap = {
|
|
18
|
-
x64:
|
|
19
|
-
arm64:
|
|
18
|
+
x64: "amd64",
|
|
19
|
+
arm64: "arm64",
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
const platform = platformMap[process.platform];
|
|
23
23
|
const arch = archMap[process.arch];
|
|
24
24
|
|
|
25
25
|
if (!platform || !arch) {
|
|
26
|
-
console.error(
|
|
26
|
+
console.error(
|
|
27
|
+
`[autodev] Unsupported platform/architecture: ${process.platform}/${process.arch}`,
|
|
28
|
+
);
|
|
27
29
|
process.exit(1);
|
|
28
30
|
}
|
|
29
31
|
|
|
30
|
-
const ext = platform ===
|
|
31
|
-
const binaryName = platform ===
|
|
32
|
+
const ext = platform === "windows" ? "zip" : "tar.gz";
|
|
33
|
+
const binaryName = platform === "windows" ? "autodev.exe" : "autodev";
|
|
32
34
|
|
|
33
35
|
// Version: prefer the latest GitHub release tag; fall back to package.json
|
|
34
|
-
const pkgJson = require(
|
|
36
|
+
const pkgJson = require("../package.json");
|
|
35
37
|
const fallbackVersion = `v${pkgJson.version}`;
|
|
36
38
|
|
|
37
39
|
function getLatestReleaseTag() {
|
|
38
|
-
|
|
39
|
-
const
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
40
|
+
return new Promise((resolve) => {
|
|
41
|
+
const options = {
|
|
42
|
+
hostname: "api.github.com",
|
|
43
|
+
path: "/repos/HEETMEHTA18/autodev/releases/latest",
|
|
44
|
+
headers: {
|
|
45
|
+
"User-Agent": "autodev-npm-cli",
|
|
46
|
+
},
|
|
47
|
+
timeout: 5000,
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
https
|
|
51
|
+
.get(options, (res) => {
|
|
52
|
+
let body = "";
|
|
53
|
+
res.on("data", (chunk) => (body += chunk));
|
|
54
|
+
res.on("end", () => {
|
|
55
|
+
try {
|
|
56
|
+
const json = JSON.parse(body);
|
|
57
|
+
const versionRegex = /^v?\d+\.\d+\.\d+(-[a-zA-Z0-9.]+)?$/;
|
|
58
|
+
if (json.tag_name && versionRegex.test(json.tag_name)) {
|
|
59
|
+
resolve(json.tag_name);
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
} catch (_) {}
|
|
63
|
+
resolve(fallbackVersion);
|
|
64
|
+
});
|
|
65
|
+
})
|
|
66
|
+
.on("error", () => {
|
|
67
|
+
resolve(fallbackVersion);
|
|
68
|
+
});
|
|
69
|
+
});
|
|
47
70
|
}
|
|
48
71
|
|
|
49
72
|
// Resolve target paths
|
|
@@ -52,9 +75,9 @@ const binaryPath = path.join(binDir, binaryName);
|
|
|
52
75
|
|
|
53
76
|
// Development fallback paths
|
|
54
77
|
const devPaths = [
|
|
55
|
-
path.join(__dirname,
|
|
56
|
-
path.join(__dirname,
|
|
57
|
-
path.join(__dirname,
|
|
78
|
+
path.join(__dirname, "..", "..", "cli", "bin", binaryName),
|
|
79
|
+
path.join(__dirname, "..", "..", "..", "bin", binaryName),
|
|
80
|
+
path.join(__dirname, "..", "..", "..", "packages", "cli", "bin", binaryName),
|
|
58
81
|
];
|
|
59
82
|
|
|
60
83
|
let activeBinaryPath = binaryPath;
|
|
@@ -74,35 +97,43 @@ for (const devPath of devPaths) {
|
|
|
74
97
|
*/
|
|
75
98
|
function download(url, destPath, maxRedirects = 5) {
|
|
76
99
|
return new Promise((resolve, reject) => {
|
|
77
|
-
if (maxRedirects <= 0) return reject(new Error(
|
|
78
|
-
|
|
79
|
-
const client = url.startsWith('https') ? https : http;
|
|
80
|
-
client.get(url, (res) => {
|
|
81
|
-
// Follow redirects (GitHub releases return 302)
|
|
82
|
-
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
83
|
-
return download(res.headers.location, destPath, maxRedirects - 1)
|
|
84
|
-
.then(resolve)
|
|
85
|
-
.catch(reject);
|
|
86
|
-
}
|
|
100
|
+
if (maxRedirects <= 0) return reject(new Error("Too many redirects"));
|
|
87
101
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
102
|
+
const client = url.startsWith("https") ? https : http;
|
|
103
|
+
client
|
|
104
|
+
.get(url, (res) => {
|
|
105
|
+
// Follow redirects (GitHub releases return 302)
|
|
106
|
+
if (
|
|
107
|
+
res.statusCode >= 300 &&
|
|
108
|
+
res.statusCode < 400 &&
|
|
109
|
+
res.headers.location
|
|
110
|
+
) {
|
|
111
|
+
return download(res.headers.location, destPath, maxRedirects - 1)
|
|
112
|
+
.then(resolve)
|
|
113
|
+
.catch(reject);
|
|
114
|
+
}
|
|
91
115
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
116
|
+
if (res.statusCode !== 200) {
|
|
117
|
+
return reject(new Error(`HTTP ${res.statusCode} from ${url}`));
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const fileStream = fs.createWriteStream(destPath);
|
|
121
|
+
res.pipe(fileStream);
|
|
122
|
+
fileStream.on("finish", () => {
|
|
123
|
+
fileStream.close();
|
|
124
|
+
resolve();
|
|
125
|
+
});
|
|
126
|
+
fileStream.on("error", reject);
|
|
127
|
+
})
|
|
128
|
+
.on("error", reject);
|
|
100
129
|
});
|
|
101
130
|
}
|
|
102
131
|
|
|
103
132
|
async function downloadBinary() {
|
|
104
|
-
|
|
105
|
-
console.log(
|
|
133
|
+
let version = await getLatestReleaseTag();
|
|
134
|
+
console.log(
|
|
135
|
+
`\n[autodev] Native binary not found. Downloading AutoDev ${version} for ${platform}/${arch}...`,
|
|
136
|
+
);
|
|
106
137
|
|
|
107
138
|
if (!fs.existsSync(binDir)) {
|
|
108
139
|
fs.mkdirSync(binDir, { recursive: true });
|
|
@@ -111,42 +142,86 @@ async function downloadBinary() {
|
|
|
111
142
|
// Construct download URL
|
|
112
143
|
const archiveName = `autodev_${platform}_${arch}`;
|
|
113
144
|
const archiveFile = `${archiveName}.${ext}`;
|
|
114
|
-
|
|
145
|
+
let url = `https://github.com/HEETMEHTA18/autodev/releases/download/${version}/${archiveFile}`;
|
|
115
146
|
|
|
116
|
-
const tempFile = path.join(
|
|
147
|
+
const tempFile = path.join(
|
|
148
|
+
os.tmpdir(),
|
|
149
|
+
`autodev_download_${Date.now()}.${ext}`,
|
|
150
|
+
);
|
|
117
151
|
|
|
118
152
|
// Download using Node.js built-in HTTPS (handles redirects properly)
|
|
119
153
|
try {
|
|
120
154
|
console.log(`[autodev] Downloading from: ${url}`);
|
|
121
155
|
await download(url, tempFile);
|
|
156
|
+
} catch (err) {
|
|
157
|
+
const stableFallback = "v0.3.0";
|
|
158
|
+
if (version !== stableFallback) {
|
|
159
|
+
console.warn(
|
|
160
|
+
`\n[autodev] Failed to download version ${version}: ${err.message}`,
|
|
161
|
+
);
|
|
162
|
+
console.warn(
|
|
163
|
+
`[autodev] Falling back to last known stable release: ${stableFallback}...`,
|
|
164
|
+
);
|
|
165
|
+
version = stableFallback;
|
|
166
|
+
url = `https://github.com/HEETMEHTA18/autodev/releases/download/${version}/${archiveFile}`;
|
|
167
|
+
try {
|
|
168
|
+
console.log(`[autodev] Downloading from: ${url}`);
|
|
169
|
+
await download(url, tempFile);
|
|
170
|
+
} catch (retryErr) {
|
|
171
|
+
console.error(
|
|
172
|
+
`\n[autodev] Error downloading stable release asset: ${retryErr.message}`,
|
|
173
|
+
);
|
|
174
|
+
console.error(`[autodev] Please verify your network connection.`);
|
|
175
|
+
process.exit(1);
|
|
176
|
+
}
|
|
177
|
+
} else {
|
|
178
|
+
console.error(
|
|
179
|
+
`\n[autodev] Error downloading release asset: ${err.message}`,
|
|
180
|
+
);
|
|
181
|
+
console.error(`[autodev] URL: ${url}`);
|
|
182
|
+
process.exit(1);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
122
185
|
|
|
186
|
+
try {
|
|
123
187
|
// Verify the file was actually downloaded
|
|
124
188
|
if (!fs.existsSync(tempFile)) {
|
|
125
|
-
throw new Error(
|
|
189
|
+
throw new Error("Download completed but file not found on disk.");
|
|
126
190
|
}
|
|
127
191
|
const stat = fs.statSync(tempFile);
|
|
128
192
|
if (stat.size < 1000) {
|
|
129
|
-
throw new Error(
|
|
193
|
+
throw new Error(
|
|
194
|
+
`Downloaded file is too small (${stat.size} bytes), likely an error page.`,
|
|
195
|
+
);
|
|
130
196
|
}
|
|
131
|
-
console.log(
|
|
197
|
+
console.log(
|
|
198
|
+
`[autodev] Downloaded ${(stat.size / 1024 / 1024).toFixed(1)} MB`,
|
|
199
|
+
);
|
|
132
200
|
} catch (err) {
|
|
133
|
-
console.error(`\n[autodev] Error
|
|
134
|
-
console.error(`[autodev] URL: ${url}`);
|
|
135
|
-
console.error(`[autodev] Please verify that the release version ${version} exists and has compiled assets.`);
|
|
201
|
+
console.error(`\n[autodev] Error verifying download: ${err.message}`);
|
|
136
202
|
process.exit(1);
|
|
137
203
|
}
|
|
138
204
|
|
|
139
205
|
// Extract
|
|
140
206
|
console.log(`[autodev] Extracting binary...`);
|
|
141
207
|
try {
|
|
142
|
-
if (ext ===
|
|
143
|
-
if (process.platform ===
|
|
144
|
-
|
|
208
|
+
if (ext === "zip") {
|
|
209
|
+
if (process.platform === "win32") {
|
|
210
|
+
const escapedTempFile = tempFile.replace(/'/g, "''");
|
|
211
|
+
const escapedBinDir = binDir.replace(/'/g, "''");
|
|
212
|
+
execSync(
|
|
213
|
+
`powershell -Command "Expand-Archive -Path '${escapedTempFile}' -DestinationPath '${escapedBinDir}' -Force"`,
|
|
214
|
+
{ stdio: "inherit" },
|
|
215
|
+
);
|
|
145
216
|
} else {
|
|
146
|
-
|
|
217
|
+
execFileSync("unzip", ["-o", tempFile, "-d", binDir], {
|
|
218
|
+
stdio: "inherit",
|
|
219
|
+
});
|
|
147
220
|
}
|
|
148
221
|
} else {
|
|
149
|
-
|
|
222
|
+
execFileSync("tar", ["-xzf", tempFile, "-C", binDir], {
|
|
223
|
+
stdio: "inherit",
|
|
224
|
+
});
|
|
150
225
|
}
|
|
151
226
|
|
|
152
227
|
// Clean up temp archive
|
|
@@ -155,7 +230,7 @@ async function downloadBinary() {
|
|
|
155
230
|
}
|
|
156
231
|
|
|
157
232
|
// Set execution permissions on Linux/macOS
|
|
158
|
-
if (process.platform !==
|
|
233
|
+
if (process.platform !== "win32" && fs.existsSync(binaryPath)) {
|
|
159
234
|
fs.chmodSync(binaryPath, 0o755);
|
|
160
235
|
}
|
|
161
236
|
console.log(`[autodev] Installation successful.\n`);
|
|
@@ -175,11 +250,36 @@ async function main() {
|
|
|
175
250
|
await downloadBinary();
|
|
176
251
|
}
|
|
177
252
|
|
|
178
|
-
// Forward execution
|
|
253
|
+
// Forward execution asynchronously to handle long-running / interactive processes properly
|
|
179
254
|
const args = process.argv.slice(2);
|
|
180
|
-
const
|
|
255
|
+
const child = spawn(activeBinaryPath, args, { stdio: "inherit" });
|
|
256
|
+
|
|
257
|
+
// Forward termination signals to the child process (critical for long-running servers / MCP)
|
|
258
|
+
const signals = ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"];
|
|
259
|
+
signals.forEach((signal) => {
|
|
260
|
+
process.on(signal, () => {
|
|
261
|
+
if (!child.killed) {
|
|
262
|
+
child.kill(signal);
|
|
263
|
+
}
|
|
264
|
+
});
|
|
265
|
+
});
|
|
181
266
|
|
|
182
|
-
|
|
267
|
+
child.on("close", (code, signal) => {
|
|
268
|
+
if (code !== null) {
|
|
269
|
+
process.exit(code);
|
|
270
|
+
} else if (signal) {
|
|
271
|
+
// Exit with standard 128 + signal number
|
|
272
|
+
const signalCodes = { SIGINT: 2, SIGTERM: 15, SIGHUP: 1, SIGQUIT: 3 };
|
|
273
|
+
process.exit(128 + (signalCodes[signal] || 0));
|
|
274
|
+
} else {
|
|
275
|
+
process.exit(0);
|
|
276
|
+
}
|
|
277
|
+
});
|
|
278
|
+
|
|
279
|
+
child.on("error", (err) => {
|
|
280
|
+
console.error(`[autodev] Failed to run binary: ${err.message}`);
|
|
281
|
+
process.exit(1);
|
|
282
|
+
});
|
|
183
283
|
}
|
|
184
284
|
|
|
185
285
|
main().catch((err) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@heetmehta18/autodev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "The App Store for Developers. Install languages, frameworks, and databases with a single command.",
|
|
5
5
|
"main": "bin/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -9,6 +9,9 @@
|
|
|
9
9
|
"publishConfig": {
|
|
10
10
|
"access": "public"
|
|
11
11
|
},
|
|
12
|
+
"scripts": {
|
|
13
|
+
"test": "node bin/index.js --help"
|
|
14
|
+
},
|
|
12
15
|
"repository": {
|
|
13
16
|
"type": "git",
|
|
14
17
|
"url": "git+https://github.com/HEETMEHTA18/autodev.git"
|
|
@@ -27,8 +30,5 @@
|
|
|
27
30
|
"bugs": {
|
|
28
31
|
"url": "https://github.com/HEETMEHTA18/autodev/issues"
|
|
29
32
|
},
|
|
30
|
-
"homepage": "https://github.com/HEETMEHTA18/autodev#readme"
|
|
31
|
-
|
|
32
|
-
"test": "node bin/index.js --help"
|
|
33
|
-
}
|
|
34
|
-
}
|
|
33
|
+
"homepage": "https://github.com/HEETMEHTA18/autodev#readme"
|
|
34
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 AutoDev Contributors
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|