pulse-js-framework 1.0.0 → 1.4.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/README.md +414 -182
- package/cli/analyze.js +499 -0
- package/cli/build.js +341 -199
- package/cli/format.js +704 -0
- package/cli/index.js +398 -324
- package/cli/lint.js +642 -0
- package/cli/mobile.js +1473 -0
- package/cli/utils/file-utils.js +298 -0
- package/compiler/lexer.js +766 -581
- package/compiler/parser.js +1797 -900
- package/compiler/transformer.js +1332 -552
- package/index.js +1 -1
- package/mobile/bridge/pulse-native.js +420 -0
- package/package.json +68 -58
- package/runtime/dom.js +363 -33
- package/runtime/index.js +2 -0
- package/runtime/native.js +368 -0
- package/runtime/pulse.js +247 -13
- package/runtime/router.js +596 -392
package/cli/build.js
CHANGED
|
@@ -1,199 +1,341 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Pulse Build System
|
|
3
|
-
*
|
|
4
|
-
* Builds Pulse projects for production
|
|
5
|
-
*/
|
|
6
|
-
|
|
7
|
-
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
|
|
8
|
-
import { join, extname, relative, dirname } from 'path';
|
|
9
|
-
import { compile } from '../compiler/index.js';
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Build project for production
|
|
13
|
-
*/
|
|
14
|
-
export async function buildProject(args) {
|
|
15
|
-
const root = process.cwd();
|
|
16
|
-
const outDir = join(root, 'dist');
|
|
17
|
-
|
|
18
|
-
// Check if vite is available
|
|
19
|
-
try {
|
|
20
|
-
const viteConfig = join(root, 'vite.config.js');
|
|
21
|
-
if (existsSync(viteConfig)) {
|
|
22
|
-
console.log('Vite config detected, using Vite build...');
|
|
23
|
-
const { build } = await import('vite');
|
|
24
|
-
await build({ root });
|
|
25
|
-
return;
|
|
26
|
-
}
|
|
27
|
-
} catch (e) {
|
|
28
|
-
// Vite not available, use built-in build
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
console.log('Building with Pulse compiler...');
|
|
32
|
-
|
|
33
|
-
// Create output directory
|
|
34
|
-
if (!existsSync(outDir)) {
|
|
35
|
-
mkdirSync(outDir, { recursive: true });
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Copy public files
|
|
39
|
-
const publicDir = join(root, 'public');
|
|
40
|
-
if (existsSync(publicDir)) {
|
|
41
|
-
copyDir(publicDir, outDir);
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
// Process source files
|
|
45
|
-
const srcDir = join(root, 'src');
|
|
46
|
-
if (existsSync(srcDir)) {
|
|
47
|
-
processDirectory(srcDir, join(outDir, 'assets'));
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
// Copy and process index.html
|
|
51
|
-
const indexHtml = join(root, 'index.html');
|
|
52
|
-
if (existsSync(indexHtml)) {
|
|
53
|
-
let html = readFileSync(indexHtml, 'utf-8');
|
|
54
|
-
|
|
55
|
-
// Update script paths for production
|
|
56
|
-
html = html.replace(
|
|
57
|
-
/src="\/src\/([^"]+)"/g,
|
|
58
|
-
'src="/assets/$1"'
|
|
59
|
-
);
|
|
60
|
-
|
|
61
|
-
// Rewrite .pulse imports to .js
|
|
62
|
-
html = html.replace(/\.pulse"/g, '.js"');
|
|
63
|
-
|
|
64
|
-
writeFileSync(join(outDir, 'index.html'), html);
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Bundle runtime
|
|
68
|
-
bundleRuntime(outDir);
|
|
69
|
-
|
|
70
|
-
console.log(`
|
|
71
|
-
Build complete!
|
|
72
|
-
|
|
73
|
-
Output directory: ${relative(root, outDir)}
|
|
74
|
-
|
|
75
|
-
To preview the build:
|
|
76
|
-
npx serve dist
|
|
77
|
-
`);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Process a directory of source files
|
|
82
|
-
*/
|
|
83
|
-
function processDirectory(srcDir, outDir) {
|
|
84
|
-
if (!existsSync(outDir)) {
|
|
85
|
-
mkdirSync(outDir, { recursive: true });
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
const files = readdirSync(srcDir);
|
|
89
|
-
|
|
90
|
-
for (const file of files) {
|
|
91
|
-
const srcPath = join(srcDir, file);
|
|
92
|
-
const stat = statSync(srcPath);
|
|
93
|
-
|
|
94
|
-
if (stat.isDirectory()) {
|
|
95
|
-
processDirectory(srcPath, join(outDir, file));
|
|
96
|
-
} else if (file.endsWith('.pulse')) {
|
|
97
|
-
// Compile .pulse files
|
|
98
|
-
const source = readFileSync(srcPath, 'utf-8');
|
|
99
|
-
const result = compile(source, {
|
|
100
|
-
runtime: './runtime.js',
|
|
101
|
-
minify: true
|
|
102
|
-
});
|
|
103
|
-
|
|
104
|
-
if (result.success) {
|
|
105
|
-
const outPath = join(outDir, file.replace('.pulse', '.js'));
|
|
106
|
-
writeFileSync(outPath, result.code);
|
|
107
|
-
console.log(` Compiled: ${file}`);
|
|
108
|
-
} else {
|
|
109
|
-
console.error(` Error compiling ${file}:`);
|
|
110
|
-
for (const error of result.errors) {
|
|
111
|
-
console.error(` ${error.message}`);
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
} else if (file.endsWith('.js') || file.endsWith('.mjs')) {
|
|
115
|
-
// Process JS files - rewrite imports
|
|
116
|
-
let content = readFileSync(srcPath, 'utf-8');
|
|
117
|
-
|
|
118
|
-
// Rewrite .pulse imports to .js
|
|
119
|
-
content = content.replace(/from\s+['"]([^'"]+)\.pulse['"]/g, "from '$1.js'");
|
|
120
|
-
|
|
121
|
-
// Rewrite runtime imports
|
|
122
|
-
content = content.replace(
|
|
123
|
-
/from\s+['"]pulse-framework\/runtime['"]/g,
|
|
124
|
-
"from './runtime.js'"
|
|
125
|
-
);
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
//
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
${readRuntimeFile('
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
1
|
+
/**
|
|
2
|
+
* Pulse Build System
|
|
3
|
+
*
|
|
4
|
+
* Builds Pulse projects for production
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { readFileSync, writeFileSync, existsSync, mkdirSync, readdirSync, statSync, copyFileSync } from 'fs';
|
|
8
|
+
import { join, extname, relative, dirname } from 'path';
|
|
9
|
+
import { compile } from '../compiler/index.js';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Build project for production
|
|
13
|
+
*/
|
|
14
|
+
export async function buildProject(args) {
|
|
15
|
+
const root = process.cwd();
|
|
16
|
+
const outDir = join(root, 'dist');
|
|
17
|
+
|
|
18
|
+
// Check if vite is available
|
|
19
|
+
try {
|
|
20
|
+
const viteConfig = join(root, 'vite.config.js');
|
|
21
|
+
if (existsSync(viteConfig)) {
|
|
22
|
+
console.log('Vite config detected, using Vite build...');
|
|
23
|
+
const { build } = await import('vite');
|
|
24
|
+
await build({ root });
|
|
25
|
+
return;
|
|
26
|
+
}
|
|
27
|
+
} catch (e) {
|
|
28
|
+
// Vite not available, use built-in build
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
console.log('Building with Pulse compiler...');
|
|
32
|
+
|
|
33
|
+
// Create output directory
|
|
34
|
+
if (!existsSync(outDir)) {
|
|
35
|
+
mkdirSync(outDir, { recursive: true });
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Copy public files
|
|
39
|
+
const publicDir = join(root, 'public');
|
|
40
|
+
if (existsSync(publicDir)) {
|
|
41
|
+
copyDir(publicDir, outDir);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// Process source files
|
|
45
|
+
const srcDir = join(root, 'src');
|
|
46
|
+
if (existsSync(srcDir)) {
|
|
47
|
+
processDirectory(srcDir, join(outDir, 'assets'));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// Copy and process index.html
|
|
51
|
+
const indexHtml = join(root, 'index.html');
|
|
52
|
+
if (existsSync(indexHtml)) {
|
|
53
|
+
let html = readFileSync(indexHtml, 'utf-8');
|
|
54
|
+
|
|
55
|
+
// Update script paths for production
|
|
56
|
+
html = html.replace(
|
|
57
|
+
/src="\/src\/([^"]+)"/g,
|
|
58
|
+
'src="/assets/$1"'
|
|
59
|
+
);
|
|
60
|
+
|
|
61
|
+
// Rewrite .pulse imports to .js
|
|
62
|
+
html = html.replace(/\.pulse"/g, '.js"');
|
|
63
|
+
|
|
64
|
+
writeFileSync(join(outDir, 'index.html'), html);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Bundle runtime
|
|
68
|
+
bundleRuntime(outDir);
|
|
69
|
+
|
|
70
|
+
console.log(`
|
|
71
|
+
Build complete!
|
|
72
|
+
|
|
73
|
+
Output directory: ${relative(root, outDir)}
|
|
74
|
+
|
|
75
|
+
To preview the build:
|
|
76
|
+
npx serve dist
|
|
77
|
+
`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Process a directory of source files
|
|
82
|
+
*/
|
|
83
|
+
function processDirectory(srcDir, outDir) {
|
|
84
|
+
if (!existsSync(outDir)) {
|
|
85
|
+
mkdirSync(outDir, { recursive: true });
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
const files = readdirSync(srcDir);
|
|
89
|
+
|
|
90
|
+
for (const file of files) {
|
|
91
|
+
const srcPath = join(srcDir, file);
|
|
92
|
+
const stat = statSync(srcPath);
|
|
93
|
+
|
|
94
|
+
if (stat.isDirectory()) {
|
|
95
|
+
processDirectory(srcPath, join(outDir, file));
|
|
96
|
+
} else if (file.endsWith('.pulse')) {
|
|
97
|
+
// Compile .pulse files
|
|
98
|
+
const source = readFileSync(srcPath, 'utf-8');
|
|
99
|
+
const result = compile(source, {
|
|
100
|
+
runtime: './runtime.js',
|
|
101
|
+
minify: true
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
if (result.success) {
|
|
105
|
+
const outPath = join(outDir, file.replace('.pulse', '.js'));
|
|
106
|
+
writeFileSync(outPath, result.code);
|
|
107
|
+
console.log(` Compiled: ${file}`);
|
|
108
|
+
} else {
|
|
109
|
+
console.error(` Error compiling ${file}:`);
|
|
110
|
+
for (const error of result.errors) {
|
|
111
|
+
console.error(` ${error.message}`);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
} else if (file.endsWith('.js') || file.endsWith('.mjs')) {
|
|
115
|
+
// Process JS files - rewrite imports
|
|
116
|
+
let content = readFileSync(srcPath, 'utf-8');
|
|
117
|
+
|
|
118
|
+
// Rewrite .pulse imports to .js
|
|
119
|
+
content = content.replace(/from\s+['"]([^'"]+)\.pulse['"]/g, "from '$1.js'");
|
|
120
|
+
|
|
121
|
+
// Rewrite runtime imports
|
|
122
|
+
content = content.replace(
|
|
123
|
+
/from\s+['"]pulse-framework\/runtime['"]/g,
|
|
124
|
+
"from './runtime.js'"
|
|
125
|
+
);
|
|
126
|
+
|
|
127
|
+
// Minify
|
|
128
|
+
content = minifyJS(content);
|
|
129
|
+
|
|
130
|
+
const outPath = join(outDir, file);
|
|
131
|
+
writeFileSync(outPath, content);
|
|
132
|
+
console.log(` Processed & minified: ${file}`);
|
|
133
|
+
} else {
|
|
134
|
+
// Copy other files
|
|
135
|
+
const outPath = join(outDir, file);
|
|
136
|
+
copyFileSync(srcPath, outPath);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Bundle the runtime into a single file
|
|
143
|
+
*/
|
|
144
|
+
function bundleRuntime(outDir, shouldMinify = true) {
|
|
145
|
+
// For simplicity, we'll create a minimal runtime bundle
|
|
146
|
+
// In production, you'd want to use a proper bundler
|
|
147
|
+
|
|
148
|
+
let runtimeCode = `
|
|
149
|
+
// Pulse Runtime (bundled)
|
|
150
|
+
${readRuntimeFile('pulse.js')}
|
|
151
|
+
${readRuntimeFile('dom.js')}
|
|
152
|
+
${readRuntimeFile('router.js')}
|
|
153
|
+
${readRuntimeFile('store.js')}
|
|
154
|
+
`;
|
|
155
|
+
|
|
156
|
+
if (shouldMinify) {
|
|
157
|
+
runtimeCode = minifyJS(runtimeCode);
|
|
158
|
+
console.log(' Bundled & minified: runtime.js');
|
|
159
|
+
} else {
|
|
160
|
+
console.log(' Bundled: runtime.js');
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
writeFileSync(join(outDir, 'assets', 'runtime.js'), runtimeCode);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Read a runtime file
|
|
168
|
+
*/
|
|
169
|
+
function readRuntimeFile(filename) {
|
|
170
|
+
const paths = [
|
|
171
|
+
join(process.cwd(), 'node_modules', 'pulse-framework', 'runtime', filename),
|
|
172
|
+
join(dirname(new URL(import.meta.url).pathname), '..', 'runtime', filename)
|
|
173
|
+
];
|
|
174
|
+
|
|
175
|
+
for (const path of paths) {
|
|
176
|
+
if (existsSync(path)) {
|
|
177
|
+
return readFileSync(path, 'utf-8');
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
console.warn(` Warning: Could not find runtime file: ${filename}`);
|
|
182
|
+
return '';
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Minify JavaScript code (simple minification)
|
|
187
|
+
* String-aware: preserves content inside string literals
|
|
188
|
+
*/
|
|
189
|
+
export function minifyJS(code) {
|
|
190
|
+
// Extract strings to protect them from minification
|
|
191
|
+
const strings = [];
|
|
192
|
+
const placeholder = '\x00STR';
|
|
193
|
+
|
|
194
|
+
// Replace strings with placeholders (handles ", ', and ` with escape sequences)
|
|
195
|
+
const withPlaceholders = code.replace(
|
|
196
|
+
/(["'`])(?:\\.|(?!\1)[^\\])*\1/g,
|
|
197
|
+
(match) => {
|
|
198
|
+
strings.push(match);
|
|
199
|
+
return placeholder + (strings.length - 1) + '\x00';
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// Apply minification to non-string parts
|
|
204
|
+
let minified = withPlaceholders
|
|
205
|
+
// Remove single-line comments
|
|
206
|
+
.replace(/\/\/.*$/gm, '')
|
|
207
|
+
// Remove multi-line comments
|
|
208
|
+
.replace(/\/\*[\s\S]*?\*\//g, '')
|
|
209
|
+
// Remove leading/trailing whitespace per line
|
|
210
|
+
.split('\n')
|
|
211
|
+
.map(line => line.trim())
|
|
212
|
+
.filter(line => line.length > 0)
|
|
213
|
+
.join('\n')
|
|
214
|
+
// Collapse multiple newlines
|
|
215
|
+
.replace(/\n{2,}/g, '\n')
|
|
216
|
+
// Remove spaces around operators (simple)
|
|
217
|
+
.replace(/\s*([{};,:])\s*/g, '$1')
|
|
218
|
+
.replace(/\s*=\s*/g, '=')
|
|
219
|
+
.replace(/\s*\(\s*/g, '(')
|
|
220
|
+
.replace(/\s*\)\s*/g, ')')
|
|
221
|
+
// Collapse remaining whitespace
|
|
222
|
+
.replace(/\s+/g, ' ')
|
|
223
|
+
.trim();
|
|
224
|
+
|
|
225
|
+
// Restore strings
|
|
226
|
+
minified = minified.replace(
|
|
227
|
+
new RegExp(placeholder.replace('\x00', '\\x00') + '(\\d+)\\x00', 'g'),
|
|
228
|
+
(_, index) => strings[parseInt(index)]
|
|
229
|
+
);
|
|
230
|
+
|
|
231
|
+
return minified;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Copy a directory recursively
|
|
236
|
+
*/
|
|
237
|
+
function copyDir(src, dest) {
|
|
238
|
+
if (!existsSync(dest)) {
|
|
239
|
+
mkdirSync(dest, { recursive: true });
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
const files = readdirSync(src);
|
|
243
|
+
|
|
244
|
+
for (const file of files) {
|
|
245
|
+
const srcPath = join(src, file);
|
|
246
|
+
const destPath = join(dest, file);
|
|
247
|
+
const stat = statSync(srcPath);
|
|
248
|
+
|
|
249
|
+
if (stat.isDirectory()) {
|
|
250
|
+
copyDir(srcPath, destPath);
|
|
251
|
+
} else {
|
|
252
|
+
copyFileSync(srcPath, destPath);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
/**
|
|
258
|
+
* Preview production build
|
|
259
|
+
*/
|
|
260
|
+
export async function previewBuild(args) {
|
|
261
|
+
const port = parseInt(args[0]) || 4173;
|
|
262
|
+
const root = process.cwd();
|
|
263
|
+
const distDir = join(root, 'dist');
|
|
264
|
+
|
|
265
|
+
if (!existsSync(distDir)) {
|
|
266
|
+
console.error('No dist folder found. Run "pulse build" first.');
|
|
267
|
+
process.exit(1);
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
// Check if vite is available for preview
|
|
271
|
+
try {
|
|
272
|
+
const viteConfig = join(root, 'vite.config.js');
|
|
273
|
+
if (existsSync(viteConfig)) {
|
|
274
|
+
console.log('Using Vite preview...');
|
|
275
|
+
const { preview } = await import('vite');
|
|
276
|
+
const server = await preview({
|
|
277
|
+
root,
|
|
278
|
+
preview: { port }
|
|
279
|
+
});
|
|
280
|
+
server.printUrls();
|
|
281
|
+
return;
|
|
282
|
+
}
|
|
283
|
+
} catch (e) {
|
|
284
|
+
// Vite not available, use built-in server
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
// Built-in static server for dist
|
|
288
|
+
const { createServer } = await import('http');
|
|
289
|
+
|
|
290
|
+
const MIME_TYPES = {
|
|
291
|
+
'.html': 'text/html',
|
|
292
|
+
'.js': 'application/javascript',
|
|
293
|
+
'.css': 'text/css',
|
|
294
|
+
'.json': 'application/json',
|
|
295
|
+
'.png': 'image/png',
|
|
296
|
+
'.jpg': 'image/jpeg',
|
|
297
|
+
'.gif': 'image/gif',
|
|
298
|
+
'.svg': 'image/svg+xml',
|
|
299
|
+
'.ico': 'image/x-icon',
|
|
300
|
+
'.woff': 'font/woff',
|
|
301
|
+
'.woff2': 'font/woff2'
|
|
302
|
+
};
|
|
303
|
+
|
|
304
|
+
const server = createServer((req, res) => {
|
|
305
|
+
let pathname = new URL(req.url, `http://localhost:${port}`).pathname;
|
|
306
|
+
|
|
307
|
+
// SPA fallback - serve index.html for routes
|
|
308
|
+
if (pathname === '/' || !pathname.includes('.')) {
|
|
309
|
+
pathname = '/index.html';
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
const filePath = join(distDir, pathname);
|
|
313
|
+
|
|
314
|
+
if (existsSync(filePath) && statSync(filePath).isFile()) {
|
|
315
|
+
const ext = filePath.substring(filePath.lastIndexOf('.'));
|
|
316
|
+
const mimeType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
317
|
+
|
|
318
|
+
res.writeHead(200, {
|
|
319
|
+
'Content-Type': mimeType,
|
|
320
|
+
'Cache-Control': 'public, max-age=31536000'
|
|
321
|
+
});
|
|
322
|
+
res.end(readFileSync(filePath));
|
|
323
|
+
} else {
|
|
324
|
+
res.writeHead(404, { 'Content-Type': 'text/plain' });
|
|
325
|
+
res.end('Not Found');
|
|
326
|
+
}
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
server.listen(port, () => {
|
|
330
|
+
console.log(`
|
|
331
|
+
Pulse Preview Server running at:
|
|
332
|
+
|
|
333
|
+
Local: http://localhost:${port}/
|
|
334
|
+
|
|
335
|
+
Serving production build from: dist/
|
|
336
|
+
Press Ctrl+C to stop.
|
|
337
|
+
`);
|
|
338
|
+
});
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
export default { buildProject, previewBuild, minifyJS };
|