@m2c2kit/cli 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/dist/cli.js +94 -0
- package/dist/templates/README.md.handlebars +15 -0
- package/dist/templates/index.html.handlebars +41 -0
- package/dist/templates/launch.json.handlebars +15 -0
- package/dist/templates/package.json.handlebars +21 -0
- package/dist/templates/rollup.config.js.handlebars +81 -0
- package/dist/templates/starter.ts.handlebars +99 -0
- package/dist/templates/tsconfig.json.handlebars +24 -0
- package/package.json +33 -0
package/dist/cli.js
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// https://github.com/yargs/yargs/issues/1854#issuecomment-792354121
|
|
3
|
+
import yargs from "yargs";
|
|
4
|
+
import { hideBin } from "yargs/helpers";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import handlebars from "handlebars";
|
|
8
|
+
import { dirname } from "path";
|
|
9
|
+
import { fileURLToPath } from "url";
|
|
10
|
+
import { spawn } from "child_process";
|
|
11
|
+
const packageHomeFolderPath = dirname(fileURLToPath(import.meta.url));
|
|
12
|
+
const yarg = yargs(hideBin(process.argv));
|
|
13
|
+
const argv = yarg
|
|
14
|
+
.command("new <name>", "create a new m2c2kit app", (yarg) => {
|
|
15
|
+
yarg.positional("name", {
|
|
16
|
+
describe: "name of new app",
|
|
17
|
+
type: "string",
|
|
18
|
+
});
|
|
19
|
+
}, (argv) => {
|
|
20
|
+
const appName = argv["name"];
|
|
21
|
+
const newFolderPath = path.join(path.resolve(), appName);
|
|
22
|
+
if (fs.existsSync(newFolderPath)) {
|
|
23
|
+
console.log(`error: folder ${newFolderPath} already exists. please remove this folder and try again.`);
|
|
24
|
+
yarg.exit(1, new Error("path exists"));
|
|
25
|
+
}
|
|
26
|
+
fs.mkdirSync(newFolderPath);
|
|
27
|
+
fs.mkdirSync(path.join(newFolderPath, "src"));
|
|
28
|
+
fs.mkdirSync(path.join(newFolderPath, ".vscode"));
|
|
29
|
+
function applyValuesToTemplate(templateFilePath, contents) {
|
|
30
|
+
const templateContents = fs.readFileSync(templateFilePath).toString();
|
|
31
|
+
const template = handlebars.compile(templateContents);
|
|
32
|
+
return template(contents);
|
|
33
|
+
}
|
|
34
|
+
const templateFolderPath = path.join(packageHomeFolderPath, "templates");
|
|
35
|
+
const templates = [
|
|
36
|
+
{
|
|
37
|
+
templateFilePath: path.join(templateFolderPath, "package.json.handlebars"),
|
|
38
|
+
destinationFilePath: path.join(newFolderPath, "package.json"),
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
templateFilePath: path.join(templateFolderPath, "rollup.config.js.handlebars"),
|
|
42
|
+
destinationFilePath: path.join(newFolderPath, "rollup.config.js"),
|
|
43
|
+
},
|
|
44
|
+
{
|
|
45
|
+
templateFilePath: path.join(templateFolderPath, "tsconfig.json.handlebars"),
|
|
46
|
+
destinationFilePath: path.join(newFolderPath, "tsconfig.json"),
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
templateFilePath: path.join(templateFolderPath, "README.md.handlebars"),
|
|
50
|
+
destinationFilePath: path.join(newFolderPath, "README.md"),
|
|
51
|
+
},
|
|
52
|
+
{
|
|
53
|
+
templateFilePath: path.join(templateFolderPath, "starter.ts.handlebars"),
|
|
54
|
+
destinationFilePath: path.join(newFolderPath, "src", `${appName}.ts`),
|
|
55
|
+
},
|
|
56
|
+
{
|
|
57
|
+
templateFilePath: path.join(templateFolderPath, "index.html.handlebars"),
|
|
58
|
+
destinationFilePath: path.join(newFolderPath, "src", "index.html"),
|
|
59
|
+
},
|
|
60
|
+
{
|
|
61
|
+
templateFilePath: path.join(templateFolderPath, "launch.json.handlebars"),
|
|
62
|
+
destinationFilePath: path.join(newFolderPath, ".vscode", "launch.json"),
|
|
63
|
+
},
|
|
64
|
+
];
|
|
65
|
+
templates.forEach((t) => {
|
|
66
|
+
const contents = applyValuesToTemplate(t.templateFilePath, {
|
|
67
|
+
appName: appName,
|
|
68
|
+
});
|
|
69
|
+
fs.writeFileSync(t.destinationFilePath, contents);
|
|
70
|
+
console.log(`CREATE ${t.destinationFilePath} (${contents.length} bytes)`);
|
|
71
|
+
});
|
|
72
|
+
let npm;
|
|
73
|
+
if (process.platform === "win32") {
|
|
74
|
+
npm = spawn(`npm`, ["install"], { shell: true, cwd: newFolderPath });
|
|
75
|
+
}
|
|
76
|
+
else {
|
|
77
|
+
npm = spawn(`npm`, ["install"], { cwd: newFolderPath });
|
|
78
|
+
}
|
|
79
|
+
npm.stdout.on("data", (data) => {
|
|
80
|
+
console.log(data.toString());
|
|
81
|
+
});
|
|
82
|
+
npm.stderr.on("data", (data) => {
|
|
83
|
+
console.error(data.toString());
|
|
84
|
+
});
|
|
85
|
+
npm.on("exit", (code) => {
|
|
86
|
+
if (code !== 0) {
|
|
87
|
+
console.log(`error: npm install exited with code ${code}`);
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
})
|
|
91
|
+
//.command("build", "compiles to output directory named dist/")
|
|
92
|
+
//.command("serve", "builds and serves app, rebuilding on files changes")
|
|
93
|
+
.demandCommand()
|
|
94
|
+
.showHelpOnFail(true).argv;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# {{appName}}
|
|
2
|
+
|
|
3
|
+
This project was generated with the m2c2kit CLI.
|
|
4
|
+
|
|
5
|
+
## Development server
|
|
6
|
+
|
|
7
|
+
Run `npm run serve` from the command line for a development server. Browse to `http://localhost:3000/`. The app will automatically compile and reload when you change source files.
|
|
8
|
+
|
|
9
|
+
## Debugging
|
|
10
|
+
|
|
11
|
+
With the file `.vscode/launch.json`, the project has been configured for debugging with Visual Studio Code and Chrome. If the development server is running, debugging in Visual Studio Code is available by pressing `F5` or selecting Run --> Start Debugging
|
|
12
|
+
|
|
13
|
+
## Build
|
|
14
|
+
|
|
15
|
+
Run `npm run build` from the command line to build the project. Build artifacts will be stored in the `dist/` directory.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<title>{{appName}}</title>
|
|
5
|
+
<style type="text/css">
|
|
6
|
+
body {
|
|
7
|
+
margin: 0;
|
|
8
|
+
}
|
|
9
|
+
</style>
|
|
10
|
+
<meta charset="UTF-8" />
|
|
11
|
+
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
12
|
+
</head>
|
|
13
|
+
|
|
14
|
+
<body style="background: white">
|
|
15
|
+
<div
|
|
16
|
+
style="
|
|
17
|
+
display: flex;
|
|
18
|
+
justify-content: center;
|
|
19
|
+
align-items: center;
|
|
20
|
+
height: 100vh;
|
|
21
|
+
width: 100vw;
|
|
22
|
+
"
|
|
23
|
+
>
|
|
24
|
+
<canvas style="height: 100vh; width: 100vw"></canvas>
|
|
25
|
+
<!-- If you don't want the game to start immediately, remove game.start()
|
|
26
|
+
from the code and call game.start() somehow else, such as with
|
|
27
|
+
the button shown below or a programmatic call -->
|
|
28
|
+
<!-- <button
|
|
29
|
+
style="position: absolute; bottom: 8px; left: 8px"
|
|
30
|
+
id="startButton"
|
|
31
|
+
onclick="{
|
|
32
|
+
document.getElementById('startButton').disabled = true;
|
|
33
|
+
window.game.start();
|
|
34
|
+
}"
|
|
35
|
+
>
|
|
36
|
+
Start
|
|
37
|
+
</button> -->
|
|
38
|
+
</div>
|
|
39
|
+
<script type="module" src="./{{appName}}.bundle.js"></script>
|
|
40
|
+
</body>
|
|
41
|
+
</html>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
{
|
|
2
|
+
// Use IntelliSense to learn about possible attributes.
|
|
3
|
+
// Hover to view descriptions of existing attributes.
|
|
4
|
+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
|
5
|
+
"version": "0.2.0",
|
|
6
|
+
"configurations": [
|
|
7
|
+
{
|
|
8
|
+
"type": "pwa-chrome",
|
|
9
|
+
"request": "launch",
|
|
10
|
+
"name": "Launch Chrome against localhost",
|
|
11
|
+
"url": "http://localhost:3000",
|
|
12
|
+
"webRoot": "${workspaceFolder}/build"
|
|
13
|
+
}
|
|
14
|
+
]
|
|
15
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "{{appName}}",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"scripts": {
|
|
5
|
+
"serve": "rollup -c --watch --configServe",
|
|
6
|
+
"build": "rollup -c --configProd"
|
|
7
|
+
},
|
|
8
|
+
"private": true,
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"@m2c2kit/core": "^0.1.0",
|
|
11
|
+
"typescript": "^4.5.2",
|
|
12
|
+
"rollup": "^2.60.2",
|
|
13
|
+
"@rollup/plugin-typescript": "^8.3.0",
|
|
14
|
+
"rollup-plugin-shim": "^1.0.0",
|
|
15
|
+
"@rollup/plugin-node-resolve": "^13.0.6",
|
|
16
|
+
"@rollup/plugin-commonjs": "^21.0.1",
|
|
17
|
+
"rollup-plugin-copy": "^3.4.0",
|
|
18
|
+
"rollup-plugin-serve": "^1.1.0",
|
|
19
|
+
"rollup-plugin-livereload": "^2.0.5"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
import typescript from "@rollup/plugin-typescript";
|
|
2
|
+
import shim from "rollup-plugin-shim";
|
|
3
|
+
import nodeResolve from "@rollup/plugin-node-resolve";
|
|
4
|
+
import commonjs from "@rollup/plugin-commonjs";
|
|
5
|
+
import copy from "rollup-plugin-copy";
|
|
6
|
+
import serve from "rollup-plugin-serve";
|
|
7
|
+
import livereload from "rollup-plugin-livereload";
|
|
8
|
+
|
|
9
|
+
let sharedPlugins = [
|
|
10
|
+
// canvaskit-wasm references these node.js functions
|
|
11
|
+
// shim them to empty functions for browser usage
|
|
12
|
+
shim({
|
|
13
|
+
fs: `export function fs_empty_shim() { }`,
|
|
14
|
+
path: `export function path_empty_shim() { }`,
|
|
15
|
+
}),
|
|
16
|
+
nodeResolve(),
|
|
17
|
+
commonjs({
|
|
18
|
+
include: "node_modules/canvaskit-wasm/**",
|
|
19
|
+
}),
|
|
20
|
+
];
|
|
21
|
+
|
|
22
|
+
export default (commandLineArgs) => {
|
|
23
|
+
|
|
24
|
+
let outputFolder = "build";
|
|
25
|
+
if (commandLineArgs.configProd) {
|
|
26
|
+
outputFolder = "dist"
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const finalConfig = [
|
|
30
|
+
{
|
|
31
|
+
input: "./src/{{appName}}.ts",
|
|
32
|
+
output: [
|
|
33
|
+
{
|
|
34
|
+
file: `./${outputFolder}/{{appName}}.bundle.js`,
|
|
35
|
+
format: "esm",
|
|
36
|
+
sourcemap: commandLineArgs.configServe && true,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
plugins: [
|
|
40
|
+
...sharedPlugins,
|
|
41
|
+
typescript({
|
|
42
|
+
inlineSourceMap: commandLineArgs.configServe && true,
|
|
43
|
+
inlineSources: commandLineArgs.configServe && true,
|
|
44
|
+
}),
|
|
45
|
+
copy({
|
|
46
|
+
targets: [
|
|
47
|
+
// copy the wasm bundle out of node_modules so it can be served
|
|
48
|
+
{
|
|
49
|
+
src: "node_modules/canvaskit-wasm/bin/canvaskit.wasm",
|
|
50
|
+
dest: outputFolder,
|
|
51
|
+
},
|
|
52
|
+
],
|
|
53
|
+
copyOnce: true,
|
|
54
|
+
hook: "writeBundle",
|
|
55
|
+
}),
|
|
56
|
+
copy({
|
|
57
|
+
targets: [
|
|
58
|
+
{
|
|
59
|
+
src: "src/index.html",
|
|
60
|
+
dest: outputFolder,
|
|
61
|
+
},
|
|
62
|
+
],
|
|
63
|
+
copyOnce: false,
|
|
64
|
+
hook: "writeBundle",
|
|
65
|
+
}),
|
|
66
|
+
commandLineArgs.configServe &&
|
|
67
|
+
serve({
|
|
68
|
+
open: false,
|
|
69
|
+
verbose: true,
|
|
70
|
+
contentBase: [`./${outputFolder}`],
|
|
71
|
+
historyApiFallback: true,
|
|
72
|
+
host: "localhost",
|
|
73
|
+
port: 3000,
|
|
74
|
+
}),
|
|
75
|
+
commandLineArgs.configServe &&
|
|
76
|
+
livereload(),
|
|
77
|
+
],
|
|
78
|
+
},
|
|
79
|
+
];
|
|
80
|
+
return finalConfig;
|
|
81
|
+
};
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WebColors,
|
|
3
|
+
Action,
|
|
4
|
+
Game,
|
|
5
|
+
Scene,
|
|
6
|
+
Rect,
|
|
7
|
+
Shape,
|
|
8
|
+
Sprite,
|
|
9
|
+
Point,
|
|
10
|
+
Label,
|
|
11
|
+
} from "@m2c2kit/core";
|
|
12
|
+
|
|
13
|
+
const game = new Game();
|
|
14
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
15
|
+
(window as unknown as any).game = game;
|
|
16
|
+
|
|
17
|
+
game
|
|
18
|
+
.init({
|
|
19
|
+
showFps: true,
|
|
20
|
+
// set this color so we can see the boundaries of the game
|
|
21
|
+
bodyBackgroundColor: WebColors.Wheat,
|
|
22
|
+
// note: using 2:1 aspect ratio, because that is closer to modern phones
|
|
23
|
+
width: 400,
|
|
24
|
+
height: 800,
|
|
25
|
+
// set stretch to true if you want to fill the screen
|
|
26
|
+
stretch: false,
|
|
27
|
+
fontUrls: [
|
|
28
|
+
"https://storage.googleapis.com/skia-cdn/google-web-fonts/Roboto-Regular.ttf",
|
|
29
|
+
],
|
|
30
|
+
// each svgImage below, you specify either a tag of an svg in the property "svgString" (as I do below)
|
|
31
|
+
// or you specify a URL to an svg in the property "url", such as url: 'https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/android.svg'
|
|
32
|
+
svgImages: [
|
|
33
|
+
{
|
|
34
|
+
name: "star",
|
|
35
|
+
height: 60,
|
|
36
|
+
width: 60,
|
|
37
|
+
svgString:
|
|
38
|
+
'<svg xmlns="http://www.w3.org/2000/svg" width="304" height="290"> <path d="M2,111 h300 l-242.7,176.3 92.7,-285.3 92.7,285.3 z" style="fill:#00FF00;stroke:#0000FF;stroke-width:15;stroke-linejoin:round"/></svg>',
|
|
39
|
+
},
|
|
40
|
+
],
|
|
41
|
+
})
|
|
42
|
+
.then(() => {
|
|
43
|
+
const s = new Scene({
|
|
44
|
+
backgroundColor: WebColors.SlateBlue,
|
|
45
|
+
name: "first-scene",
|
|
46
|
+
});
|
|
47
|
+
game.addScene(s);
|
|
48
|
+
|
|
49
|
+
const greeting = new Label({
|
|
50
|
+
text: "Hello, {{appName}}",
|
|
51
|
+
fontColor: WebColors.WhiteSmoke,
|
|
52
|
+
position: new Point(200, 200),
|
|
53
|
+
});
|
|
54
|
+
s.addChild(greeting);
|
|
55
|
+
|
|
56
|
+
const starImage = new Sprite({
|
|
57
|
+
imageName: "star",
|
|
58
|
+
position: new Point(200, 400),
|
|
59
|
+
});
|
|
60
|
+
s.addChild(starImage);
|
|
61
|
+
|
|
62
|
+
const rectangle = new Shape({
|
|
63
|
+
rect: new Rect({ width: 300, height: 50, x: 200, y: 700 }),
|
|
64
|
+
cornerRadius: 9,
|
|
65
|
+
fillColor: WebColors.RebeccaPurple,
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
const messageLabel = new Label({
|
|
69
|
+
text: "you tapped the bar!",
|
|
70
|
+
fontColor: WebColors.Yellow,
|
|
71
|
+
position: new Point(200, 600),
|
|
72
|
+
});
|
|
73
|
+
s.addChild(messageLabel);
|
|
74
|
+
messageLabel.hidden = true;
|
|
75
|
+
|
|
76
|
+
rectangle.isUserInteractionEnabled = true;
|
|
77
|
+
rectangle.onTap(() => {
|
|
78
|
+
console.log("you tapped it!");
|
|
79
|
+
rectangle.run(
|
|
80
|
+
Action.Sequence([
|
|
81
|
+
Action.Custom({
|
|
82
|
+
callback: () => {
|
|
83
|
+
messageLabel.hidden = false;
|
|
84
|
+
},
|
|
85
|
+
}),
|
|
86
|
+
Action.Wait({ duration: 500 }),
|
|
87
|
+
Action.Custom({
|
|
88
|
+
callback: () => {
|
|
89
|
+
messageLabel.hidden = true;
|
|
90
|
+
},
|
|
91
|
+
}),
|
|
92
|
+
])
|
|
93
|
+
);
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
s.addChild(rectangle);
|
|
97
|
+
|
|
98
|
+
game.start("first-scene");
|
|
99
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es6",
|
|
4
|
+
"lib": [
|
|
5
|
+
"es6",
|
|
6
|
+
"dom",
|
|
7
|
+
"dom.iterable"
|
|
8
|
+
],
|
|
9
|
+
"module": "es6",
|
|
10
|
+
"moduleResolution": "node",
|
|
11
|
+
"allowJs": true,
|
|
12
|
+
"esModuleInterop": true,
|
|
13
|
+
"forceConsistentCasingInFileNames": true,
|
|
14
|
+
"strict": true,
|
|
15
|
+
"skipLibCheck": true
|
|
16
|
+
},
|
|
17
|
+
"exclude": [
|
|
18
|
+
"node_modules",
|
|
19
|
+
"build",
|
|
20
|
+
"dist",
|
|
21
|
+
"**/{{appName}}.bundle.js",
|
|
22
|
+
"rollup.config.js"
|
|
23
|
+
]
|
|
24
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@m2c2kit/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "m2c2kit command line interface",
|
|
5
|
+
"module": "dist/cli.js",
|
|
6
|
+
"files": [
|
|
7
|
+
"dist"
|
|
8
|
+
],
|
|
9
|
+
"type": "module",
|
|
10
|
+
"bin": {
|
|
11
|
+
"m2": "./dist/cli.js"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "npm run clean && npm run compile && npm run copy-files",
|
|
15
|
+
"compile": "tsc",
|
|
16
|
+
"clean": "rimraf dist/ && rimraf build/",
|
|
17
|
+
"copy-files": "copyfiles -f build/src/cli.js dist && copyfiles templates/* dist/"
|
|
18
|
+
},
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "MIT",
|
|
21
|
+
"dependencies": {
|
|
22
|
+
"yargs": "^17.3.0",
|
|
23
|
+
"handlebars": "^4.7.7"
|
|
24
|
+
},
|
|
25
|
+
"devDependencies": {
|
|
26
|
+
"rimraf": "^3.0.2",
|
|
27
|
+
"typescript": "^4.5.2",
|
|
28
|
+
"copyfiles": "^2.4.1",
|
|
29
|
+
"yargs": "^17.3.0",
|
|
30
|
+
"@types/node": "^16.11.12",
|
|
31
|
+
"@types/yargs": "^17.0.7"
|
|
32
|
+
}
|
|
33
|
+
}
|