sitevision-cli 0.0.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/dist/app.d.ts +7 -0
- package/dist/app.js +180 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +95 -0
- package/dist/commands/build.d.ts +12 -0
- package/dist/commands/build.js +168 -0
- package/dist/commands/deploy.d.ts +17 -0
- package/dist/commands/deploy.js +162 -0
- package/dist/commands/dev.d.ts +15 -0
- package/dist/commands/dev.js +291 -0
- package/dist/commands/index.d.ts +4 -0
- package/dist/commands/index.js +20 -0
- package/dist/commands/info.d.ts +2 -0
- package/dist/commands/info.js +66 -0
- package/dist/commands/setup-signing.d.ts +2 -0
- package/dist/commands/setup-signing.js +82 -0
- package/dist/commands/sign.d.ts +14 -0
- package/dist/commands/sign.js +103 -0
- package/dist/commands/types.d.ts +18 -0
- package/dist/commands/types.js +1 -0
- package/dist/components/DevPropertiesForm.d.ts +11 -0
- package/dist/components/DevPropertiesForm.js +87 -0
- package/dist/components/InfoScreen.d.ts +8 -0
- package/dist/components/InfoScreen.js +60 -0
- package/dist/components/MainMenu.d.ts +8 -0
- package/dist/components/MainMenu.js +138 -0
- package/dist/components/PasswordInput.d.ts +8 -0
- package/dist/components/PasswordInput.js +30 -0
- package/dist/components/ProcessOutput.d.ts +7 -0
- package/dist/components/ProcessOutput.js +32 -0
- package/dist/components/SetupFlow.d.ts +8 -0
- package/dist/components/SetupFlow.js +194 -0
- package/dist/components/SigningPropertiesForm.d.ts +8 -0
- package/dist/components/SigningPropertiesForm.js +49 -0
- package/dist/components/StatusIndicator.d.ts +9 -0
- package/dist/components/StatusIndicator.js +36 -0
- package/dist/components/TextInput.d.ts +11 -0
- package/dist/components/TextInput.js +37 -0
- package/dist/types/index.d.ts +250 -0
- package/dist/types/index.js +6 -0
- package/dist/utils/password-prompt.d.ts +4 -0
- package/dist/utils/password-prompt.js +45 -0
- package/dist/utils/process-runner.d.ts +30 -0
- package/dist/utils/process-runner.js +119 -0
- package/dist/utils/project-detection.d.ts +103 -0
- package/dist/utils/project-detection.js +287 -0
- package/dist/utils/sitevision-api.d.ts +56 -0
- package/dist/utils/sitevision-api.js +393 -0
- package/dist/utils/webpack-runner.d.ts +75 -0
- package/dist/utils/webpack-runner.js +313 -0
- package/dist/utils/zip.d.ts +64 -0
- package/dist/utils/zip.js +246 -0
- package/package.json +59 -0
- package/readme.md +196 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
export type Status = 'pending' | 'running' | 'success' | 'error';
|
|
3
|
+
interface Props {
|
|
4
|
+
status: Status;
|
|
5
|
+
label: string;
|
|
6
|
+
message?: string;
|
|
7
|
+
}
|
|
8
|
+
export declare function StatusIndicator({ status, label, message }: Props): React.JSX.Element;
|
|
9
|
+
export {};
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import Spinner from 'ink-spinner';
|
|
4
|
+
export function StatusIndicator({ status, label, message }) {
|
|
5
|
+
const getIcon = () => {
|
|
6
|
+
switch (status) {
|
|
7
|
+
case 'pending':
|
|
8
|
+
return React.createElement(Text, { dimColor: true }, "\u25CB");
|
|
9
|
+
case 'running':
|
|
10
|
+
return (React.createElement(Text, { color: "cyan" },
|
|
11
|
+
React.createElement(Spinner, { type: "dots" })));
|
|
12
|
+
case 'success':
|
|
13
|
+
return React.createElement(Text, { color: "green" }, "\u2713");
|
|
14
|
+
case 'error':
|
|
15
|
+
return React.createElement(Text, { color: "red" }, "\u2717");
|
|
16
|
+
}
|
|
17
|
+
};
|
|
18
|
+
const getColor = () => {
|
|
19
|
+
switch (status) {
|
|
20
|
+
case 'pending':
|
|
21
|
+
return 'gray';
|
|
22
|
+
case 'running':
|
|
23
|
+
return 'cyan';
|
|
24
|
+
case 'success':
|
|
25
|
+
return 'green';
|
|
26
|
+
case 'error':
|
|
27
|
+
return 'red';
|
|
28
|
+
}
|
|
29
|
+
};
|
|
30
|
+
return (React.createElement(Box, null,
|
|
31
|
+
getIcon(),
|
|
32
|
+
React.createElement(Box, { marginLeft: 1 },
|
|
33
|
+
React.createElement(Text, { color: getColor(), bold: true }, label)),
|
|
34
|
+
message && (React.createElement(Box, { marginLeft: 1 },
|
|
35
|
+
React.createElement(Text, { dimColor: true }, message)))));
|
|
36
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
interface Props {
|
|
3
|
+
label: string;
|
|
4
|
+
defaultValue?: string;
|
|
5
|
+
placeholder?: string;
|
|
6
|
+
onSubmit: (value: string) => void;
|
|
7
|
+
onCancel?: () => void;
|
|
8
|
+
type?: 'text' | 'password';
|
|
9
|
+
}
|
|
10
|
+
export declare function TextInput({ label, defaultValue, placeholder, onSubmit, onCancel, type, }: Props): React.JSX.Element;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import React, { useState } from 'react';
|
|
2
|
+
import { Box, Text, useInput } from 'ink';
|
|
3
|
+
export function TextInput({ label, defaultValue = '', placeholder, onSubmit, onCancel, type = 'text', }) {
|
|
4
|
+
const [value, setValue] = useState(defaultValue);
|
|
5
|
+
useInput((input, key) => {
|
|
6
|
+
if (key.return) {
|
|
7
|
+
if (value === '' && defaultValue) {
|
|
8
|
+
onSubmit(defaultValue);
|
|
9
|
+
}
|
|
10
|
+
else {
|
|
11
|
+
onSubmit(value);
|
|
12
|
+
}
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
if (key.escape && onCancel) {
|
|
16
|
+
onCancel();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (key.delete || key.backspace) {
|
|
20
|
+
setValue((prev) => prev.slice(0, -1));
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
if (!key.ctrl && !key.meta) {
|
|
24
|
+
setValue((prev) => prev + input);
|
|
25
|
+
}
|
|
26
|
+
});
|
|
27
|
+
return (React.createElement(Box, { flexDirection: "column", padding: 1 },
|
|
28
|
+
React.createElement(Box, { marginBottom: 1 },
|
|
29
|
+
React.createElement(Text, { bold: true, color: "cyan" }, label)),
|
|
30
|
+
React.createElement(Box, { borderStyle: "round", borderColor: "cyan", paddingX: 1 },
|
|
31
|
+
React.createElement(Text, null, type === 'password' ? '*'.repeat(value.length) : value),
|
|
32
|
+
value === '' && placeholder && (React.createElement(Text, { dimColor: true }, placeholder))),
|
|
33
|
+
React.createElement(Box, { marginTop: 1 },
|
|
34
|
+
React.createElement(Text, { dimColor: true },
|
|
35
|
+
"Press Enter to submit",
|
|
36
|
+
onCancel ? ', Esc to cancel' : ''))));
|
|
37
|
+
}
|
|
@@ -0,0 +1,250 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sitevision CLI - Shared Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* This file contains all shared types used across the CLI.
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* App types supported by Sitevision
|
|
8
|
+
*/
|
|
9
|
+
export type AppType = 'WebApp' | 'Widget' | 'RESTApp';
|
|
10
|
+
/**
|
|
11
|
+
* Simplified app type for internal use
|
|
12
|
+
*/
|
|
13
|
+
export type SimpleAppType = 'web' | 'widget' | 'rest';
|
|
14
|
+
/**
|
|
15
|
+
* Sitevision app manifest (manifest.json)
|
|
16
|
+
*/
|
|
17
|
+
export interface SitevisionManifest {
|
|
18
|
+
id: string;
|
|
19
|
+
name: string;
|
|
20
|
+
version: string;
|
|
21
|
+
type: AppType;
|
|
22
|
+
bundled?: boolean;
|
|
23
|
+
description?: string;
|
|
24
|
+
author?: string;
|
|
25
|
+
helpUrl?: string;
|
|
26
|
+
license?: string;
|
|
27
|
+
categories?: string[];
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Development properties stored in .dev_properties.json
|
|
31
|
+
*/
|
|
32
|
+
export interface DevProperties {
|
|
33
|
+
domain: string;
|
|
34
|
+
siteName: string;
|
|
35
|
+
addonName: string;
|
|
36
|
+
username: string;
|
|
37
|
+
password: string;
|
|
38
|
+
useHTTPForDevDeploy?: boolean;
|
|
39
|
+
signingUsername?: string;
|
|
40
|
+
certificateName?: string;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Signing credentials (password is runtime-only, not persisted)
|
|
44
|
+
*/
|
|
45
|
+
export interface SigningCredentials {
|
|
46
|
+
username: string;
|
|
47
|
+
password: string;
|
|
48
|
+
certificateName?: string;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Deployment configuration
|
|
52
|
+
*/
|
|
53
|
+
export interface DeployConfig {
|
|
54
|
+
domain: string;
|
|
55
|
+
siteName: string;
|
|
56
|
+
addonName: string;
|
|
57
|
+
username: string;
|
|
58
|
+
password: string;
|
|
59
|
+
useHTTP?: boolean;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Production deployment configuration
|
|
63
|
+
*/
|
|
64
|
+
export interface ProductionDeployConfig extends DeployConfig {
|
|
65
|
+
activate?: boolean;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Package.json sitevision_scripts_properties section
|
|
69
|
+
*/
|
|
70
|
+
export interface SitevisionScriptsProperties {
|
|
71
|
+
transpile?: boolean;
|
|
72
|
+
transpilePackages?: string[];
|
|
73
|
+
babel?: Record<string, unknown>;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Full project information detected from the filesystem
|
|
77
|
+
*/
|
|
78
|
+
export interface ProjectInfo {
|
|
79
|
+
root: string;
|
|
80
|
+
manifest: SitevisionManifest;
|
|
81
|
+
hasDevProperties: boolean;
|
|
82
|
+
hasSigningProperties: boolean;
|
|
83
|
+
devProperties?: DevProperties;
|
|
84
|
+
packageJson: PackageJson;
|
|
85
|
+
hasSitevisionScripts: boolean;
|
|
86
|
+
hasNodeModules: boolean;
|
|
87
|
+
paths: ProjectPaths;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Standard project paths
|
|
91
|
+
*/
|
|
92
|
+
export interface ProjectPaths {
|
|
93
|
+
root: string;
|
|
94
|
+
src: string;
|
|
95
|
+
static: string;
|
|
96
|
+
build: string;
|
|
97
|
+
dist: string;
|
|
98
|
+
manifest: string;
|
|
99
|
+
devProperties: string | null;
|
|
100
|
+
packageJson: string;
|
|
101
|
+
nodeModules: string;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Partial package.json with fields we care about
|
|
105
|
+
*/
|
|
106
|
+
export interface PackageJson {
|
|
107
|
+
name?: string;
|
|
108
|
+
version?: string;
|
|
109
|
+
scripts?: Record<string, string>;
|
|
110
|
+
dependencies?: Record<string, string>;
|
|
111
|
+
devDependencies?: Record<string, string>;
|
|
112
|
+
sitevision_scripts_properties?: SitevisionScriptsProperties;
|
|
113
|
+
developmentDomain?: string;
|
|
114
|
+
productionDomain?: string;
|
|
115
|
+
addonName?: string;
|
|
116
|
+
siteName?: string;
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* REST API endpoints by app type
|
|
120
|
+
*/
|
|
121
|
+
export interface ApiEndpoints {
|
|
122
|
+
addon: string;
|
|
123
|
+
import: string;
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* API response from app signing
|
|
127
|
+
*/
|
|
128
|
+
export interface SigningResponse {
|
|
129
|
+
success: boolean;
|
|
130
|
+
signedFilePath?: string;
|
|
131
|
+
error?: string;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* API response from deployment
|
|
135
|
+
*/
|
|
136
|
+
export interface DeployResponse {
|
|
137
|
+
success: boolean;
|
|
138
|
+
executableId?: string;
|
|
139
|
+
message?: string;
|
|
140
|
+
error?: string;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* API response from addon creation
|
|
144
|
+
*/
|
|
145
|
+
export interface CreateAddonResponse {
|
|
146
|
+
success: boolean;
|
|
147
|
+
addonId?: string;
|
|
148
|
+
error?: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* API response from activation
|
|
152
|
+
*/
|
|
153
|
+
export interface ActivationResponse {
|
|
154
|
+
success: boolean;
|
|
155
|
+
error?: string;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Build mode
|
|
159
|
+
*/
|
|
160
|
+
export type BuildMode = 'development' | 'production';
|
|
161
|
+
/**
|
|
162
|
+
* Build options for webpack
|
|
163
|
+
*/
|
|
164
|
+
export interface BuildOptions {
|
|
165
|
+
mode: BuildMode;
|
|
166
|
+
watch?: boolean;
|
|
167
|
+
cssPrefix?: string;
|
|
168
|
+
restApp?: boolean;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Build result
|
|
172
|
+
*/
|
|
173
|
+
export interface BuildResult {
|
|
174
|
+
success: boolean;
|
|
175
|
+
outputPath?: string;
|
|
176
|
+
errors?: string[];
|
|
177
|
+
warnings?: string[];
|
|
178
|
+
stats?: {
|
|
179
|
+
time: number;
|
|
180
|
+
hash: string;
|
|
181
|
+
assets: string[];
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Watch callback for webpack watch mode
|
|
186
|
+
*/
|
|
187
|
+
export type WatchCallback = (result: BuildResult) => void;
|
|
188
|
+
/**
|
|
189
|
+
* Command execution context
|
|
190
|
+
*/
|
|
191
|
+
export interface CommandContext {
|
|
192
|
+
project: ProjectInfo;
|
|
193
|
+
flags: Record<string, unknown>;
|
|
194
|
+
args: string[];
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Command definition
|
|
198
|
+
*/
|
|
199
|
+
export interface Command {
|
|
200
|
+
name: string;
|
|
201
|
+
description: string;
|
|
202
|
+
requiresProject: boolean;
|
|
203
|
+
flags?: Record<string, CommandFlag>;
|
|
204
|
+
execute: (context: CommandContext) => Promise<void>;
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Command flag definition
|
|
208
|
+
*/
|
|
209
|
+
export interface CommandFlag {
|
|
210
|
+
type: 'string' | 'boolean';
|
|
211
|
+
description: string;
|
|
212
|
+
alias?: string;
|
|
213
|
+
default?: unknown;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Process output types
|
|
217
|
+
*/
|
|
218
|
+
export interface ProcessOutput {
|
|
219
|
+
type: 'stdout' | 'stderr';
|
|
220
|
+
data: string;
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Process execution result
|
|
224
|
+
*/
|
|
225
|
+
export interface ProcessResult {
|
|
226
|
+
exitCode: number;
|
|
227
|
+
output: ProcessOutput[];
|
|
228
|
+
}
|
|
229
|
+
/**
|
|
230
|
+
* HTTP request options
|
|
231
|
+
*/
|
|
232
|
+
export interface HttpRequestOptions {
|
|
233
|
+
method: 'GET' | 'POST' | 'PUT' | 'DELETE';
|
|
234
|
+
headers?: Record<string, string>;
|
|
235
|
+
body?: unknown;
|
|
236
|
+
auth?: {
|
|
237
|
+
username: string;
|
|
238
|
+
password: string;
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Generic result type for operations that can fail
|
|
243
|
+
*/
|
|
244
|
+
export type Result<T, E = Error> = {
|
|
245
|
+
success: true;
|
|
246
|
+
data: T;
|
|
247
|
+
} | {
|
|
248
|
+
success: false;
|
|
249
|
+
error: E;
|
|
250
|
+
};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt for password input with masked display
|
|
3
|
+
*/
|
|
4
|
+
export function promptPassword(prompt) {
|
|
5
|
+
return new Promise((resolve) => {
|
|
6
|
+
process.stdout.write(prompt);
|
|
7
|
+
const stdin = process.stdin;
|
|
8
|
+
stdin.setRawMode(true);
|
|
9
|
+
stdin.resume();
|
|
10
|
+
stdin.setEncoding('utf8');
|
|
11
|
+
let password = '';
|
|
12
|
+
const onData = (data) => {
|
|
13
|
+
// Handle each character in the input (supports paste)
|
|
14
|
+
for (const char of data) {
|
|
15
|
+
const charCode = char.charCodeAt(0);
|
|
16
|
+
if (charCode === 13 || charCode === 10) {
|
|
17
|
+
// Enter key
|
|
18
|
+
stdin.setRawMode(false);
|
|
19
|
+
stdin.removeListener('data', onData);
|
|
20
|
+
stdin.pause();
|
|
21
|
+
process.stdout.write('\n');
|
|
22
|
+
resolve(password);
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
else if (charCode === 127 || charCode === 8) {
|
|
26
|
+
// Backspace
|
|
27
|
+
if (password.length > 0) {
|
|
28
|
+
password = password.slice(0, -1);
|
|
29
|
+
process.stdout.write('\b \b');
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
else if (charCode === 3) {
|
|
33
|
+
// Ctrl+C
|
|
34
|
+
process.exit();
|
|
35
|
+
}
|
|
36
|
+
else if (charCode >= 32) {
|
|
37
|
+
// Printable characters
|
|
38
|
+
password += char;
|
|
39
|
+
process.stdout.write('*');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
stdin.on('data', onData);
|
|
44
|
+
});
|
|
45
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { EventEmitter } from 'events';
|
|
2
|
+
export interface ProcessOutput {
|
|
3
|
+
type: 'stdout' | 'stderr';
|
|
4
|
+
data: string;
|
|
5
|
+
}
|
|
6
|
+
export interface ProcessResult {
|
|
7
|
+
exitCode: number;
|
|
8
|
+
output: ProcessOutput[];
|
|
9
|
+
}
|
|
10
|
+
export declare class ProcessRunner extends EventEmitter {
|
|
11
|
+
private command;
|
|
12
|
+
private args;
|
|
13
|
+
private cwd?;
|
|
14
|
+
private interactive;
|
|
15
|
+
private customEnv?;
|
|
16
|
+
private process;
|
|
17
|
+
private output;
|
|
18
|
+
constructor(command: string, args?: string[], cwd?: string | undefined, interactive?: boolean, customEnv?: Record<string, string> | undefined);
|
|
19
|
+
run(): Promise<ProcessResult>;
|
|
20
|
+
kill(): void;
|
|
21
|
+
getOutput(): ProcessOutput[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Run a sitevision-scripts command in the project directory
|
|
25
|
+
*/
|
|
26
|
+
export declare function runSitevisionScript(scriptName: string, args?: string[], projectRoot?: string): ProcessRunner;
|
|
27
|
+
/**
|
|
28
|
+
* Run an NPM script
|
|
29
|
+
*/
|
|
30
|
+
export declare function runNpmScript(scriptName: string, args?: string[], projectRoot?: string, customEnv?: Record<string, string>): ProcessRunner;
|
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { spawn } from 'child_process';
|
|
2
|
+
import { EventEmitter } from 'events';
|
|
3
|
+
export class ProcessRunner extends EventEmitter {
|
|
4
|
+
constructor(command, args = [], cwd, interactive = false, customEnv) {
|
|
5
|
+
super();
|
|
6
|
+
Object.defineProperty(this, "command", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: command
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "args", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: args
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(this, "cwd", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: cwd
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "interactive", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: interactive
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "customEnv", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: customEnv
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "process", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: null
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "output", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: []
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
run() {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
this.process = spawn(this.command, this.args, {
|
|
52
|
+
cwd: this.cwd || process.cwd(),
|
|
53
|
+
env: { ...process.env, ...this.customEnv },
|
|
54
|
+
shell: true,
|
|
55
|
+
stdio: this.interactive ? 'inherit' : 'pipe',
|
|
56
|
+
});
|
|
57
|
+
// Only capture output if not in interactive mode
|
|
58
|
+
if (!this.interactive) {
|
|
59
|
+
this.process.stdout?.on('data', data => {
|
|
60
|
+
const output = {
|
|
61
|
+
type: 'stdout',
|
|
62
|
+
data: data.toString(),
|
|
63
|
+
};
|
|
64
|
+
this.output.push(output);
|
|
65
|
+
if (this.output.length > 1000) {
|
|
66
|
+
this.output.shift();
|
|
67
|
+
}
|
|
68
|
+
this.emit('output', output);
|
|
69
|
+
});
|
|
70
|
+
this.process.stderr?.on('data', data => {
|
|
71
|
+
const output = {
|
|
72
|
+
type: 'stderr',
|
|
73
|
+
data: data.toString(),
|
|
74
|
+
};
|
|
75
|
+
this.output.push(output);
|
|
76
|
+
if (this.output.length > 1000) {
|
|
77
|
+
this.output.shift();
|
|
78
|
+
}
|
|
79
|
+
this.emit('output', output);
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
this.process.on('error', error => {
|
|
83
|
+
this.emit('error', error);
|
|
84
|
+
reject(error);
|
|
85
|
+
});
|
|
86
|
+
this.process.on('close', code => {
|
|
87
|
+
const exitCode = code ?? 0;
|
|
88
|
+
this.emit('exit', exitCode);
|
|
89
|
+
resolve({
|
|
90
|
+
exitCode,
|
|
91
|
+
output: this.output,
|
|
92
|
+
});
|
|
93
|
+
});
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
kill() {
|
|
97
|
+
if (this.process) {
|
|
98
|
+
this.process.kill('SIGTERM');
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
getOutput() {
|
|
102
|
+
return this.output;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Run a sitevision-scripts command in the project directory
|
|
107
|
+
*/
|
|
108
|
+
export function runSitevisionScript(scriptName, args = [], projectRoot) {
|
|
109
|
+
// Check if sitevision-scripts is available locally
|
|
110
|
+
const runner = new ProcessRunner('npm', ['run', scriptName, '--', ...args], projectRoot);
|
|
111
|
+
return runner;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Run an NPM script
|
|
115
|
+
*/
|
|
116
|
+
export function runNpmScript(scriptName, args = [], projectRoot, customEnv) {
|
|
117
|
+
const runner = new ProcessRunner('npm', ['run', scriptName, ...args], projectRoot, false, customEnv);
|
|
118
|
+
return runner;
|
|
119
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
import type { SitevisionManifest, DevProperties, ProjectPaths, SimpleAppType, PackageJson, ApiEndpoints } from '../types/index.js';
|
|
2
|
+
export type { SitevisionManifest, DevProperties } from '../types/index.js';
|
|
3
|
+
/**
|
|
4
|
+
* Project information with paths
|
|
5
|
+
*/
|
|
6
|
+
export interface ProjectInfo {
|
|
7
|
+
root: string;
|
|
8
|
+
manifest: SitevisionManifest;
|
|
9
|
+
hasDevProperties: boolean;
|
|
10
|
+
hasSigningProperties: boolean;
|
|
11
|
+
devProperties?: DevProperties;
|
|
12
|
+
packageJson: PackageJson;
|
|
13
|
+
hasSitevisionScripts: boolean;
|
|
14
|
+
hasNodeModules: boolean;
|
|
15
|
+
paths: ProjectPaths;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Get standard project paths for a given root directory
|
|
19
|
+
*/
|
|
20
|
+
export declare function getProjectPaths(root: string, manifestPath: string, devPropertiesPath: string | null): ProjectPaths;
|
|
21
|
+
/**
|
|
22
|
+
* Find the dev properties file path (supports both naming conventions)
|
|
23
|
+
*/
|
|
24
|
+
export declare function findDevPropertiesPath(root: string): string | null;
|
|
25
|
+
/**
|
|
26
|
+
* Get the default dev properties path (for creating new files)
|
|
27
|
+
*/
|
|
28
|
+
export declare function getDefaultDevPropertiesPath(root: string): string;
|
|
29
|
+
/**
|
|
30
|
+
* Get the full app ID including any prefix/suffix from environment
|
|
31
|
+
*
|
|
32
|
+
* This combines: prefix + baseId + suffix
|
|
33
|
+
* Used for generating zip filenames and deployment identifiers
|
|
34
|
+
*/
|
|
35
|
+
export declare function getFullAppId(baseId: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Get the zip filename for an app
|
|
38
|
+
*/
|
|
39
|
+
export declare function getZipFilename(manifest: SitevisionManifest): string;
|
|
40
|
+
/**
|
|
41
|
+
* Get the signed zip filename for an app
|
|
42
|
+
*/
|
|
43
|
+
export declare function getSignedZipFilename(manifest: SitevisionManifest): string;
|
|
44
|
+
/**
|
|
45
|
+
* Get the full path to the zip file in dist/
|
|
46
|
+
*/
|
|
47
|
+
export declare function getZipPath(projectRoot: string, manifest: SitevisionManifest): string;
|
|
48
|
+
/**
|
|
49
|
+
* Get the full path to the signed zip file in dist/
|
|
50
|
+
*/
|
|
51
|
+
export declare function getSignedZipPath(projectRoot: string, manifest: SitevisionManifest): string;
|
|
52
|
+
/**
|
|
53
|
+
* Get API endpoints for the given app type
|
|
54
|
+
*/
|
|
55
|
+
export declare function getApiEndpoints(appType: SimpleAppType): ApiEndpoints;
|
|
56
|
+
/**
|
|
57
|
+
* Build the base URL for API requests
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildApiBaseUrl(domain: string, siteName: string, useHTTP?: boolean): string;
|
|
60
|
+
/**
|
|
61
|
+
* Build the addon endpoint URL
|
|
62
|
+
*/
|
|
63
|
+
export declare function buildAddonEndpointUrl(domain: string, siteName: string, appType: SimpleAppType, useHTTP?: boolean): string;
|
|
64
|
+
/**
|
|
65
|
+
* Build the import endpoint URL
|
|
66
|
+
*/
|
|
67
|
+
export declare function buildImportEndpointUrl(domain: string, siteName: string, addonName: string, appType: SimpleAppType, useHTTP?: boolean): string;
|
|
68
|
+
/**
|
|
69
|
+
* Detect if the current directory is a Sitevision project
|
|
70
|
+
*/
|
|
71
|
+
export declare function detectProject(cwd?: string): ProjectInfo | null;
|
|
72
|
+
/**
|
|
73
|
+
* Validate that we're in a Sitevision project directory
|
|
74
|
+
*/
|
|
75
|
+
export declare function requireProject(cwd?: string): ProjectInfo;
|
|
76
|
+
/**
|
|
77
|
+
* Get the app type (web, widget, rest)
|
|
78
|
+
*/
|
|
79
|
+
export declare function getAppType(manifest: SitevisionManifest): SimpleAppType;
|
|
80
|
+
/**
|
|
81
|
+
* Check if the app uses webpack bundling
|
|
82
|
+
*/
|
|
83
|
+
export declare function isBundledApp(manifest: SitevisionManifest): boolean;
|
|
84
|
+
/**
|
|
85
|
+
* Read and parse the dev properties file
|
|
86
|
+
*/
|
|
87
|
+
export declare function readDevProperties(projectRoot: string): DevProperties | null;
|
|
88
|
+
/**
|
|
89
|
+
* Write dev properties to file
|
|
90
|
+
*/
|
|
91
|
+
export declare function writeDevProperties(projectRoot: string, properties: DevProperties): void;
|
|
92
|
+
/**
|
|
93
|
+
* Ensure the dist directory exists
|
|
94
|
+
*/
|
|
95
|
+
export declare function ensureDistDir(projectRoot: string): string;
|
|
96
|
+
/**
|
|
97
|
+
* Ensure the build directory exists
|
|
98
|
+
*/
|
|
99
|
+
export declare function ensureBuildDir(projectRoot: string): string;
|
|
100
|
+
/**
|
|
101
|
+
* Clean the build directory
|
|
102
|
+
*/
|
|
103
|
+
export declare function cleanBuildDir(projectRoot: string): void;
|