zephyr-cli 0.0.3 → 0.1.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/.eslintignore +3 -0
- package/.eslintrc.json +22 -0
- package/LICENSE +40 -21
- package/README.md +90 -17
- package/dist/cli.d.ts +25 -0
- package/dist/cli.js +141 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/deploy.d.ts +12 -0
- package/dist/commands/deploy.js +60 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/run.d.ts +9 -0
- package/dist/commands/run.js +161 -0
- package/dist/commands/run.js.map +1 -0
- package/dist/index.js +48 -60
- package/dist/index.js.map +1 -0
- package/dist/lib/build-stats.d.ts +7 -0
- package/dist/lib/build-stats.js +12 -0
- package/dist/lib/build-stats.js.map +1 -0
- package/dist/lib/command-detector.d.ts +38 -0
- package/dist/lib/command-detector.js +453 -0
- package/dist/lib/command-detector.js.map +1 -0
- package/dist/lib/config-readers.d.ts +37 -0
- package/dist/lib/config-readers.js +239 -0
- package/dist/lib/config-readers.js.map +1 -0
- package/dist/lib/extract-assets.d.ts +6 -0
- package/dist/lib/extract-assets.js +95 -0
- package/dist/lib/extract-assets.js.map +1 -0
- package/dist/lib/shell-parser.d.ts +40 -0
- package/dist/lib/shell-parser.js +190 -0
- package/dist/lib/shell-parser.js.map +1 -0
- package/dist/lib/spawn-helper.d.ts +14 -0
- package/dist/lib/spawn-helper.js +36 -0
- package/dist/lib/spawn-helper.js.map +1 -0
- package/dist/lib/upload.d.ts +14 -0
- package/dist/lib/upload.js +32 -0
- package/dist/lib/upload.js.map +1 -0
- package/dist/package.json +48 -0
- package/dist/tsconfig.tsbuildinfo +1 -0
- package/jest.config.ts +10 -0
- package/package.json +38 -21
- package/project.json +34 -0
- package/src/cli.ts +150 -0
- package/src/commands/deploy.ts +74 -0
- package/src/commands/run.ts +196 -0
- package/src/index.ts +58 -0
- package/src/lib/build-stats.ts +13 -0
- package/src/lib/command-detector.ts +600 -0
- package/src/lib/config-readers.ts +269 -0
- package/src/lib/extract-assets.ts +111 -0
- package/src/lib/shell-parser.ts +229 -0
- package/src/lib/spawn-helper.ts +49 -0
- package/src/lib/upload.ts +39 -0
- package/tsconfig.json +22 -0
- package/tsconfig.lib.json +10 -0
- package/tsconfig.spec.json +14 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export interface PackageJsonConfig {
|
|
2
|
+
scripts?: Record<string, string>;
|
|
3
|
+
[key: string]: unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface TsConfigJson {
|
|
6
|
+
compilerOptions?: {
|
|
7
|
+
outDir?: string;
|
|
8
|
+
rootDir?: string;
|
|
9
|
+
[key: string]: unknown;
|
|
10
|
+
};
|
|
11
|
+
[key: string]: unknown;
|
|
12
|
+
}
|
|
13
|
+
/** Read and parse package.json from the given directory */
|
|
14
|
+
export declare function readPackageJson(cwd: string): PackageJsonConfig | null;
|
|
15
|
+
/** Read and parse tsconfig.json from the given directory */
|
|
16
|
+
export declare function readTsConfig(cwd: string, configPath?: string): TsConfigJson | null;
|
|
17
|
+
/** Check if a file exists and has a .js or .mjs extension */
|
|
18
|
+
export declare function isJavaScriptConfig(cwd: string, baseName: string): boolean;
|
|
19
|
+
/** Check if a configuration file exists (any extension) */
|
|
20
|
+
export declare function configFileExists(cwd: string, baseName: string): string | null;
|
|
21
|
+
/** Generic interface for framework configuration with output directory */
|
|
22
|
+
export interface FrameworkConfig {
|
|
23
|
+
/** The detected output directory from the config */
|
|
24
|
+
outputDir?: string | null;
|
|
25
|
+
/** The full configuration object (framework-specific) */
|
|
26
|
+
config: any;
|
|
27
|
+
/** The file path where the config was loaded from */
|
|
28
|
+
filepath: string;
|
|
29
|
+
}
|
|
30
|
+
/** Load Webpack configuration using cosmiconfig */
|
|
31
|
+
export declare function loadWebpackConfig(cwd: string): Promise<FrameworkConfig | null>;
|
|
32
|
+
/** Load Vite configuration using cosmiconfig */
|
|
33
|
+
export declare function loadViteConfig(cwd: string): Promise<FrameworkConfig | null>;
|
|
34
|
+
/** Load Rollup configuration using cosmiconfig */
|
|
35
|
+
export declare function loadRollupConfig(cwd: string): Promise<FrameworkConfig | null>;
|
|
36
|
+
/** Load SWC configuration using cosmiconfig */
|
|
37
|
+
export declare function loadSwcConfig(cwd: string): Promise<FrameworkConfig | null>;
|
|
@@ -0,0 +1,239 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.readPackageJson = readPackageJson;
|
|
4
|
+
exports.readTsConfig = readTsConfig;
|
|
5
|
+
exports.isJavaScriptConfig = isJavaScriptConfig;
|
|
6
|
+
exports.configFileExists = configFileExists;
|
|
7
|
+
exports.loadWebpackConfig = loadWebpackConfig;
|
|
8
|
+
exports.loadViteConfig = loadViteConfig;
|
|
9
|
+
exports.loadRollupConfig = loadRollupConfig;
|
|
10
|
+
exports.loadSwcConfig = loadSwcConfig;
|
|
11
|
+
const cosmiconfig_1 = require("cosmiconfig");
|
|
12
|
+
const jsonc_parser_1 = require("jsonc-parser");
|
|
13
|
+
const node_fs_1 = require("node:fs");
|
|
14
|
+
const node_path_1 = require("node:path");
|
|
15
|
+
/** Read and parse package.json from the given directory */
|
|
16
|
+
function readPackageJson(cwd) {
|
|
17
|
+
const packageJsonPath = (0, node_path_1.join)(cwd, 'package.json');
|
|
18
|
+
if (!(0, node_fs_1.existsSync)(packageJsonPath)) {
|
|
19
|
+
return null;
|
|
20
|
+
}
|
|
21
|
+
try {
|
|
22
|
+
const content = (0, node_fs_1.readFileSync)(packageJsonPath, 'utf-8');
|
|
23
|
+
return (0, jsonc_parser_1.parse)(content);
|
|
24
|
+
}
|
|
25
|
+
catch (_a) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Read and parse tsconfig.json from the given directory */
|
|
30
|
+
function readTsConfig(cwd, configPath = 'tsconfig.json') {
|
|
31
|
+
const tsConfigPath = (0, node_path_1.join)(cwd, configPath);
|
|
32
|
+
if (!(0, node_fs_1.existsSync)(tsConfigPath)) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
try {
|
|
36
|
+
const content = (0, node_fs_1.readFileSync)(tsConfigPath, 'utf-8');
|
|
37
|
+
// Parse JSON with comments support using jsonc-parser
|
|
38
|
+
return (0, jsonc_parser_1.parse)(content);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
console.error(`Error reading tsconfig.json: ${error}`);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/** Check if a file exists and has a .js or .mjs extension */
|
|
46
|
+
function isJavaScriptConfig(cwd, baseName) {
|
|
47
|
+
const jsExtensions = ['.js', '.mjs', '.cjs', '.ts', '.mts', '.cts'];
|
|
48
|
+
for (const ext of jsExtensions) {
|
|
49
|
+
const configPath = (0, node_path_1.join)(cwd, `${baseName}${ext}`);
|
|
50
|
+
if ((0, node_fs_1.existsSync)(configPath)) {
|
|
51
|
+
return true;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
/** Check if a configuration file exists (any extension) */
|
|
57
|
+
function configFileExists(cwd, baseName) {
|
|
58
|
+
const extensions = ['.json', '.js', '.mjs', '.cjs', '.ts'];
|
|
59
|
+
for (const ext of extensions) {
|
|
60
|
+
const configPath = (0, node_path_1.join)(cwd, `${baseName}${ext}`);
|
|
61
|
+
if ((0, node_fs_1.existsSync)(configPath)) {
|
|
62
|
+
return configPath;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
return null;
|
|
66
|
+
}
|
|
67
|
+
/** Load Webpack configuration using cosmiconfig */
|
|
68
|
+
async function loadWebpackConfig(cwd) {
|
|
69
|
+
var _a, _b;
|
|
70
|
+
try {
|
|
71
|
+
const explorer = (0, cosmiconfig_1.cosmiconfig)('webpack', {
|
|
72
|
+
searchPlaces: [
|
|
73
|
+
'webpack.config.js',
|
|
74
|
+
'webpack.config.mjs',
|
|
75
|
+
'webpack.config.cjs',
|
|
76
|
+
'webpack.config.ts',
|
|
77
|
+
],
|
|
78
|
+
});
|
|
79
|
+
const result = await explorer.search(cwd);
|
|
80
|
+
if (!result || !result.config) {
|
|
81
|
+
return null;
|
|
82
|
+
}
|
|
83
|
+
// Extract output.path from webpack config
|
|
84
|
+
let outputDir = null;
|
|
85
|
+
const config = result.config;
|
|
86
|
+
// Handle function configs (they receive env and argv)
|
|
87
|
+
if (typeof config === 'function') {
|
|
88
|
+
try {
|
|
89
|
+
const resolvedConfig = await config({}, { mode: 'production' });
|
|
90
|
+
outputDir = ((_a = resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.output) === null || _a === void 0 ? void 0 : _a.path) || null;
|
|
91
|
+
}
|
|
92
|
+
catch (_c) {
|
|
93
|
+
// If function execution fails, we can't extract the output
|
|
94
|
+
outputDir = null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
else if ((_b = config === null || config === void 0 ? void 0 : config.output) === null || _b === void 0 ? void 0 : _b.path) {
|
|
98
|
+
outputDir = config.output.path;
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
outputDir,
|
|
102
|
+
config: result.config,
|
|
103
|
+
filepath: result.filepath,
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
catch (_d) {
|
|
107
|
+
// If loading fails, return null
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
/** Load Vite configuration using cosmiconfig */
|
|
112
|
+
async function loadViteConfig(cwd) {
|
|
113
|
+
var _a, _b;
|
|
114
|
+
try {
|
|
115
|
+
const explorer = (0, cosmiconfig_1.cosmiconfig)('vite', {
|
|
116
|
+
searchPlaces: [
|
|
117
|
+
'vite.config.js',
|
|
118
|
+
'vite.config.mjs',
|
|
119
|
+
'vite.config.cjs',
|
|
120
|
+
'vite.config.ts',
|
|
121
|
+
],
|
|
122
|
+
});
|
|
123
|
+
const result = await explorer.search(cwd);
|
|
124
|
+
if (!result || !result.config) {
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
// Extract build.outDir from vite config
|
|
128
|
+
let outputDir = null;
|
|
129
|
+
const config = result.config;
|
|
130
|
+
// Handle function configs (they receive config env)
|
|
131
|
+
if (typeof config === 'function') {
|
|
132
|
+
try {
|
|
133
|
+
const resolvedConfig = await config({ mode: 'production', command: 'build' });
|
|
134
|
+
outputDir = ((_a = resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.build) === null || _a === void 0 ? void 0 : _a.outDir) || 'dist';
|
|
135
|
+
}
|
|
136
|
+
catch (_c) {
|
|
137
|
+
outputDir = 'dist'; // Vite default
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
else if ((_b = config === null || config === void 0 ? void 0 : config.build) === null || _b === void 0 ? void 0 : _b.outDir) {
|
|
141
|
+
outputDir = config.build.outDir;
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
outputDir = 'dist'; // Vite default
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
outputDir,
|
|
148
|
+
config: result.config,
|
|
149
|
+
filepath: result.filepath,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
catch (_d) {
|
|
153
|
+
return null;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
/** Load Rollup configuration using cosmiconfig */
|
|
157
|
+
async function loadRollupConfig(cwd) {
|
|
158
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
|
|
159
|
+
try {
|
|
160
|
+
const explorer = (0, cosmiconfig_1.cosmiconfig)('rollup', {
|
|
161
|
+
searchPlaces: [
|
|
162
|
+
'rollup.config.js',
|
|
163
|
+
'rollup.config.mjs',
|
|
164
|
+
'rollup.config.cjs',
|
|
165
|
+
'rollup.config.ts',
|
|
166
|
+
],
|
|
167
|
+
});
|
|
168
|
+
const result = await explorer.search(cwd);
|
|
169
|
+
if (!result || !result.config) {
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
172
|
+
// Extract output.dir or output.file from rollup config
|
|
173
|
+
let outputDir = null;
|
|
174
|
+
const config = result.config;
|
|
175
|
+
// Handle function configs
|
|
176
|
+
if (typeof config === 'function') {
|
|
177
|
+
try {
|
|
178
|
+
const resolvedConfig = await config({});
|
|
179
|
+
if (Array.isArray(resolvedConfig)) {
|
|
180
|
+
// Multiple outputs - take the first one
|
|
181
|
+
outputDir =
|
|
182
|
+
((_b = (_a = resolvedConfig[0]) === null || _a === void 0 ? void 0 : _a.output) === null || _b === void 0 ? void 0 : _b.dir) || ((_d = (_c = resolvedConfig[0]) === null || _c === void 0 ? void 0 : _c.output) === null || _d === void 0 ? void 0 : _d.file) || null;
|
|
183
|
+
}
|
|
184
|
+
else {
|
|
185
|
+
outputDir = ((_e = resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.output) === null || _e === void 0 ? void 0 : _e.dir) || ((_f = resolvedConfig === null || resolvedConfig === void 0 ? void 0 : resolvedConfig.output) === null || _f === void 0 ? void 0 : _f.file) || null;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
catch (_l) {
|
|
189
|
+
outputDir = null;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
else if (Array.isArray(config)) {
|
|
193
|
+
// Multiple outputs - take the first one
|
|
194
|
+
outputDir = ((_h = (_g = config[0]) === null || _g === void 0 ? void 0 : _g.output) === null || _h === void 0 ? void 0 : _h.dir) || ((_k = (_j = config[0]) === null || _j === void 0 ? void 0 : _j.output) === null || _k === void 0 ? void 0 : _k.file) || null;
|
|
195
|
+
}
|
|
196
|
+
else if (config === null || config === void 0 ? void 0 : config.output) {
|
|
197
|
+
const output = Array.isArray(config.output) ? config.output[0] : config.output;
|
|
198
|
+
outputDir = (output === null || output === void 0 ? void 0 : output.dir) || (output === null || output === void 0 ? void 0 : output.file) || null;
|
|
199
|
+
}
|
|
200
|
+
// If outputDir is a file path, extract the directory
|
|
201
|
+
if (outputDir && outputDir.includes('.')) {
|
|
202
|
+
const lastSlash = Math.max(outputDir.lastIndexOf('/'), outputDir.lastIndexOf('\\'));
|
|
203
|
+
if (lastSlash !== -1) {
|
|
204
|
+
outputDir = outputDir.substring(0, lastSlash);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
outputDir,
|
|
209
|
+
config: result.config,
|
|
210
|
+
filepath: result.filepath,
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
catch (_m) {
|
|
214
|
+
return null;
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
/** Load SWC configuration using cosmiconfig */
|
|
218
|
+
async function loadSwcConfig(cwd) {
|
|
219
|
+
try {
|
|
220
|
+
const explorer = (0, cosmiconfig_1.cosmiconfig)('swc', {
|
|
221
|
+
searchPlaces: ['.swcrc', '.swcrc.json', '.swcrc.js', '.swcrc.mjs', '.swcrc.cjs'],
|
|
222
|
+
});
|
|
223
|
+
const result = await explorer.search(cwd);
|
|
224
|
+
if (!result || !result.config) {
|
|
225
|
+
return null;
|
|
226
|
+
}
|
|
227
|
+
// SWC doesn't have a standard output directory config
|
|
228
|
+
// Most projects use a custom output directory
|
|
229
|
+
return {
|
|
230
|
+
outputDir: null,
|
|
231
|
+
config: result.config,
|
|
232
|
+
filepath: result.filepath,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
catch (_a) {
|
|
236
|
+
return null;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
//# sourceMappingURL=config-readers.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-readers.js","sourceRoot":"","sources":["../../src/lib/config-readers.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { type ZeBuildAssetsMap } from 'zephyr-agent';
|
|
2
|
+
/**
|
|
3
|
+
* Extract assets map from a directory by recursively walking through it. Similar to
|
|
4
|
+
* extractAstroAssetsMap but for any directory.
|
|
5
|
+
*/
|
|
6
|
+
export declare function extractAssetsFromDirectory(buildDir: string): Promise<ZeBuildAssetsMap>;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractAssetsFromDirectory = extractAssetsFromDirectory;
|
|
4
|
+
const promises_1 = require("node:fs/promises");
|
|
5
|
+
const node_path_1 = require("node:path");
|
|
6
|
+
const zephyr_agent_1 = require("zephyr-agent");
|
|
7
|
+
function extractBuffer(asset) {
|
|
8
|
+
return asset.content;
|
|
9
|
+
}
|
|
10
|
+
function getAssetType(asset) {
|
|
11
|
+
return asset.type;
|
|
12
|
+
}
|
|
13
|
+
/** Normalize path separators to forward slashes for cross-platform consistency */
|
|
14
|
+
function normalizePath(filePath) {
|
|
15
|
+
return filePath.split(node_path_1.sep).join('/');
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Extract assets map from a directory by recursively walking through it. Similar to
|
|
19
|
+
* extractAstroAssetsMap but for any directory.
|
|
20
|
+
*/
|
|
21
|
+
async function extractAssetsFromDirectory(buildDir) {
|
|
22
|
+
const assets = {};
|
|
23
|
+
// Recursively walk through the build directory
|
|
24
|
+
async function walkDir(dirPath) {
|
|
25
|
+
try {
|
|
26
|
+
const entries = await (0, promises_1.readdir)(dirPath, { withFileTypes: true });
|
|
27
|
+
for (const entry of entries) {
|
|
28
|
+
const fullPath = (0, node_path_1.join)(dirPath, entry.name);
|
|
29
|
+
if (entry.isDirectory()) {
|
|
30
|
+
await walkDir(fullPath);
|
|
31
|
+
}
|
|
32
|
+
else if (entry.isFile()) {
|
|
33
|
+
// Get relative path from build directory
|
|
34
|
+
const relativePath = normalizePath((0, node_path_1.relative)(buildDir, fullPath));
|
|
35
|
+
// Skip certain files that shouldn't be uploaded
|
|
36
|
+
if (shouldSkipFile(relativePath)) {
|
|
37
|
+
continue;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const content = await (0, promises_1.readFile)(fullPath);
|
|
41
|
+
const fileType = getFileType(relativePath);
|
|
42
|
+
assets[relativePath] = {
|
|
43
|
+
content,
|
|
44
|
+
type: fileType,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
catch (readError) {
|
|
48
|
+
(0, zephyr_agent_1.logFn)('warn', `Failed to read file ${fullPath}: ${readError}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
(0, zephyr_agent_1.logFn)('warn', `Failed to walk directory ${dirPath}: ${error}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
await walkDir(buildDir);
|
|
58
|
+
return (0, zephyr_agent_1.buildAssetsMap)(assets, extractBuffer, getAssetType);
|
|
59
|
+
}
|
|
60
|
+
function shouldSkipFile(filePath) {
|
|
61
|
+
// Skip common files that shouldn't be uploaded
|
|
62
|
+
const skipPatterns = [
|
|
63
|
+
/\.map$/, // Source maps
|
|
64
|
+
/node_modules/, // Node modules
|
|
65
|
+
/\.git/, // Git files
|
|
66
|
+
/\.DS_Store$/, // macOS files
|
|
67
|
+
/thumbs\.db$/i, // Windows files
|
|
68
|
+
];
|
|
69
|
+
return skipPatterns.some((pattern) => pattern.test(filePath));
|
|
70
|
+
}
|
|
71
|
+
function getFileType(filePath) {
|
|
72
|
+
var _a;
|
|
73
|
+
const extension = ((_a = filePath.split('.').pop()) === null || _a === void 0 ? void 0 : _a.toLowerCase()) || '';
|
|
74
|
+
const typeMap = {
|
|
75
|
+
html: 'text/html',
|
|
76
|
+
css: 'text/css',
|
|
77
|
+
js: 'application/javascript',
|
|
78
|
+
mjs: 'application/javascript',
|
|
79
|
+
json: 'application/json',
|
|
80
|
+
png: 'image/png',
|
|
81
|
+
jpg: 'image/jpeg',
|
|
82
|
+
jpeg: 'image/jpeg',
|
|
83
|
+
gif: 'image/gif',
|
|
84
|
+
svg: 'image/svg+xml',
|
|
85
|
+
ico: 'image/x-icon',
|
|
86
|
+
woff: 'font/woff',
|
|
87
|
+
woff2: 'font/woff2',
|
|
88
|
+
ttf: 'font/ttf',
|
|
89
|
+
eot: 'application/vnd.ms-fontobject',
|
|
90
|
+
xml: 'text/xml',
|
|
91
|
+
txt: 'text/plain',
|
|
92
|
+
};
|
|
93
|
+
return typeMap[extension] || 'application/octet-stream';
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=extract-assets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"extract-assets.js","sourceRoot":"","sources":["../../src/lib/extract-assets.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
export interface ParsedCommand {
|
|
2
|
+
/** The main command to execute (without environment variables) */
|
|
3
|
+
command: string;
|
|
4
|
+
/** Environment variables set for this command */
|
|
5
|
+
envVars: Record<string, string>;
|
|
6
|
+
/** Arguments passed to the command */
|
|
7
|
+
args: string[];
|
|
8
|
+
/** The full command line as a string */
|
|
9
|
+
fullCommand: string;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Parse a shell command to extract the actual command, args, and environment variables.
|
|
13
|
+
* Uses simple regex-based parsing to handle common cases like:
|
|
14
|
+
*
|
|
15
|
+
* - `pnpm build`
|
|
16
|
+
* - `NODE_ENV=production webpack --mode production`
|
|
17
|
+
* - `KEY1=value1 KEY2=value2 command arg1 arg2`
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* parseShellCommand('NODE_ENV=production webpack --mode production');
|
|
21
|
+
* // Returns: { command: 'webpack', envVars: { NODE_ENV: 'production' }, args: ['--mode', 'production'] }
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* parseShellCommand('pnpm build');
|
|
25
|
+
* // Returns: { command: 'pnpm', envVars: {}, args: ['build'] }
|
|
26
|
+
*/
|
|
27
|
+
export declare function parseShellCommand(commandLine: string): ParsedCommand;
|
|
28
|
+
/**
|
|
29
|
+
* Split a command line into multiple commands based on shell operators (;, &&) Respects
|
|
30
|
+
* quotes and escapes.
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* splitCommands('npm run build && npm run test');
|
|
34
|
+
* // Returns: ['npm run build', 'npm run test']
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* splitCommands('echo "hello; world" && npm run build');
|
|
38
|
+
* // Returns: ['echo "hello; world"', 'npm run build']
|
|
39
|
+
*/
|
|
40
|
+
export declare function splitCommands(commandLine: string): string[];
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseShellCommand = parseShellCommand;
|
|
4
|
+
exports.splitCommands = splitCommands;
|
|
5
|
+
const zephyr_agent_1 = require("zephyr-agent");
|
|
6
|
+
/**
|
|
7
|
+
* Parse a shell command to extract the actual command, args, and environment variables.
|
|
8
|
+
* Uses simple regex-based parsing to handle common cases like:
|
|
9
|
+
*
|
|
10
|
+
* - `pnpm build`
|
|
11
|
+
* - `NODE_ENV=production webpack --mode production`
|
|
12
|
+
* - `KEY1=value1 KEY2=value2 command arg1 arg2`
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* parseShellCommand('NODE_ENV=production webpack --mode production');
|
|
16
|
+
* // Returns: { command: 'webpack', envVars: { NODE_ENV: 'production' }, args: ['--mode', 'production'] }
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* parseShellCommand('pnpm build');
|
|
20
|
+
* // Returns: { command: 'pnpm', envVars: {}, args: ['build'] }
|
|
21
|
+
*/
|
|
22
|
+
function parseShellCommand(commandLine) {
|
|
23
|
+
const envVars = {};
|
|
24
|
+
const trimmed = commandLine.trim();
|
|
25
|
+
if (!trimmed) {
|
|
26
|
+
throw new zephyr_agent_1.ZephyrError(zephyr_agent_1.ZeErrors.ERR_UNKNOWN, {
|
|
27
|
+
message: 'Empty command line',
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// Split by whitespace while respecting quotes
|
|
31
|
+
const tokens = tokenizeCommand(trimmed);
|
|
32
|
+
if (tokens.length === 0) {
|
|
33
|
+
throw new zephyr_agent_1.ZephyrError(zephyr_agent_1.ZeErrors.ERR_UNKNOWN, {
|
|
34
|
+
message: `Failed to parse command: ${commandLine}`,
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
let i = 0;
|
|
38
|
+
// Extract environment variables (KEY=VALUE format at the beginning)
|
|
39
|
+
while (i < tokens.length) {
|
|
40
|
+
const token = tokens[i];
|
|
41
|
+
const match = token.match(/^([A-Za-z_][A-Za-z0-9_]*)=(.*)$/);
|
|
42
|
+
if (match) {
|
|
43
|
+
const [, name, value] = match;
|
|
44
|
+
envVars[name] = value;
|
|
45
|
+
i++;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
break;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
// The next token should be the command
|
|
52
|
+
if (i >= tokens.length) {
|
|
53
|
+
throw new zephyr_agent_1.ZephyrError(zephyr_agent_1.ZeErrors.ERR_UNKNOWN, {
|
|
54
|
+
message: `Failed to parse command: ${commandLine}\nNo command found after environment variables`,
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
const command = tokens[i];
|
|
58
|
+
i++;
|
|
59
|
+
// Remaining tokens are arguments
|
|
60
|
+
const args = tokens.slice(i);
|
|
61
|
+
return {
|
|
62
|
+
command,
|
|
63
|
+
envVars,
|
|
64
|
+
args,
|
|
65
|
+
fullCommand: commandLine,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Split a command line into multiple commands based on shell operators (;, &&) Respects
|
|
70
|
+
* quotes and escapes.
|
|
71
|
+
*
|
|
72
|
+
* @example
|
|
73
|
+
* splitCommands('npm run build && npm run test');
|
|
74
|
+
* // Returns: ['npm run build', 'npm run test']
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* splitCommands('echo "hello; world" && npm run build');
|
|
78
|
+
* // Returns: ['echo "hello; world"', 'npm run build']
|
|
79
|
+
*/
|
|
80
|
+
function splitCommands(commandLine) {
|
|
81
|
+
const commands = [];
|
|
82
|
+
let current = '';
|
|
83
|
+
let inSingleQuote = false;
|
|
84
|
+
let inDoubleQuote = false;
|
|
85
|
+
let escaped = false;
|
|
86
|
+
for (let i = 0; i < commandLine.length; i++) {
|
|
87
|
+
const char = commandLine[i];
|
|
88
|
+
const nextChar = i + 1 < commandLine.length ? commandLine[i + 1] : '';
|
|
89
|
+
if (escaped) {
|
|
90
|
+
current += char;
|
|
91
|
+
escaped = false;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (char === '\\') {
|
|
95
|
+
current += char;
|
|
96
|
+
escaped = true;
|
|
97
|
+
continue;
|
|
98
|
+
}
|
|
99
|
+
if (char === "'" && !inDoubleQuote) {
|
|
100
|
+
inSingleQuote = !inSingleQuote;
|
|
101
|
+
current += char;
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
if (char === '"' && !inSingleQuote) {
|
|
105
|
+
inDoubleQuote = !inDoubleQuote;
|
|
106
|
+
current += char;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
// Check for shell operators outside quotes
|
|
110
|
+
if (!inSingleQuote && !inDoubleQuote) {
|
|
111
|
+
// Check for &&
|
|
112
|
+
if (char === '&' && nextChar === '&') {
|
|
113
|
+
const trimmed = current.trim();
|
|
114
|
+
if (trimmed) {
|
|
115
|
+
commands.push(trimmed);
|
|
116
|
+
}
|
|
117
|
+
current = '';
|
|
118
|
+
i++; // Skip the next &
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
// Check for ;
|
|
122
|
+
if (char === ';') {
|
|
123
|
+
const trimmed = current.trim();
|
|
124
|
+
if (trimmed) {
|
|
125
|
+
commands.push(trimmed);
|
|
126
|
+
}
|
|
127
|
+
current = '';
|
|
128
|
+
continue;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
current += char;
|
|
132
|
+
}
|
|
133
|
+
// Add the last command if any
|
|
134
|
+
const trimmed = current.trim();
|
|
135
|
+
if (trimmed) {
|
|
136
|
+
commands.push(trimmed);
|
|
137
|
+
}
|
|
138
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
139
|
+
throw new zephyr_agent_1.ZephyrError(zephyr_agent_1.ZeErrors.ERR_UNKNOWN, {
|
|
140
|
+
message: 'Unmatched quote in command line',
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
return commands;
|
|
144
|
+
}
|
|
145
|
+
/** Tokenize a command line string, respecting quotes and escapes */
|
|
146
|
+
function tokenizeCommand(commandLine) {
|
|
147
|
+
const tokens = [];
|
|
148
|
+
let current = '';
|
|
149
|
+
let inSingleQuote = false;
|
|
150
|
+
let inDoubleQuote = false;
|
|
151
|
+
let escaped = false;
|
|
152
|
+
for (let i = 0; i < commandLine.length; i++) {
|
|
153
|
+
const char = commandLine[i];
|
|
154
|
+
if (escaped) {
|
|
155
|
+
current += char;
|
|
156
|
+
escaped = false;
|
|
157
|
+
continue;
|
|
158
|
+
}
|
|
159
|
+
if (char === '\\') {
|
|
160
|
+
escaped = true;
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
if (char === "'" && !inDoubleQuote) {
|
|
164
|
+
inSingleQuote = !inSingleQuote;
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
if (char === '"' && !inSingleQuote) {
|
|
168
|
+
inDoubleQuote = !inDoubleQuote;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
if (/\s/.test(char) && !inSingleQuote && !inDoubleQuote) {
|
|
172
|
+
if (current) {
|
|
173
|
+
tokens.push(current);
|
|
174
|
+
current = '';
|
|
175
|
+
}
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
current += char;
|
|
179
|
+
}
|
|
180
|
+
if (current) {
|
|
181
|
+
tokens.push(current);
|
|
182
|
+
}
|
|
183
|
+
if (inSingleQuote || inDoubleQuote) {
|
|
184
|
+
throw new zephyr_agent_1.ZephyrError(zephyr_agent_1.ZeErrors.ERR_UNKNOWN, {
|
|
185
|
+
message: 'Unmatched quote in command line',
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
return tokens;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=shell-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"shell-parser.js","sourceRoot":"","sources":["../../src/lib/shell-parser.ts"],"names":[],"mappings":";;AA6BA,8CAsDC;AAcD,sCA2EC;AA5KD,+CAAqD;AAarD;;;;;;;;;;;;;;;GAeG;AACH,SAAgB,iBAAiB,CAAC,WAAmB;IACnD,MAAM,OAAO,GAA2B,EAAE,CAAC;IAC3C,MAAM,OAAO,GAAG,WAAW,CAAC,IAAI,EAAE,CAAC;IAEnC,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,0BAAW,CAAC,uBAAQ,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE,oBAAoB;SAC9B,CAAC,CAAC;IACL,CAAC;IAED,8CAA8C;IAC9C,MAAM,MAAM,GAAG,eAAe,CAAC,OAAO,CAAC,CAAC;IAExC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,0BAAW,CAAC,uBAAQ,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE,4BAA4B,WAAW,EAAE;SACnD,CAAC,CAAC;IACL,CAAC;IAED,IAAI,CAAC,GAAG,CAAC,CAAC;IAEV,oEAAoE;IACpE,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;QACxB,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC;QAE7D,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,GAAG,KAAK,CAAC;YAC9B,OAAO,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;YACtB,CAAC,EAAE,CAAC;QACN,CAAC;aAAM,CAAC;YACN,MAAM;QACR,CAAC;IACH,CAAC;IAED,uCAAuC;IACvC,IAAI,CAAC,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACvB,MAAM,IAAI,0BAAW,CAAC,uBAAQ,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE,4BAA4B,WAAW,gDAAgD;SACjG,CAAC,CAAC;IACL,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC;IAC1B,CAAC,EAAE,CAAC;IAEJ,iCAAiC;IACjC,MAAM,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;IAE7B,OAAO;QACL,OAAO;QACP,OAAO;QACP,IAAI;QACJ,WAAW,EAAE,WAAW;KACzB,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,SAAgB,aAAa,CAAC,WAAmB;IAC/C,MAAM,QAAQ,GAAa,EAAE,CAAC;IAC9B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAC5B,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEtE,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,IAAI,IAAI,CAAC;YAChB,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,IAAI,IAAI,CAAC;YAChB,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,OAAO,IAAI,IAAI,CAAC;YAChB,SAAS;QACX,CAAC;QAED,2CAA2C;QAC3C,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,EAAE,CAAC;YACrC,eAAe;YACf,IAAI,IAAI,KAAK,GAAG,IAAI,QAAQ,KAAK,GAAG,EAAE,CAAC;gBACrC,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC/B,IAAI,OAAO,EAAE,CAAC;oBACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzB,CAAC;gBACD,OAAO,GAAG,EAAE,CAAC;gBACb,CAAC,EAAE,CAAC,CAAC,kBAAkB;gBACvB,SAAS;YACX,CAAC;YAED,cAAc;YACd,IAAI,IAAI,KAAK,GAAG,EAAE,CAAC;gBACjB,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;gBAC/B,IAAI,OAAO,EAAE,CAAC;oBACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACzB,CAAC;gBACD,OAAO,GAAG,EAAE,CAAC;gBACb,SAAS;YACX,CAAC;QACH,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IAED,8BAA8B;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,IAAI,EAAE,CAAC;IAC/B,IAAI,OAAO,EAAE,CAAC;QACZ,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACzB,CAAC;IAED,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,IAAI,0BAAW,CAAC,uBAAQ,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE,iCAAiC;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,oEAAoE;AACpE,SAAS,eAAe,CAAC,WAAmB;IAC1C,MAAM,MAAM,GAAa,EAAE,CAAC;IAC5B,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,aAAa,GAAG,KAAK,CAAC;IAC1B,IAAI,OAAO,GAAG,KAAK,CAAC;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;QAC5C,MAAM,IAAI,GAAG,WAAW,CAAC,CAAC,CAAC,CAAC;QAE5B,IAAI,OAAO,EAAE,CAAC;YACZ,OAAO,IAAI,IAAI,CAAC;YAChB,OAAO,GAAG,KAAK,CAAC;YAChB,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,IAAI,EAAE,CAAC;YAClB,OAAO,GAAG,IAAI,CAAC;YACf,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,IAAI,IAAI,KAAK,GAAG,IAAI,CAAC,aAAa,EAAE,CAAC;YACnC,aAAa,GAAG,CAAC,aAAa,CAAC;YAC/B,SAAS;QACX,CAAC;QAED,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,aAAa,IAAI,CAAC,aAAa,EAAE,CAAC;YACxD,IAAI,OAAO,EAAE,CAAC;gBACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACrB,OAAO,GAAG,EAAE,CAAC;YACf,CAAC;YACD,SAAS;QACX,CAAC;QAED,OAAO,IAAI,IAAI,CAAC;IAClB,CAAC;IAED,IAAI,OAAO,EAAE,CAAC;QACZ,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IAED,IAAI,aAAa,IAAI,aAAa,EAAE,CAAC;QACnC,MAAM,IAAI,0BAAW,CAAC,uBAAQ,CAAC,WAAW,EAAE;YAC1C,OAAO,EAAE,iCAAiC;SAC3C,CAAC,CAAC;IACL,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { ParsedCommand } from './shell-parser';
|
|
2
|
+
export interface SpawnResult {
|
|
3
|
+
exitCode: number;
|
|
4
|
+
signal: NodeJS.Signals | null;
|
|
5
|
+
}
|
|
6
|
+
/**
|
|
7
|
+
* Execute a command with full stdio passthrough. All stdin, stdout, and stderr are
|
|
8
|
+
* proxied between the parent and child process.
|
|
9
|
+
*
|
|
10
|
+
* @param parsed - The parsed command to execute
|
|
11
|
+
* @param cwd - The working directory
|
|
12
|
+
* @returns Promise that resolves with exit code and signal
|
|
13
|
+
*/
|
|
14
|
+
export declare function executeCommand(parsed: ParsedCommand, cwd: string): Promise<SpawnResult>;
|