windowpp 0.1.1 → 0.1.2
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/lib/create.js +95 -283
- package/package.json +1 -1
package/lib/create.js
CHANGED
|
@@ -1,283 +1,95 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
// cli/lib/create.js — WindowPP app scaffolding
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
'
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
const
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
if (TEXT_EXTENSIONS.has(ext)) {
|
|
97
|
-
let content = fs.readFileSync(src, 'utf8');
|
|
98
|
-
for (const [token, value] of Object.entries(tokens)) {
|
|
99
|
-
content = content.split(token).join(value);
|
|
100
|
-
}
|
|
101
|
-
fs.writeFileSync(dest, content, 'utf8');
|
|
102
|
-
} else {
|
|
103
|
-
fs.copyFileSync(src, dest);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
|
|
107
|
-
module.exports = { create };
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
function create(name, options = {}) {
|
|
111
|
-
const {
|
|
112
|
-
template = 'solid',
|
|
113
|
-
outDir = process.cwd(),
|
|
114
|
-
installDeps = true,
|
|
115
|
-
} = options;
|
|
116
|
-
|
|
117
|
-
if (!name || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
|
|
118
|
-
console.error('Error: app name must start with a letter and contain only letters, digits, hyphens or underscores.');
|
|
119
|
-
process.exit(1);
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
const appDir = path.join(outDir, name);
|
|
123
|
-
if (fs.existsSync(appDir)) {
|
|
124
|
-
console.error(`Error: directory "${appDir}" already exists.`);
|
|
125
|
-
process.exit(1);
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const cliDir = path.resolve(__dirname, '..');
|
|
129
|
-
const templateDir = path.join(cliDir, 'templates', template);
|
|
130
|
-
if (!fs.existsSync(templateDir)) {
|
|
131
|
-
console.error(`Error: template "${template}" not found in ${path.join(cliDir, 'templates')}`);
|
|
132
|
-
process.exit(1);
|
|
133
|
-
}
|
|
134
|
-
|
|
135
|
-
const rootDir = findRootDir(outDir);
|
|
136
|
-
|
|
137
|
-
// cmake target name: replace hyphens with underscores
|
|
138
|
-
const cmakeTarget = name.replace(/-/g, '_');
|
|
139
|
-
const appTitle = name
|
|
140
|
-
.split(/[-_]/)
|
|
141
|
-
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
142
|
-
.join(' ');
|
|
143
|
-
|
|
144
|
-
const tokens = {
|
|
145
|
-
'{{APP_NAME}}': name,
|
|
146
|
-
'{{APP_TITLE}}': appTitle,
|
|
147
|
-
'{{CMAKE_TARGET}}': cmakeTarget,
|
|
148
|
-
'{{REPO_ROOT}}': rootDir.replace(/\\/g, '/'),
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
console.log(`\n=== WindowPP Create — ${name} (template: ${template}) ===\n`);
|
|
152
|
-
console.log(`Scaffolding into: ${appDir}\n`);
|
|
153
|
-
|
|
154
|
-
// ── Copy template ─────────────────────────────────────────────────────────
|
|
155
|
-
copyDir(templateDir, appDir, tokens);
|
|
156
|
-
|
|
157
|
-
// ── Register in CMakeLists.txt ────────────────────────────────────────────
|
|
158
|
-
const appDirRelative = path.relative(rootDir, appDir).replace(/\\/g, '/');
|
|
159
|
-
addToCMake(rootDir, name, cmakeTarget, appDirRelative);
|
|
160
|
-
|
|
161
|
-
// ── Install frontend deps ─────────────────────────────────────────────────
|
|
162
|
-
const frontendDir = path.join(appDir, 'frontend');
|
|
163
|
-
if (installDeps && fs.existsSync(frontendDir)) {
|
|
164
|
-
console.log('Installing frontend dependencies...');
|
|
165
|
-
execSync('npm install', { cwd: frontendDir, stdio: 'inherit' });
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
console.log(`\n✓ Created "${name}"\n`);
|
|
169
|
-
console.log('Next steps:');
|
|
170
|
-
console.log(` cd ${name}`);
|
|
171
|
-
console.log(' windowpp dev\n');
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
// ── Helpers ───────────────────────────────────────────────────────────────────
|
|
175
|
-
|
|
176
|
-
function copyDir(src, dest, tokens) {
|
|
177
|
-
fs.mkdirSync(dest, { recursive: true });
|
|
178
|
-
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
179
|
-
const srcPath = path.join(src, entry.name);
|
|
180
|
-
const destPath = path.join(dest, entry.name);
|
|
181
|
-
if (entry.isDirectory()) {
|
|
182
|
-
copyDir(srcPath, destPath, tokens);
|
|
183
|
-
} else {
|
|
184
|
-
copyFile(srcPath, destPath, tokens);
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
const TEXT_EXTENSIONS = new Set([
|
|
190
|
-
'.cpp', '.h', '.ts', '.tsx', '.js', '.json', '.html',
|
|
191
|
-
'.css', '.md', '.txt', '.cmake', '.sh', '.env',
|
|
192
|
-
]);
|
|
193
|
-
|
|
194
|
-
function copyFile(src, dest, tokens) {
|
|
195
|
-
const ext = path.extname(src).toLowerCase();
|
|
196
|
-
if (TEXT_EXTENSIONS.has(ext)) {
|
|
197
|
-
let content = fs.readFileSync(src, 'utf8');
|
|
198
|
-
for (const [token, value] of Object.entries(tokens)) {
|
|
199
|
-
content = content.split(token).join(value);
|
|
200
|
-
}
|
|
201
|
-
fs.writeFileSync(dest, content, 'utf8');
|
|
202
|
-
} else {
|
|
203
|
-
fs.copyFileSync(src, dest);
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
function addToCMake(rootDir, appName, cmakeTarget, appDirRelative) {
|
|
208
|
-
const cmakePath = path.join(rootDir, 'CMakeLists.txt');
|
|
209
|
-
let cmake = fs.readFileSync(cmakePath, 'utf8');
|
|
210
|
-
|
|
211
|
-
// Insert before the # ─── Install section
|
|
212
|
-
const installMarker = '# ─── Install ──';
|
|
213
|
-
if (!cmake.includes(installMarker)) {
|
|
214
|
-
console.warn('Warning: could not locate Install section in CMakeLists.txt — skipping auto-registration.');
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
|
|
218
|
-
const appBlock = generateCMakeBlock(appName, cmakeTarget, appDirRelative);
|
|
219
|
-
cmake = cmake.replace(installMarker, appBlock + '\n' + installMarker);
|
|
220
|
-
fs.writeFileSync(cmakePath, cmake, 'utf8');
|
|
221
|
-
console.log(`Registered ${cmakeTarget} in CMakeLists.txt`);
|
|
222
|
-
}
|
|
223
|
-
|
|
224
|
-
function generateCMakeBlock(appName, cmakeTarget, appDirRelative) {
|
|
225
|
-
const generatedVar = cmakeTarget.toUpperCase() + '_GENERATED_DIR';
|
|
226
|
-
const embeddedCppVar = cmakeTarget.toUpperCase() + '_EMBEDDED_ASSETS_CPP';
|
|
227
|
-
const embeddedHVar = cmakeTarget.toUpperCase() + '_EMBEDDED_ASSETS_H';
|
|
228
|
-
const assetsTarget = cmakeTarget + '_frontend_assets';
|
|
229
|
-
|
|
230
|
-
return `# ─── ${appName} ──────────────────────────────────────────────────────────────────
|
|
231
|
-
|
|
232
|
-
if(WPP_BUILD_EXAMPLES)
|
|
233
|
-
add_executable(${cmakeTarget} ${appDirRelative}/main.cpp)
|
|
234
|
-
target_link_libraries(${cmakeTarget} PRIVATE windowpp nlohmann_json::nlohmann_json)
|
|
235
|
-
if(WIN32 AND WEBVIEW2_INCLUDE_DIR)
|
|
236
|
-
target_include_directories(${cmakeTarget} PRIVATE \${WEBVIEW2_INCLUDE_DIR})
|
|
237
|
-
if(WEBVIEW2_STATIC)
|
|
238
|
-
target_link_libraries(${cmakeTarget} PRIVATE
|
|
239
|
-
\${CMAKE_CURRENT_SOURCE_DIR}/src/renderer/webview/x64/WebView2LoaderStatic.lib
|
|
240
|
-
version)
|
|
241
|
-
else()
|
|
242
|
-
target_link_libraries(${cmakeTarget} PRIVATE
|
|
243
|
-
\${CMAKE_CURRENT_SOURCE_DIR}/src/renderer/webview/x64/WebView2Loader.lib)
|
|
244
|
-
endif()
|
|
245
|
-
endif()
|
|
246
|
-
|
|
247
|
-
set(${generatedVar} \${CMAKE_BINARY_DIR}/generated_${cmakeTarget})
|
|
248
|
-
set(${embeddedCppVar} \${${generatedVar}}/embedded_assets.cpp)
|
|
249
|
-
set(${embeddedHVar} \${${generatedVar}}/embedded_assets.h)
|
|
250
|
-
|
|
251
|
-
add_custom_command(
|
|
252
|
-
OUTPUT \${${embeddedCppVar}} \${${embeddedHVar}}
|
|
253
|
-
COMMAND \${CMAKE_COMMAND} -E make_directory \${${generatedVar}}
|
|
254
|
-
COMMAND \${Python3_EXECUTABLE}
|
|
255
|
-
\${WPP_EMBED_SCRIPT}
|
|
256
|
-
\${CMAKE_CURRENT_SOURCE_DIR}/${appDirRelative}/frontend/dist
|
|
257
|
-
\${${embeddedCppVar}}
|
|
258
|
-
\${${embeddedHVar}}
|
|
259
|
-
DEPENDS \${CMAKE_CURRENT_SOURCE_DIR}/${appDirRelative}/frontend/dist/index.html
|
|
260
|
-
COMMENT "Embedding ${appName} frontend assets into C++ byte arrays..."
|
|
261
|
-
VERBATIM
|
|
262
|
-
)
|
|
263
|
-
|
|
264
|
-
set_source_files_properties(
|
|
265
|
-
\${${embeddedCppVar}}
|
|
266
|
-
\${${embeddedHVar}}
|
|
267
|
-
PROPERTIES GENERATED TRUE
|
|
268
|
-
)
|
|
269
|
-
|
|
270
|
-
add_custom_target(${assetsTarget} ALL
|
|
271
|
-
DEPENDS \${${embeddedCppVar}} \${${embeddedHVar}}
|
|
272
|
-
)
|
|
273
|
-
|
|
274
|
-
target_sources(${cmakeTarget} PRIVATE \${${embeddedCppVar}})
|
|
275
|
-
target_include_directories(${cmakeTarget} PRIVATE \${${generatedVar}})
|
|
276
|
-
target_compile_definitions(${cmakeTarget} PRIVATE WPP_EMBEDDED_ASSETS)
|
|
277
|
-
add_dependencies(${cmakeTarget} ${assetsTarget})
|
|
278
|
-
endif()
|
|
279
|
-
|
|
280
|
-
`;
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
module.exports = { create };
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// cli/lib/create.js — WindowPP app scaffolding
|
|
3
|
+
|
|
4
|
+
'use strict';
|
|
5
|
+
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const fs = require('fs');
|
|
8
|
+
const { execSync } = require('child_process');
|
|
9
|
+
|
|
10
|
+
const TEXT_EXTENSIONS = new Set([
|
|
11
|
+
'.cpp', '.h', '.ts', '.tsx', '.js', '.json', '.html',
|
|
12
|
+
'.css', '.md', '.txt', '.cmake', '.sh', '.env',
|
|
13
|
+
]);
|
|
14
|
+
|
|
15
|
+
function copyFile(src, dest, tokens) {
|
|
16
|
+
const ext = path.extname(src).toLowerCase();
|
|
17
|
+
if (TEXT_EXTENSIONS.has(ext)) {
|
|
18
|
+
let content = fs.readFileSync(src, 'utf8');
|
|
19
|
+
for (const [token, value] of Object.entries(tokens)) {
|
|
20
|
+
content = content.split(token).join(value);
|
|
21
|
+
}
|
|
22
|
+
fs.writeFileSync(dest, content, 'utf8');
|
|
23
|
+
} else {
|
|
24
|
+
fs.copyFileSync(src, dest);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function copyDir(src, dest, tokens) {
|
|
29
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
30
|
+
for (const entry of fs.readdirSync(src, { withFileTypes: true })) {
|
|
31
|
+
const srcPath = path.join(src, entry.name);
|
|
32
|
+
const destPath = path.join(dest, entry.name);
|
|
33
|
+
if (entry.isDirectory()) {
|
|
34
|
+
copyDir(srcPath, destPath, tokens);
|
|
35
|
+
} else {
|
|
36
|
+
copyFile(srcPath, destPath, tokens);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function create(name, options = {}) {
|
|
42
|
+
const {
|
|
43
|
+
template = 'solid',
|
|
44
|
+
outDir = process.cwd(),
|
|
45
|
+
installDeps = true,
|
|
46
|
+
} = options;
|
|
47
|
+
|
|
48
|
+
if (!name || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(name)) {
|
|
49
|
+
console.error('Error: app name must start with a letter and contain only letters, digits, hyphens or underscores.');
|
|
50
|
+
process.exit(1);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const appDir = path.join(outDir, name);
|
|
54
|
+
if (fs.existsSync(appDir)) {
|
|
55
|
+
console.error(`Error: directory "${appDir}" already exists.`);
|
|
56
|
+
process.exit(1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
const cliDir = path.resolve(__dirname, '..');
|
|
60
|
+
const templateDir = path.join(cliDir, 'templates', template);
|
|
61
|
+
if (!fs.existsSync(templateDir)) {
|
|
62
|
+
console.error(`Error: template "${template}" not found in ${path.join(cliDir, 'templates')}`);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
const cmakeTarget = name.replace(/-/g, '_');
|
|
67
|
+
const appTitle = name
|
|
68
|
+
.split(/[-_]/)
|
|
69
|
+
.map(w => w.charAt(0).toUpperCase() + w.slice(1))
|
|
70
|
+
.join(' ');
|
|
71
|
+
|
|
72
|
+
const tokens = {
|
|
73
|
+
'{{APP_NAME}}': name,
|
|
74
|
+
'{{APP_TITLE}}': appTitle,
|
|
75
|
+
'{{CMAKE_TARGET}}': cmakeTarget,
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
console.log(`\n=== WindowPP Create --- ${name} (template: ${template}) ===\n`);
|
|
79
|
+
console.log(`Scaffolding into: ${appDir}\n`);
|
|
80
|
+
|
|
81
|
+
copyDir(templateDir, appDir, tokens);
|
|
82
|
+
|
|
83
|
+
const frontendDir = path.join(appDir, 'frontend');
|
|
84
|
+
if (installDeps && fs.existsSync(frontendDir)) {
|
|
85
|
+
console.log('Installing frontend dependencies...');
|
|
86
|
+
execSync('npm install', { cwd: frontendDir, stdio: 'inherit' });
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
console.log(`\n-- Created "${name}"\n`);
|
|
90
|
+
console.log('Next steps:');
|
|
91
|
+
console.log(` cd ${name}`);
|
|
92
|
+
console.log(' windowpp dev\n');
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
module.exports = { create };
|