@puzzmo/cli 1.0.5 → 1.0.7
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/commands/game/create.js +27 -19
- package/lib/commands/game/create.js.map +1 -1
- package/lib/download/page-downloader.d.ts +5 -1
- package/lib/download/page-downloader.js +6 -0
- package/lib/download/page-downloader.js.map +1 -1
- package/package.json +1 -1
- package/src/commands/game/create.ts +30 -21
- package/src/download/page-downloader.ts +11 -2
|
@@ -10,11 +10,6 @@ import { login } from "../login.js";
|
|
|
10
10
|
const parseArgs = (args) => {
|
|
11
11
|
const opts = {};
|
|
12
12
|
let i = 0;
|
|
13
|
-
// First positional arg could be access token
|
|
14
|
-
if (args[0] && !args[0].startsWith("--")) {
|
|
15
|
-
opts.accessToken = args[0];
|
|
16
|
-
i = 1;
|
|
17
|
-
}
|
|
18
13
|
while (i < args.length) {
|
|
19
14
|
const arg = args[i];
|
|
20
15
|
if (arg === "--name" && args[i + 1]) {
|
|
@@ -26,6 +21,9 @@ const parseArgs = (args) => {
|
|
|
26
21
|
else if (arg === "--agent" && args[i + 1]) {
|
|
27
22
|
opts.agent = args[++i];
|
|
28
23
|
}
|
|
24
|
+
else if (arg === "--token" && args[i + 1]) {
|
|
25
|
+
opts.accessToken = args[++i];
|
|
26
|
+
}
|
|
29
27
|
else if (arg === "--pm" && args[i + 1]) {
|
|
30
28
|
opts.pm = args[++i];
|
|
31
29
|
}
|
|
@@ -64,17 +62,16 @@ const askSelect = async (message, options) => {
|
|
|
64
62
|
});
|
|
65
63
|
});
|
|
66
64
|
};
|
|
65
|
+
/** Converts a string to a URL-friendly slug */
|
|
66
|
+
const slugify = (str) => str
|
|
67
|
+
.toLowerCase()
|
|
68
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
69
|
+
.replace(/^-+|-+$/g, "");
|
|
67
70
|
/** Main game create wizard */
|
|
68
71
|
export const gameCreate = async (args) => {
|
|
69
72
|
const opts = parseArgs(args);
|
|
70
73
|
console.log("\n Puzzmo Game Creator\n");
|
|
71
|
-
// Step 1:
|
|
72
|
-
const name = opts.name || (await askText("Game name"));
|
|
73
|
-
if (!name) {
|
|
74
|
-
console.error("Game name is required");
|
|
75
|
-
process.exit(1);
|
|
76
|
-
}
|
|
77
|
-
// Step 2: Mode selection
|
|
74
|
+
// Step 1: Mode selection
|
|
78
75
|
const mode = await askSelect("How would you like to create your game?", [
|
|
79
76
|
{ value: "import", label: "Import an HTML game from a web page" },
|
|
80
77
|
{ value: "new-repo", label: "Create game in a new repo", disabled: true },
|
|
@@ -84,17 +81,28 @@ export const gameCreate = async (args) => {
|
|
|
84
81
|
console.log("This mode is not yet supported.");
|
|
85
82
|
process.exit(0);
|
|
86
83
|
}
|
|
87
|
-
// Step
|
|
84
|
+
// Step 2: Source URL
|
|
88
85
|
const url = opts.url || (await askText("Source URL to import"));
|
|
89
86
|
if (!url) {
|
|
90
87
|
console.error("Source URL is required for import mode");
|
|
91
88
|
process.exit(1);
|
|
92
89
|
}
|
|
93
|
-
// Step
|
|
94
|
-
const
|
|
95
|
-
console.log(`\nDownloading ${url}
|
|
96
|
-
await downloadPage(url,
|
|
90
|
+
// Step 3: Download page to a temp dir, extract title
|
|
91
|
+
const tmpDir = path.resolve(".puzzmo-import-tmp");
|
|
92
|
+
console.log(`\nDownloading ${url}...`);
|
|
93
|
+
const { title } = await downloadPage(url, tmpDir);
|
|
97
94
|
console.log("Download complete.");
|
|
95
|
+
// Step 4: Game name (default to HTML title if available)
|
|
96
|
+
const defaultName = opts.name || title;
|
|
97
|
+
const name = await askText("Game name", defaultName);
|
|
98
|
+
if (!name) {
|
|
99
|
+
console.error("Game name is required");
|
|
100
|
+
process.exit(1);
|
|
101
|
+
}
|
|
102
|
+
// Step 5: Move downloaded files to slugified directory
|
|
103
|
+
const slug = slugify(name);
|
|
104
|
+
const gameDir = path.resolve(slug);
|
|
105
|
+
fs.renameSync(tmpDir, gameDir);
|
|
98
106
|
// Step 5: Detect agents
|
|
99
107
|
const agents = detectAgent();
|
|
100
108
|
const agentChoices = [
|
|
@@ -138,9 +146,9 @@ export const gameCreate = async (args) => {
|
|
|
138
146
|
// Done
|
|
139
147
|
const pm = opts.pm || "npm";
|
|
140
148
|
const runCmd = pm === "npm" ? "npx" : pm === "yarn" ? "yarn dlx" : "pnpm dlx";
|
|
141
|
-
console.log(`\nDone! Your game is in ./${
|
|
149
|
+
console.log(`\nDone! Your game is in ./${slug}/`);
|
|
142
150
|
console.log(`\nNext steps:`);
|
|
143
|
-
console.log(` cd ${
|
|
151
|
+
console.log(` cd ${slug}`);
|
|
144
152
|
console.log(` ${runCmd} vite # Start development server`);
|
|
145
153
|
console.log(` ${runCmd} vite build # Build for production`);
|
|
146
154
|
if (selectedAgent === "none") {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/game/create.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,OAAO,EAAE,WAAW,EAAE,MAAM,8BAA8B,CAAA;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,mCAAmC,CAAA;AAChE,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAA;AAC1D,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAC7D,OAAO,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AACxD,OAAO,EAAE,KAAK,EAAE,MAAM,aAAa,CAAA;AAUnC,yCAAyC;AACzC,MAAM,SAAS,GAAG,CAAC,IAAc,EAAiB,EAAE;IAClD,MAAM,IAAI,GAAkB,EAAE,CAAA;IAC9B,IAAI,CAAC,GAAG,CAAC,CAAA;IAET,
|
|
1
|
+
{"version":3,"file":"create.js","sourceRoot":"","sources":["../../../src/commands/game/create.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,2 +1,6 @@
|
|
|
1
|
+
/** Extracts the <title> from HTML */
|
|
2
|
+
export declare const extractTitle: (html: string) => string | undefined;
|
|
1
3
|
/** Downloads an HTML page and its referenced assets into a src/ directory */
|
|
2
|
-
export declare const downloadPage: (url: string, outputDir: string) => Promise<
|
|
4
|
+
export declare const downloadPage: (url: string, outputDir: string) => Promise<{
|
|
5
|
+
title?: string;
|
|
6
|
+
}>;
|
|
@@ -28,6 +28,11 @@ const fetchPage = async (url) => {
|
|
|
28
28
|
req.on("error", reject);
|
|
29
29
|
});
|
|
30
30
|
};
|
|
31
|
+
/** Extracts the <title> from HTML */
|
|
32
|
+
export const extractTitle = (html) => {
|
|
33
|
+
const match = /<title[^>]*>([^<]+)<\/title>/i.exec(html);
|
|
34
|
+
return match?.[1]?.trim() || undefined;
|
|
35
|
+
};
|
|
31
36
|
/** Downloads an HTML page and its referenced assets into a src/ directory */
|
|
32
37
|
export const downloadPage = async (url, outputDir) => {
|
|
33
38
|
const srcDir = path.join(outputDir, "src");
|
|
@@ -72,6 +77,7 @@ export const downloadPage = async (url, outputDir) => {
|
|
|
72
77
|
// Write the HTML file
|
|
73
78
|
fs.writeFileSync(path.join(srcDir, "index.html"), html);
|
|
74
79
|
console.log(` Saved index.html + ${downloaded.size} asset(s) to ${path.relative(process.cwd(), srcDir)}/`);
|
|
80
|
+
return { title: extractTitle(html) };
|
|
75
81
|
};
|
|
76
82
|
/** Extracts asset references from HTML using regex */
|
|
77
83
|
const extractAssetRefs = (html) => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"page-downloader.js","sourceRoot":"","sources":["../../src/download/page-downloader.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,SAAS,CAAA;AACxB,OAAO,IAAI,MAAM,WAAW,CAAA;AAC5B,OAAO,KAAK,MAAM,YAAY,CAAA;AAC9B,OAAO,IAAI,MAAM,WAAW,CAAA;AAE5B,gEAAgE;AAChE,MAAM,SAAS,GAAG,KAAK,
|
|
1
|
+
{"version":3,"file":"page-downloader.js","sourceRoot":"","sources":["../../src/download/page-downloader.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -21,12 +21,6 @@ const parseArgs = (args: string[]): CreateOptions => {
|
|
|
21
21
|
const opts: CreateOptions = {}
|
|
22
22
|
let i = 0
|
|
23
23
|
|
|
24
|
-
// First positional arg could be access token
|
|
25
|
-
if (args[0] && !args[0].startsWith("--")) {
|
|
26
|
-
opts.accessToken = args[0]
|
|
27
|
-
i = 1
|
|
28
|
-
}
|
|
29
|
-
|
|
30
24
|
while (i < args.length) {
|
|
31
25
|
const arg = args[i]
|
|
32
26
|
if (arg === "--name" && args[i + 1]) {
|
|
@@ -35,6 +29,8 @@ const parseArgs = (args: string[]): CreateOptions => {
|
|
|
35
29
|
opts.url = args[++i]
|
|
36
30
|
} else if (arg === "--agent" && args[i + 1]) {
|
|
37
31
|
opts.agent = args[++i]
|
|
32
|
+
} else if (arg === "--token" && args[i + 1]) {
|
|
33
|
+
opts.accessToken = args[++i]
|
|
38
34
|
} else if (arg === "--pm" && args[i + 1]) {
|
|
39
35
|
opts.pm = args[++i]
|
|
40
36
|
}
|
|
@@ -80,20 +76,20 @@ const askSelect = async (message: string, options: { value: string; label: strin
|
|
|
80
76
|
})
|
|
81
77
|
}
|
|
82
78
|
|
|
79
|
+
/** Converts a string to a URL-friendly slug */
|
|
80
|
+
const slugify = (str: string): string =>
|
|
81
|
+
str
|
|
82
|
+
.toLowerCase()
|
|
83
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
84
|
+
.replace(/^-+|-+$/g, "")
|
|
85
|
+
|
|
83
86
|
/** Main game create wizard */
|
|
84
87
|
export const gameCreate = async (args: string[]) => {
|
|
85
88
|
const opts = parseArgs(args)
|
|
86
89
|
|
|
87
90
|
console.log("\n Puzzmo Game Creator\n")
|
|
88
91
|
|
|
89
|
-
// Step 1:
|
|
90
|
-
const name = opts.name || (await askText("Game name"))
|
|
91
|
-
if (!name) {
|
|
92
|
-
console.error("Game name is required")
|
|
93
|
-
process.exit(1)
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
// Step 2: Mode selection
|
|
92
|
+
// Step 1: Mode selection
|
|
97
93
|
const mode = await askSelect("How would you like to create your game?", [
|
|
98
94
|
{ value: "import", label: "Import an HTML game from a web page" },
|
|
99
95
|
{ value: "new-repo", label: "Create game in a new repo", disabled: true },
|
|
@@ -105,19 +101,32 @@ export const gameCreate = async (args: string[]) => {
|
|
|
105
101
|
process.exit(0)
|
|
106
102
|
}
|
|
107
103
|
|
|
108
|
-
// Step
|
|
104
|
+
// Step 2: Source URL
|
|
109
105
|
const url = opts.url || (await askText("Source URL to import"))
|
|
110
106
|
if (!url) {
|
|
111
107
|
console.error("Source URL is required for import mode")
|
|
112
108
|
process.exit(1)
|
|
113
109
|
}
|
|
114
110
|
|
|
115
|
-
// Step
|
|
116
|
-
const
|
|
117
|
-
console.log(`\nDownloading ${url}
|
|
118
|
-
await downloadPage(url,
|
|
111
|
+
// Step 3: Download page to a temp dir, extract title
|
|
112
|
+
const tmpDir = path.resolve(".puzzmo-import-tmp")
|
|
113
|
+
console.log(`\nDownloading ${url}...`)
|
|
114
|
+
const { title } = await downloadPage(url, tmpDir)
|
|
119
115
|
console.log("Download complete.")
|
|
120
116
|
|
|
117
|
+
// Step 4: Game name (default to HTML title if available)
|
|
118
|
+
const defaultName = opts.name || title
|
|
119
|
+
const name = await askText("Game name", defaultName)
|
|
120
|
+
if (!name) {
|
|
121
|
+
console.error("Game name is required")
|
|
122
|
+
process.exit(1)
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Step 5: Move downloaded files to slugified directory
|
|
126
|
+
const slug = slugify(name)
|
|
127
|
+
const gameDir = path.resolve(slug)
|
|
128
|
+
fs.renameSync(tmpDir, gameDir)
|
|
129
|
+
|
|
121
130
|
// Step 5: Detect agents
|
|
122
131
|
const agents = detectAgent()
|
|
123
132
|
const agentChoices = [
|
|
@@ -165,9 +174,9 @@ export const gameCreate = async (args: string[]) => {
|
|
|
165
174
|
// Done
|
|
166
175
|
const pm = opts.pm || "npm"
|
|
167
176
|
const runCmd = pm === "npm" ? "npx" : pm === "yarn" ? "yarn dlx" : "pnpm dlx"
|
|
168
|
-
console.log(`\nDone! Your game is in ./${
|
|
177
|
+
console.log(`\nDone! Your game is in ./${slug}/`)
|
|
169
178
|
console.log(`\nNext steps:`)
|
|
170
|
-
console.log(` cd ${
|
|
179
|
+
console.log(` cd ${slug}`)
|
|
171
180
|
console.log(` ${runCmd} vite # Start development server`)
|
|
172
181
|
console.log(` ${runCmd} vite build # Build for production`)
|
|
173
182
|
if (selectedAgent === "none") {
|
|
@@ -4,7 +4,9 @@ import https from "node:https"
|
|
|
4
4
|
import http from "node:http"
|
|
5
5
|
|
|
6
6
|
/** Fetch that tolerates expired/self-signed SSL certificates */
|
|
7
|
-
const fetchPage = async (
|
|
7
|
+
const fetchPage = async (
|
|
8
|
+
url: string,
|
|
9
|
+
): Promise<{ ok: boolean; status: number; text: () => Promise<string>; arrayBuffer: () => Promise<ArrayBuffer> }> => {
|
|
8
10
|
const parsed = new URL(url)
|
|
9
11
|
const isHttps = parsed.protocol === "https:"
|
|
10
12
|
|
|
@@ -32,8 +34,14 @@ const fetchPage = async (url: string): Promise<{ ok: boolean; status: number; te
|
|
|
32
34
|
})
|
|
33
35
|
}
|
|
34
36
|
|
|
37
|
+
/** Extracts the <title> from HTML */
|
|
38
|
+
export const extractTitle = (html: string): string | undefined => {
|
|
39
|
+
const match = /<title[^>]*>([^<]+)<\/title>/i.exec(html)
|
|
40
|
+
return match?.[1]?.trim() || undefined
|
|
41
|
+
}
|
|
42
|
+
|
|
35
43
|
/** Downloads an HTML page and its referenced assets into a src/ directory */
|
|
36
|
-
export const downloadPage = async (url: string, outputDir: string) => {
|
|
44
|
+
export const downloadPage = async (url: string, outputDir: string): Promise<{ title?: string }> => {
|
|
37
45
|
const srcDir = path.join(outputDir, "src")
|
|
38
46
|
fs.mkdirSync(srcDir, { recursive: true })
|
|
39
47
|
|
|
@@ -81,6 +89,7 @@ export const downloadPage = async (url: string, outputDir: string) => {
|
|
|
81
89
|
fs.writeFileSync(path.join(srcDir, "index.html"), html)
|
|
82
90
|
|
|
83
91
|
console.log(` Saved index.html + ${downloaded.size} asset(s) to ${path.relative(process.cwd(), srcDir)}/`)
|
|
92
|
+
return { title: extractTitle(html) }
|
|
84
93
|
}
|
|
85
94
|
|
|
86
95
|
/** Extracts asset references from HTML using regex */
|