create-vike 0.0.1 → 0.0.4
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 +7 -5
- package/dist/index.js +191 -144
- package/{input-files/react/pages/about/index.page.tsx → files/js/react/pages/about/index.page.jsx} +0 -0
- package/{input-files/react/pages/index/Counter.tsx → files/js/react/pages/index/Counter.jsx} +0 -0
- package/{input-files/react/pages/index/index.page.tsx → files/js/react/pages/index/index.page.jsx} +0 -0
- package/files/js/react/renderer/Link.jsx +15 -0
- package/files/js/react/renderer/PageWrapper.jsx +89 -0
- package/files/js/react/renderer/_default.page.client.jsx +19 -0
- package/files/js/react/renderer/_default.page.server.jsx +47 -0
- package/files/js/react/renderer/_error.page.jsx +21 -0
- package/files/js/react/renderer/usePageContext.jsx +18 -0
- package/files/js/react+client-router/renderer/_default.page.client.jsx +43 -0
- package/files/js/react+client-router/renderer/types.js +1 -0
- package/files/js/vike/server/index.js +40 -0
- package/{input-files → files/js}/vue/pages/about/index.page.vue +0 -0
- package/files/js/vue/pages/index/Counter.vue +10 -0
- package/files/js/vue/pages/index/index.page.vue +12 -0
- package/files/js/vue/renderer/Link.vue +17 -0
- package/files/js/vue/renderer/PageWrapper.vue +55 -0
- package/files/js/vue/renderer/_default.page.client.js +12 -0
- package/files/js/vue/renderer/_default.page.server.js +41 -0
- package/files/js/vue/renderer/_error.page.vue +14 -0
- package/files/js/vue/renderer/app.js +29 -0
- package/files/js/vue/renderer/usePageContext.js +18 -0
- package/files/js/vue+client-router/renderer/_default.page.client.js +23 -0
- package/files/js/vue+client-router/renderer/app.js +36 -0
- package/files/js/vue+client-router/renderer/types.js +1 -0
- package/{input-files → files/shared}/.prettierrc +0 -0
- package/{input-files → files/shared}/react/pages/about/index.css +0 -0
- package/{input-files → files/shared}/react/renderer/PageWrapper.css +0 -0
- package/files/shared/vike/_gitignore +121 -0
- package/{input-files/common → files/shared/vike}/renderer/logo.svg +0 -0
- package/files/ts/react/pages/about/index.page.tsx +13 -0
- package/files/ts/react/pages/index/Counter.tsx +12 -0
- package/files/ts/react/pages/index/index.page.tsx +19 -0
- package/{input-files → files/ts}/react/renderer/Link.tsx +0 -0
- package/{input-files → files/ts}/react/renderer/PageWrapper.tsx +0 -0
- package/{input-files → files/ts}/react/renderer/_default.page.client.tsx +0 -0
- package/{input-files → files/ts}/react/renderer/_default.page.server.tsx +0 -0
- package/{input-files → files/ts}/react/renderer/_error.page.tsx +0 -0
- package/{input-files → files/ts}/react/renderer/types.ts +0 -0
- package/{input-files → files/ts}/react/renderer/usePageContext.tsx +0 -0
- package/files/ts/react+client-router/renderer/_default.page.client.tsx +44 -0
- package/files/ts/react+client-router/renderer/types.ts +12 -0
- package/{input-files/common → files/ts/vike}/server/index.ts +0 -5
- package/files/ts/vue/pages/about/index.page.vue +11 -0
- package/{input-files → files/ts}/vue/pages/index/Counter.vue +0 -0
- package/{input-files → files/ts}/vue/pages/index/index.page.vue +0 -0
- package/{input-files → files/ts}/vue/renderer/Link.vue +0 -0
- package/{input-files → files/ts}/vue/renderer/PageWrapper.vue +0 -0
- package/{input-files → files/ts}/vue/renderer/_default.page.client.ts +0 -0
- package/{input-files → files/ts}/vue/renderer/_default.page.server.ts +0 -0
- package/{input-files → files/ts}/vue/renderer/_error.page.vue +0 -0
- package/{input-files → files/ts}/vue/renderer/app.ts +0 -12
- package/{input-files → files/ts}/vue/renderer/types.ts +0 -0
- package/{input-files → files/ts}/vue/renderer/usePageContext.ts +0 -0
- package/{input-files → files/ts}/vue/vue.d.ts +0 -0
- package/files/ts/vue+client-router/renderer/_default.page.client.ts +24 -0
- package/files/ts/vue+client-router/renderer/app.ts +37 -0
- package/files/ts/vue+client-router/renderer/types.ts +11 -0
- package/package.json +56 -53
- package/input-files/common/_gitignore +0 -4
- package/input-files/vue/tsconfig.json +0 -18
package/README.md
CHANGED
|
@@ -17,12 +17,14 @@ Options:
|
|
|
17
17
|
```
|
|
18
18
|
|
|
19
19
|
## How it works
|
|
20
|
-
-
|
|
21
|
-
-
|
|
20
|
+
- Generates TypeScript and JavaScript files from the templates in `input-files` via `detype`.
|
|
21
|
+
- Copies files from `files/<language>/<feature>` where:
|
|
22
|
+
- `<language>` is `shared`, `ts`, or `js`
|
|
23
|
+
- `<feature>` is any combination of `vike` (default), `react`, `vue`, and `client-router` combined with a plus sign
|
|
22
24
|
- Configuration files (`package.json`, `tsconfig.json`, and `vite.config.{js,ts}`) are generated programmatically.
|
|
23
|
-
- Boilerplate package versions are kept in `src/config-generators/package-versions.json
|
|
25
|
+
- Boilerplate package versions are kept in `src/config-generators/package-versions.json`, `check-deps.mjs` can be used to review package updates.
|
|
24
26
|
|
|
25
|
-
##
|
|
27
|
+
## TODO
|
|
28
|
+
- Add integration tests
|
|
26
29
|
- Create an interactive frontend
|
|
27
|
-
- Apply TS > JS transform in build-time to speed up generation
|
|
28
30
|
- Resolve user's default prettier config if any and use it instead of the default
|
package/dist/index.js
CHANGED
|
@@ -21,104 +21,42 @@ var __spreadValues = (a, b) => {
|
|
|
21
21
|
return a;
|
|
22
22
|
};
|
|
23
23
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
24
|
-
var
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
__defProp(target, key, { get: () => module2[key], enumerable: !(desc = __getOwnPropDesc(module2, key)) || desc.enumerable });
|
|
24
|
+
var __copyProps = (to, from, except, desc) => {
|
|
25
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
26
|
+
for (let key of __getOwnPropNames(from))
|
|
27
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
28
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
30
29
|
}
|
|
31
|
-
return
|
|
32
|
-
};
|
|
33
|
-
var __toModule = (module2) => {
|
|
34
|
-
return __reExport(__markAsModule(__defProp(module2 != null ? __create(__getProtoOf(module2)) : {}, "default", module2 && module2.__esModule && "default" in module2 ? { get: () => module2.default, enumerable: true } : { value: module2, enumerable: true })), module2);
|
|
30
|
+
return to;
|
|
35
31
|
};
|
|
32
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod));
|
|
36
33
|
|
|
37
34
|
// src/index.ts
|
|
38
|
-
var import_commander =
|
|
35
|
+
var import_commander = require("commander");
|
|
39
36
|
|
|
40
37
|
// src/generate.ts
|
|
41
|
-
var
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
var import_fs = __toModule(require("fs"));
|
|
45
|
-
var import_path = __toModule(require("path"));
|
|
46
|
-
var import_walk = __toModule(require("walk"));
|
|
47
|
-
async function copyFiles(src, dest, filter) {
|
|
48
|
-
return new Promise((resolve) => {
|
|
49
|
-
const walker = (0, import_walk.walk)(src, {});
|
|
50
|
-
walker.on("file", async (root, fileStats, next) => {
|
|
51
|
-
var _a;
|
|
52
|
-
const srcPath = import_path.default.join(root, fileStats.name);
|
|
53
|
-
const relativePath = import_path.default.relative(src, srcPath);
|
|
54
|
-
const destPath = import_path.default.join(dest, relativePath);
|
|
55
|
-
const filterResult = await filter({
|
|
56
|
-
path: relativePath,
|
|
57
|
-
readContent: () => import_fs.default.promises.readFile(srcPath, "utf-8"),
|
|
58
|
-
srcPath,
|
|
59
|
-
destPath
|
|
60
|
-
});
|
|
61
|
-
switch (filterResult.operation) {
|
|
62
|
-
case "skip":
|
|
63
|
-
break;
|
|
64
|
-
case "copy":
|
|
65
|
-
{
|
|
66
|
-
const outFileDir = import_path.default.dirname(destPath);
|
|
67
|
-
await import_fs.default.promises.mkdir(outFileDir, { recursive: true });
|
|
68
|
-
await import_fs.default.promises.copyFile(srcPath, destPath);
|
|
69
|
-
}
|
|
70
|
-
break;
|
|
71
|
-
case "rename":
|
|
72
|
-
{
|
|
73
|
-
const outFileName = import_path.default.join(dest, filterResult.newPath);
|
|
74
|
-
const outFileDir = import_path.default.dirname(outFileName);
|
|
75
|
-
await import_fs.default.promises.mkdir(outFileDir, { recursive: true });
|
|
76
|
-
await import_fs.default.promises.copyFile(srcPath, outFileName);
|
|
77
|
-
}
|
|
78
|
-
break;
|
|
79
|
-
case "transform":
|
|
80
|
-
{
|
|
81
|
-
const outFileName = import_path.default.join(dest, (_a = filterResult.newPath) != null ? _a : relativePath);
|
|
82
|
-
const outFileDir = import_path.default.dirname(outFileName);
|
|
83
|
-
await import_fs.default.promises.mkdir(outFileDir, { recursive: true });
|
|
84
|
-
await import_fs.default.promises.writeFile(outFileName, filterResult.newContent, "utf-8");
|
|
85
|
-
}
|
|
86
|
-
break;
|
|
87
|
-
default:
|
|
88
|
-
assertNever(filterResult);
|
|
89
|
-
}
|
|
90
|
-
next();
|
|
91
|
-
});
|
|
92
|
-
walker.on("end", resolve);
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
function assertNever(arg) {
|
|
96
|
-
throw new Error("Unexpected type");
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// src/generate.ts
|
|
100
|
-
var import_detype = __toModule(require("detype"));
|
|
101
|
-
var import_promises = __toModule(require("fs/promises"));
|
|
102
|
-
var import_prettier = __toModule(require("prettier"));
|
|
38
|
+
var import_path = __toESM(require("path"));
|
|
39
|
+
var import_promises = __toESM(require("fs/promises"));
|
|
40
|
+
var import_prettier = require("prettier");
|
|
103
41
|
|
|
104
42
|
// src/config-generators/package-versions.json
|
|
105
|
-
var _types_express = "
|
|
106
|
-
var _types_node = "
|
|
107
|
-
var _types_react_dom = "
|
|
108
|
-
var _types_react = "
|
|
109
|
-
var _vitejs_plugin_react_refresh = "
|
|
110
|
-
var _vitejs_plugin_vue = "
|
|
111
|
-
var _vue_compiler_sfc = "
|
|
112
|
-
var _vue_server_renderer = "
|
|
113
|
-
var cross_env = "
|
|
114
|
-
var express = "
|
|
115
|
-
var react_dom = "
|
|
116
|
-
var react = "
|
|
117
|
-
var ts_node = "
|
|
118
|
-
var typescript = "
|
|
119
|
-
var vite_plugin_ssr = "
|
|
120
|
-
var vite = "2.
|
|
121
|
-
var vue = "
|
|
43
|
+
var _types_express = "4.17.13";
|
|
44
|
+
var _types_node = "17.0.36";
|
|
45
|
+
var _types_react_dom = "18.0.5";
|
|
46
|
+
var _types_react = "18.0.9";
|
|
47
|
+
var _vitejs_plugin_react_refresh = "1.3.6";
|
|
48
|
+
var _vitejs_plugin_vue = "2.3.3";
|
|
49
|
+
var _vue_compiler_sfc = "3.2.36";
|
|
50
|
+
var _vue_server_renderer = "3.2.36";
|
|
51
|
+
var cross_env = "7.0.3";
|
|
52
|
+
var express = "4.18.1";
|
|
53
|
+
var react_dom = "18.1.0";
|
|
54
|
+
var react = "18.1.0";
|
|
55
|
+
var ts_node = "10.8.0";
|
|
56
|
+
var typescript = "4.7.2";
|
|
57
|
+
var vite_plugin_ssr = "0.3.64";
|
|
58
|
+
var vite = "2.9.9";
|
|
59
|
+
var vue = "3.2.36";
|
|
122
60
|
var package_versions_default = {
|
|
123
61
|
"@types/express": _types_express,
|
|
124
62
|
"@types/node": _types_node,
|
|
@@ -168,7 +106,7 @@ var ConfigGenerator = class {
|
|
|
168
106
|
return [dep, package_versions_default[dep]];
|
|
169
107
|
}))
|
|
170
108
|
});
|
|
171
|
-
return
|
|
109
|
+
return output;
|
|
172
110
|
}
|
|
173
111
|
generateViteConfig() {
|
|
174
112
|
const config = this.getViteConfig();
|
|
@@ -279,77 +217,186 @@ var VUE_DEPENDENCIES = [
|
|
|
279
217
|
"vue"
|
|
280
218
|
];
|
|
281
219
|
|
|
220
|
+
// src/detect-package-manager.ts
|
|
221
|
+
function detectPackageManager() {
|
|
222
|
+
const agent = process.env.npm_config_user_agent;
|
|
223
|
+
if (agent) {
|
|
224
|
+
const [program2] = agent.split("/");
|
|
225
|
+
if (program2 === "yarn")
|
|
226
|
+
return "yarn";
|
|
227
|
+
if (program2 === "pnpm")
|
|
228
|
+
return "pnpm";
|
|
229
|
+
if (program2 === "npm")
|
|
230
|
+
return "npm";
|
|
231
|
+
}
|
|
232
|
+
if (process.platform !== "win32") {
|
|
233
|
+
const parent = process.env._;
|
|
234
|
+
if (parent) {
|
|
235
|
+
if (parent.endsWith("pnpx") || parent.endsWith("pnpm"))
|
|
236
|
+
return "pnpm";
|
|
237
|
+
if (parent.endsWith("yarn"))
|
|
238
|
+
return "yarn";
|
|
239
|
+
if (parent.endsWith("npx") || parent.endsWith("npm"))
|
|
240
|
+
return "npm";
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return null;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// src/run-command.ts
|
|
247
|
+
var import_child_process = require("child_process");
|
|
248
|
+
async function runCommand(command, ...args) {
|
|
249
|
+
return new Promise((resolve, reject) => {
|
|
250
|
+
const child = (0, import_child_process.spawn)(command, args, { stdio: "inherit" });
|
|
251
|
+
child.on("close", (code) => {
|
|
252
|
+
if (code === 0) {
|
|
253
|
+
resolve();
|
|
254
|
+
} else {
|
|
255
|
+
reject();
|
|
256
|
+
}
|
|
257
|
+
});
|
|
258
|
+
});
|
|
259
|
+
}
|
|
260
|
+
|
|
282
261
|
// src/generate.ts
|
|
283
|
-
var
|
|
262
|
+
var import_walk = require("walk");
|
|
263
|
+
var FILES_DIR = import_path.default.resolve(__dirname, "../files");
|
|
284
264
|
async function generate({
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
265
|
+
outputDir,
|
|
266
|
+
typescript: typescript2,
|
|
267
|
+
react: react2,
|
|
268
|
+
vue: vue2,
|
|
269
|
+
clientRouter,
|
|
270
|
+
skipDependencies,
|
|
271
|
+
npm,
|
|
272
|
+
yarn,
|
|
273
|
+
pnpm,
|
|
274
|
+
initGitRepo,
|
|
275
|
+
createInitialCommit
|
|
288
276
|
}) {
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
277
|
+
let error = false;
|
|
278
|
+
if (Number(npm) + Number(pnpm) + Number(yarn) > 1) {
|
|
279
|
+
process.stderr.write("Only one of npm, pnpm, or yarn can be specified\n");
|
|
280
|
+
error = true;
|
|
281
|
+
}
|
|
282
|
+
let packageManager = npm ? "npm" : pnpm ? "pnpm" : yarn ? "yarn" : void 0;
|
|
283
|
+
if (!packageManager) {
|
|
284
|
+
const detected = detectPackageManager();
|
|
285
|
+
packageManager = detected || "npm";
|
|
286
|
+
}
|
|
287
|
+
if (vue2 && react2) {
|
|
288
|
+
process.stderr.write("Cannot use both react and vue\n");
|
|
289
|
+
error = true;
|
|
290
|
+
} else if (!vue2 && !react2) {
|
|
291
|
+
process.stderr.write("Please specify either --react or --vue\n");
|
|
292
|
+
error = true;
|
|
293
|
+
}
|
|
294
|
+
if (error) {
|
|
295
|
+
process.exit(1);
|
|
296
|
+
}
|
|
297
|
+
const framework = vue2 ? "vue" : "react";
|
|
298
|
+
const features = ["vike", framework];
|
|
299
|
+
if (clientRouter)
|
|
300
|
+
features.push("client-router");
|
|
301
|
+
const language = typescript2 ? "ts" : "js";
|
|
302
|
+
async function findDirs(dir) {
|
|
303
|
+
return (await import_promises.default.readdir(import_path.default.join(FILES_DIR, dir), {
|
|
304
|
+
withFileTypes: true
|
|
305
|
+
})).filter((x) => x.isDirectory()).map((x) => ({
|
|
306
|
+
name: import_path.default.join(dir, x.name),
|
|
307
|
+
features: x.name.split("+")
|
|
308
|
+
})).sort((a, b) => a.features.length - b.features.length);
|
|
309
|
+
}
|
|
310
|
+
const dirs = [...await findDirs("shared"), ...await findDirs(language)].filter((x) => x.features.every((f) => features.includes(f))).map((x) => x.name);
|
|
311
|
+
console.log("Copying files");
|
|
312
|
+
const toBeCopied = {};
|
|
313
|
+
for (const dir of dirs) {
|
|
314
|
+
const files = await getFiles(dir);
|
|
315
|
+
files.forEach((x) => {
|
|
316
|
+
let targetName = x.slice(dir.length + 1);
|
|
317
|
+
if (targetName === "_gitignore")
|
|
318
|
+
targetName = ".gitignore";
|
|
319
|
+
toBeCopied[targetName] = x;
|
|
320
|
+
});
|
|
321
|
+
}
|
|
322
|
+
for (const [targetName, sourcePath] of Object.entries(toBeCopied)) {
|
|
323
|
+
const targetPath = import_path.default.join(outputDir, targetName);
|
|
324
|
+
const dirName = import_path.default.dirname(targetPath);
|
|
325
|
+
await import_promises.default.mkdir(dirName, { recursive: true });
|
|
326
|
+
await import_promises.default.copyFile(import_path.default.join(FILES_DIR, sourcePath), targetPath);
|
|
327
|
+
}
|
|
319
328
|
const generators = {
|
|
320
329
|
react: ReactConfigGenerator,
|
|
321
330
|
vue: VueConfigGenerator
|
|
322
331
|
};
|
|
323
|
-
|
|
324
|
-
const
|
|
325
|
-
|
|
332
|
+
console.log("Generating configutation files");
|
|
333
|
+
const generator = new generators[framework](language);
|
|
334
|
+
const prettierConfig = {};
|
|
335
|
+
const packageJson = generator.generatePackageJson();
|
|
336
|
+
if (yarn) {
|
|
337
|
+
packageJson.scripts.dev = "yarn server";
|
|
338
|
+
packageJson.scripts.prod = "yarn build && yarn server:prod";
|
|
339
|
+
} else if (pnpm) {
|
|
340
|
+
packageJson.scripts.dev = "pnpm run server";
|
|
341
|
+
packageJson.scripts.prod = "pnpm build && pnpm server:prod";
|
|
342
|
+
}
|
|
343
|
+
const packageJsonfileName = import_path.default.join(outputDir, "package.json");
|
|
344
|
+
await import_promises.default.writeFile(packageJsonfileName, (0, import_prettier.format)(JSON.stringify(packageJson), __spreadProps(__spreadValues({}, prettierConfig), {
|
|
326
345
|
filepath: packageJsonfileName
|
|
327
346
|
})));
|
|
328
347
|
if (language === "ts") {
|
|
329
|
-
const fn =
|
|
348
|
+
const fn = import_path.default.join(outputDir, "tsconfig.json");
|
|
330
349
|
await import_promises.default.writeFile(fn, (0, import_prettier.format)(generator.generateTsConfig(), __spreadProps(__spreadValues({}, prettierConfig), { filepath: fn })));
|
|
331
350
|
}
|
|
332
|
-
const viteConfigFileName =
|
|
351
|
+
const viteConfigFileName = import_path.default.join(outputDir, "vite.config." + language);
|
|
333
352
|
await import_promises.default.writeFile(viteConfigFileName, (0, import_prettier.format)(generator.generateViteConfig(), __spreadProps(__spreadValues({}, prettierConfig), {
|
|
334
353
|
filepath: viteConfigFileName
|
|
335
354
|
})));
|
|
355
|
+
process.chdir(outputDir);
|
|
356
|
+
if (!skipDependencies) {
|
|
357
|
+
console.log("Installing dependencies with", packageManager);
|
|
358
|
+
await runCommand(packageManager, "install");
|
|
359
|
+
}
|
|
360
|
+
if (initGitRepo) {
|
|
361
|
+
console.log("Initializing git repository");
|
|
362
|
+
await runCommand("git", "init");
|
|
363
|
+
if (initGitRepo === true)
|
|
364
|
+
initGitRepo = "main";
|
|
365
|
+
if (initGitRepo !== "master") {
|
|
366
|
+
await runCommand("git", "checkout", "-b", initGitRepo);
|
|
367
|
+
}
|
|
368
|
+
if (createInitialCommit) {
|
|
369
|
+
console.log("Creating initial commit");
|
|
370
|
+
if (createInitialCommit === true)
|
|
371
|
+
createInitialCommit = `Initialized Vike ${typescript2 ? "TypeScript" : "vanilla JavaScript"} boilerplate for ${react2 ? "React" : "Vue"}`;
|
|
372
|
+
await runCommand("git", "add", ".");
|
|
373
|
+
await runCommand("git", "commit", "-m", createInitialCommit);
|
|
374
|
+
}
|
|
375
|
+
} else if (createInitialCommit) {
|
|
376
|
+
console.warn("Ignoring initial commit because no git repo was initialized");
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
async function getFiles(dir) {
|
|
380
|
+
const files = [];
|
|
381
|
+
const walker = (0, import_walk.walk)(import_path.default.join(FILES_DIR, dir));
|
|
382
|
+
walker.on("file", (root, fileStats, next) => {
|
|
383
|
+
files.push(import_path.default.relative(FILES_DIR, import_path.default.join(root, fileStats.name)));
|
|
384
|
+
next();
|
|
385
|
+
});
|
|
386
|
+
await new Promise((resolve, reject) => {
|
|
387
|
+
walker.on("end", resolve);
|
|
388
|
+
walker.on("errors", (_, statsArr) => {
|
|
389
|
+
const errors = statsArr.map((stat) => stat.error);
|
|
390
|
+
reject(new Error(`Failed to walk ${dir}: ${errors.join(", ")}`));
|
|
391
|
+
});
|
|
392
|
+
});
|
|
393
|
+
return files;
|
|
336
394
|
}
|
|
337
395
|
|
|
338
396
|
// package.json
|
|
339
|
-
var version = "0.0.
|
|
397
|
+
var version = "0.0.4";
|
|
340
398
|
|
|
341
399
|
// src/index.ts
|
|
342
|
-
import_commander.program.description("Generates Vike application boilerplate").version(version)
|
|
343
|
-
import_commander.program.argument("<output-dir>", "Output directory");
|
|
344
|
-
import_commander.program.addOption(new import_commander.Option("-f, --framework <framework>", "Frontend framework").choices([
|
|
345
|
-
"react",
|
|
346
|
-
"vue"
|
|
347
|
-
]));
|
|
348
|
-
import_commander.program.addOption(new import_commander.Option("-l, --language <language>", "Programming language").choices([
|
|
349
|
-
"js",
|
|
350
|
-
"ts"
|
|
351
|
-
]));
|
|
352
|
-
import_commander.program.action((outputDir, options) => {
|
|
400
|
+
import_commander.program.description("Generates Vike application boilerplate").version(version).argument("<output-dir>", "Output directory").option("-t, --typescript", "use TypeScript", false).option("-n, --npm", "use npm package manager", false).option("-y, --yarn", "use yarn package manager", false).option("-p, --pnpm", "use pnpm package manager", false).option("-v, --vue", "use Vue", false).option("-r, --react", "use React", false).option("-c, --client-router", "use client router", false).option("-s, --skip-dependencies", "skip installing dependencies", false).option("-i, --init-git-repo [branch]", "initialize git repo", false).option("-m, --create-initial-commit [message]", "create initial commit", false).action((outputDir, options) => {
|
|
353
401
|
generate(__spreadValues({ outputDir }, options));
|
|
354
|
-
});
|
|
355
|
-
import_commander.program.parse();
|
|
402
|
+
}).parse();
|
package/{input-files/react/pages/about/index.page.tsx → files/js/react/pages/about/index.page.jsx}
RENAMED
|
File without changes
|
package/{input-files/react/pages/index/Counter.tsx → files/js/react/pages/index/Counter.jsx}
RENAMED
|
File without changes
|
package/{input-files/react/pages/index/index.page.tsx → files/js/react/pages/index/index.page.jsx}
RENAMED
|
File without changes
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { usePageContext } from "./usePageContext";
|
|
3
|
+
|
|
4
|
+
export { Link };
|
|
5
|
+
|
|
6
|
+
function Link(props) {
|
|
7
|
+
const pageContext = usePageContext();
|
|
8
|
+
const className = [
|
|
9
|
+
props.className,
|
|
10
|
+
pageContext.urlPathname === props.href && "is-active",
|
|
11
|
+
]
|
|
12
|
+
.filter(Boolean)
|
|
13
|
+
.join(" ");
|
|
14
|
+
return <a {...props} className={className} />;
|
|
15
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import logo from "./logo.svg";
|
|
3
|
+
import { PageContextProvider } from "./usePageContext";
|
|
4
|
+
import "./PageWrapper.css";
|
|
5
|
+
import { Link } from "./Link";
|
|
6
|
+
|
|
7
|
+
export { PageWrapper };
|
|
8
|
+
|
|
9
|
+
function PageWrapper({ children, pageContext }) {
|
|
10
|
+
return (
|
|
11
|
+
<React.StrictMode>
|
|
12
|
+
<PageContextProvider pageContext={pageContext}>
|
|
13
|
+
<Layout>
|
|
14
|
+
<Sidebar>
|
|
15
|
+
<Logo />
|
|
16
|
+
<Link className="navitem" href="/">
|
|
17
|
+
Home
|
|
18
|
+
</Link>
|
|
19
|
+
<Link className="navitem" href="/about">
|
|
20
|
+
About
|
|
21
|
+
</Link>
|
|
22
|
+
</Sidebar>
|
|
23
|
+
<Content>{children}</Content>
|
|
24
|
+
</Layout>
|
|
25
|
+
</PageContextProvider>
|
|
26
|
+
</React.StrictMode>
|
|
27
|
+
);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function Layout({ children }) {
|
|
31
|
+
return (
|
|
32
|
+
<div
|
|
33
|
+
style={{
|
|
34
|
+
display: "flex",
|
|
35
|
+
maxWidth: 900,
|
|
36
|
+
margin: "auto",
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{children}
|
|
40
|
+
</div>
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function Sidebar({ children }) {
|
|
45
|
+
return (
|
|
46
|
+
<div
|
|
47
|
+
style={{
|
|
48
|
+
padding: 20,
|
|
49
|
+
flexShrink: 0,
|
|
50
|
+
display: "flex",
|
|
51
|
+
flexDirection: "column",
|
|
52
|
+
alignItems: "center",
|
|
53
|
+
lineHeight: "1.8em",
|
|
54
|
+
}}
|
|
55
|
+
>
|
|
56
|
+
{children}
|
|
57
|
+
</div>
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
function Content({ children }) {
|
|
62
|
+
return (
|
|
63
|
+
<div
|
|
64
|
+
style={{
|
|
65
|
+
padding: 20,
|
|
66
|
+
paddingBottom: 50,
|
|
67
|
+
borderLeft: "2px solid #eee",
|
|
68
|
+
minHeight: "100vh",
|
|
69
|
+
}}
|
|
70
|
+
>
|
|
71
|
+
{children}
|
|
72
|
+
</div>
|
|
73
|
+
);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
function Logo() {
|
|
77
|
+
return (
|
|
78
|
+
<div
|
|
79
|
+
style={{
|
|
80
|
+
marginTop: 20,
|
|
81
|
+
marginBottom: 10,
|
|
82
|
+
}}
|
|
83
|
+
>
|
|
84
|
+
<a href="/">
|
|
85
|
+
<img src={logo} height={64} width={64} alt="logo" />
|
|
86
|
+
</a>
|
|
87
|
+
</div>
|
|
88
|
+
);
|
|
89
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import ReactDOM from "react-dom";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { getPage } from "vite-plugin-ssr/client";
|
|
4
|
+
import { PageWrapper } from "./PageWrapper";
|
|
5
|
+
|
|
6
|
+
hydrate();
|
|
7
|
+
|
|
8
|
+
async function hydrate() {
|
|
9
|
+
// We do Server Routing, but we can also do Client Routing by using `useClientRouter()`
|
|
10
|
+
// instead of `getPage()`, see https://vite-plugin-ssr.com/useClientRouter
|
|
11
|
+
const pageContext = await getPage();
|
|
12
|
+
const { Page, pageProps } = pageContext;
|
|
13
|
+
ReactDOM.hydrate(
|
|
14
|
+
<PageWrapper pageContext={pageContext}>
|
|
15
|
+
<Page {...pageProps} />
|
|
16
|
+
</PageWrapper>,
|
|
17
|
+
document.getElementById("page-view")
|
|
18
|
+
);
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import ReactDOMServer from "react-dom/server";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { PageWrapper } from "./PageWrapper";
|
|
4
|
+
import { escapeInject, dangerouslySkipEscape } from "vite-plugin-ssr";
|
|
5
|
+
import logoUrl from "./logo.svg";
|
|
6
|
+
|
|
7
|
+
export { render };
|
|
8
|
+
|
|
9
|
+
// See https://vite-plugin-ssr.com/data-fetching
|
|
10
|
+
export const passToClient = ["pageProps", "urlPathname"];
|
|
11
|
+
|
|
12
|
+
async function render(pageContext) {
|
|
13
|
+
const { Page, pageProps } = pageContext;
|
|
14
|
+
const pageHtml = ReactDOMServer.renderToString(
|
|
15
|
+
<PageWrapper pageContext={pageContext}>
|
|
16
|
+
<Page {...pageProps} />
|
|
17
|
+
</PageWrapper>
|
|
18
|
+
);
|
|
19
|
+
|
|
20
|
+
// See https://vite-plugin-ssr.com/html-head
|
|
21
|
+
const { documentProps } = pageContext;
|
|
22
|
+
const title = (documentProps && documentProps.title) || "Vite SSR app";
|
|
23
|
+
const desc =
|
|
24
|
+
(documentProps && documentProps.description) ||
|
|
25
|
+
"App using Vite + vite-plugin-ssr";
|
|
26
|
+
|
|
27
|
+
const documentHtml = escapeInject`<!DOCTYPE html>
|
|
28
|
+
<html lang="en">
|
|
29
|
+
<head>
|
|
30
|
+
<meta charset="UTF-8" />
|
|
31
|
+
<link rel="icon" href="${logoUrl}" />
|
|
32
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
33
|
+
<meta name="description" content="${desc}" />
|
|
34
|
+
<title>${title}</title>
|
|
35
|
+
</head>
|
|
36
|
+
<body>
|
|
37
|
+
<div id="page-view">${dangerouslySkipEscape(pageHtml)}</div>
|
|
38
|
+
</body>
|
|
39
|
+
</html>`;
|
|
40
|
+
|
|
41
|
+
return {
|
|
42
|
+
documentHtml,
|
|
43
|
+
pageContext: {
|
|
44
|
+
// We can add some `pageContext` here, which is useful if we want to do page redirection https://vite-plugin-ssr.com/page-redirection
|
|
45
|
+
},
|
|
46
|
+
};
|
|
47
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
|
|
3
|
+
export { Page };
|
|
4
|
+
|
|
5
|
+
function Page({ is404 }) {
|
|
6
|
+
if (is404) {
|
|
7
|
+
return (
|
|
8
|
+
<>
|
|
9
|
+
<h1>404 Page Not Found</h1>
|
|
10
|
+
<p>This page could not be found.</p>
|
|
11
|
+
</>
|
|
12
|
+
);
|
|
13
|
+
} else {
|
|
14
|
+
return (
|
|
15
|
+
<>
|
|
16
|
+
<h1>500 Internal Server Error</h1>
|
|
17
|
+
<p>Something went wrong.</p>
|
|
18
|
+
</>
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// `usePageContext` allows us to access `pageContext` in any React component.
|
|
2
|
+
// More infos: https://vite-plugin-ssr.com/pageContext-anywhere
|
|
3
|
+
|
|
4
|
+
import React, { useContext } from "react";
|
|
5
|
+
|
|
6
|
+
export { PageContextProvider };
|
|
7
|
+
export { usePageContext };
|
|
8
|
+
|
|
9
|
+
const Context = React.createContext(undefined);
|
|
10
|
+
|
|
11
|
+
function PageContextProvider({ pageContext, children }) {
|
|
12
|
+
return <Context.Provider value={pageContext}>{children}</Context.Provider>;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function usePageContext() {
|
|
16
|
+
const pageContext = useContext(Context);
|
|
17
|
+
return pageContext;
|
|
18
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import ReactDOM from "react-dom";
|
|
2
|
+
import React from "react";
|
|
3
|
+
import { useClientRouter } from "vite-plugin-ssr/client/router";
|
|
4
|
+
import { PageWrapper } from "./PageWrapper";
|
|
5
|
+
|
|
6
|
+
useClientRouter({
|
|
7
|
+
async render(pageContext) {
|
|
8
|
+
if (pageContext.isHydration) {
|
|
9
|
+
// When we render the first page. (Since we do SSR, the first page is already
|
|
10
|
+
// rendered to HTML and we merely have to hydrate it.)
|
|
11
|
+
const { Page, pageProps } = pageContext;
|
|
12
|
+
ReactDOM.hydrate(
|
|
13
|
+
<PageWrapper pageContext={pageContext}>
|
|
14
|
+
<Page {...pageProps} />
|
|
15
|
+
</PageWrapper>,
|
|
16
|
+
document.getElementById("page-view")
|
|
17
|
+
);
|
|
18
|
+
} else {
|
|
19
|
+
// When the user navigates to a new page.
|
|
20
|
+
const { Page, pageProps } = pageContext;
|
|
21
|
+
ReactDOM.render(
|
|
22
|
+
<PageWrapper pageContext={pageContext}>
|
|
23
|
+
<Page {...pageProps} />
|
|
24
|
+
</PageWrapper>,
|
|
25
|
+
document.getElementById("page-view")
|
|
26
|
+
);
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
|
|
30
|
+
ensureHydration: true,
|
|
31
|
+
|
|
32
|
+
prefetchLinks: true,
|
|
33
|
+
|
|
34
|
+
onTransitionStart() {
|
|
35
|
+
// Page transition started
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
onTransitionEnd() {
|
|
39
|
+
// Page transition ended
|
|
40
|
+
},
|
|
41
|
+
}).hydrationPromise.then(() => {
|
|
42
|
+
// Hydration finished; page is now interactive
|
|
43
|
+
});
|