create-spage 0.6.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.

Potentially problematic release.


This version of create-spage might be problematic. Click here for more details.

package/README.md ADDED
@@ -0,0 +1,130 @@
1
+
2
+ # create-spage
3
+
4
+ The official scaffolding CLI for creating an [spage](https://spage.me) project.
5
+
6
+ ## Usage
7
+
8
+ ```bash
9
+ # npm
10
+ npm create spage@latest my-blog
11
+
12
+ # bun
13
+ bun create spage@latest my-blog
14
+
15
+ # pnpm
16
+ pnpm create spage my-blog
17
+
18
+ # yarn
19
+ yarn create spage my-blog
20
+ ```
21
+
22
+ To initialize in the current directory:
23
+
24
+ ```bash
25
+ npm create spage@latest .
26
+ ```
27
+
28
+ The CLI prompts for project name, description, author, site URL, and timezone — then generates everything you need.
29
+
30
+ ## What Gets Generated
31
+
32
+ ```
33
+ my-blog/
34
+ ├── posts/
35
+ │ ├── hello-world.md # Sample welcome post
36
+ │ └── about.md # Sample about page
37
+ ├── albums/
38
+ │ └── blog/ # Sample album directory
39
+ ├── public/
40
+ │ ├── logo.png
41
+ │ ├── logomax.png
42
+ │ ├── favicon.ico
43
+ │ └── _redirects
44
+ ├── config.json # Site configuration (with your answers filled in)
45
+ ├── album.config.json # Album configuration
46
+ ├── memo.config.json # Memo module configuration (Ech0 integration, disabled by default)
47
+ ├── package.json # { "dev": "spage serve", "build": "spage build" }
48
+ └── .gitignore
49
+ ```
50
+
51
+ ### Generated `package.json`
52
+
53
+ ```json
54
+ {
55
+ "name": "my-blog",
56
+ "private": true,
57
+ "type": "module",
58
+ "scripts": {
59
+ "dev": "spage serve",
60
+ "build": "spage build"
61
+ },
62
+ "dependencies": {
63
+ "@s-page/core": "^0.6.0",
64
+ "@s-page/engine": "^0.6.0"
65
+ }
66
+ }
67
+ ```
68
+
69
+ ## After Scaffolding
70
+
71
+ ```bash
72
+ cd my-blog
73
+ npm install
74
+ npm run dev # Start development server (localhost:3000)
75
+ npm run build # Build for production → dist/
76
+ ```
77
+
78
+ ## Configuration
79
+
80
+ ### `config.json`
81
+
82
+ | Field | Required | Description |
83
+ |-------|----------|-------------|
84
+ | `title` | Yes | Site title |
85
+ | `description` | Yes | Site description |
86
+ | `logo` | Yes | Logo image path |
87
+ | `favicon` | Yes | Favicon path |
88
+ | `siteUrl` | No | Production URL (enables SEO features) |
89
+ | `author` | No | Author name |
90
+ | `language` | No | Default language (`en`, `zh-CN`, `ja`) |
91
+ | `timezone` | No | IANA timezone for correct post dates |
92
+ | `basePath` | No | Sub-directory path (e.g., `/blog`) |
93
+ | `github` | No | GitHub URL (shows icon in top-right) |
94
+
95
+ ### `album.config.json`
96
+
97
+ ```json
98
+ {
99
+ "enabled": true,
100
+ "albums": [
101
+ { "dir": "blog", "name": "Blog Photos" }
102
+ ]
103
+ }
104
+ ```
105
+
106
+ ### `memo.config.json`
107
+
108
+ Enables the Memo module powered by [Ech0](https://github.com/lin-snow/ech0). Disabled by default.
109
+
110
+ ```json
111
+ {
112
+ "enabled": true,
113
+ "provider": "ech0",
114
+ "serverUrl": "https://your-ech0-instance.com",
115
+ "pageSize": 20,
116
+ "title": "Memo"
117
+ }
118
+ ```
119
+
120
+ | Field | Required | Description |
121
+ |-------|----------|-------------|
122
+ | `enabled` | Yes | Toggle the memo module on/off |
123
+ | `provider` | Yes | Data provider (currently only `"ech0"`) |
124
+ | `serverUrl` | Yes | Ech0 instance URL |
125
+ | `pageSize` | No | Memos per load (default: 20) |
126
+ | `title` | No | Custom page title (falls back to i18n default) |
127
+
128
+ ## License
129
+
130
+ MIT © Suzichen
package/dist/args.d.ts ADDED
@@ -0,0 +1,15 @@
1
+ export interface CliArgs {
2
+ name?: string;
3
+ description?: string;
4
+ author?: string;
5
+ siteUrl?: string;
6
+ timezone?: string;
7
+ pm?: 'npm' | 'yarn' | 'pnpm' | 'bun';
8
+ 'skip-install'?: boolean;
9
+ yes?: boolean;
10
+ help?: boolean;
11
+ version?: boolean;
12
+ }
13
+ export declare function parseArgs(argv?: string[]): CliArgs;
14
+ export declare function printHelp(): void;
15
+ export declare function printVersion(): void;
package/dist/args.js ADDED
@@ -0,0 +1,64 @@
1
+ import minimist from 'minimist';
2
+ import { readFileSync } from 'node:fs';
3
+ import { fileURLToPath } from 'node:url';
4
+ import path from 'node:path';
5
+ const HELP_TEXT = `
6
+ Usage: create-spage [options]
7
+
8
+ Options:
9
+ --name <name> Project name (default: my-blog)
10
+ --description <desc> Project description (default: A blog powered by spage)
11
+ --author <author> Author name (default: "")
12
+ --siteUrl <url> Site URL for SEO (default: "")
13
+ --timezone <tz> IANA timezone identifier (default: system timezone)
14
+ --pm <npm|yarn|pnpm|bun> Package manager (default: npm)
15
+ --skip-install Skip dependency installation
16
+ --yes, -y Skip prompts and use default values
17
+ --help Show this help message
18
+ --version Show version number
19
+ `;
20
+ export function parseArgs(argv = process.argv.slice(2)) {
21
+ const args = minimist(argv, {
22
+ string: ['name', 'description', 'author', 'siteUrl', 'timezone', 'pm'],
23
+ boolean: ['skip-install', 'yes', 'help', 'version'],
24
+ alias: {
25
+ y: 'yes',
26
+ h: 'help',
27
+ v: 'version',
28
+ },
29
+ });
30
+ return {
31
+ name: args._[0] || args.name || undefined,
32
+ description: args.description || undefined,
33
+ author: args.author !== undefined ? args.author : undefined,
34
+ siteUrl: args.siteUrl !== undefined ? args.siteUrl : undefined,
35
+ timezone: args.timezone !== undefined ? args.timezone : undefined,
36
+ pm: validatePm(args.pm),
37
+ 'skip-install': args['skip-install'] || false,
38
+ yes: args.yes || false,
39
+ help: args.help || false,
40
+ version: args.version || false,
41
+ };
42
+ }
43
+ function validatePm(pm) {
44
+ if (pm === 'npm' || pm === 'yarn' || pm === 'pnpm' || pm === 'bun')
45
+ return pm;
46
+ if (pm) {
47
+ console.warn(`Warning: Invalid package manager "${pm}", will use npm as default.`);
48
+ }
49
+ return undefined;
50
+ }
51
+ export function printHelp() {
52
+ console.log(HELP_TEXT);
53
+ }
54
+ export function printVersion() {
55
+ try {
56
+ const __dirname = path.dirname(fileURLToPath(import.meta.url));
57
+ const pkg = JSON.parse(readFileSync(path.resolve(__dirname, '../package.json'), 'utf-8'));
58
+ console.log(`create-spage v${pkg.version}`);
59
+ }
60
+ catch {
61
+ console.log('create-spage v0.6.0');
62
+ }
63
+ }
64
+ //# sourceMappingURL=args.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"args.js","sourceRoot":"","sources":["../src/args.ts"],"names":[],"mappings":"AAAA,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAe7B,MAAM,SAAS,GAAG;;;;;;;;;;;;;;CAcjB,CAAC;AAEF,MAAM,UAAU,SAAS,CAAC,OAAiB,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;IAC9D,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE;QAC1B,MAAM,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,QAAQ,EAAE,SAAS,EAAE,UAAU,EAAE,IAAI,CAAC;QACtE,OAAO,EAAE,CAAC,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,CAAC;QACnD,KAAK,EAAE;YACL,CAAC,EAAE,KAAK;YACR,CAAC,EAAE,MAAM;YACT,CAAC,EAAE,SAAS;SACb;KACF,CAAC,CAAC;IAEH,OAAO;QACL,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,IAAI,IAAI,SAAS;QACzC,WAAW,EAAE,IAAI,CAAC,WAAW,IAAI,SAAS;QAC1C,MAAM,EAAE,IAAI,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC3D,OAAO,EAAE,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS;QAC9D,QAAQ,EAAE,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,SAAS;QACjE,EAAE,EAAE,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvB,cAAc,EAAE,IAAI,CAAC,cAAc,CAAC,IAAI,KAAK;QAC7C,GAAG,EAAE,IAAI,CAAC,GAAG,IAAI,KAAK;QACtB,IAAI,EAAE,IAAI,CAAC,IAAI,IAAI,KAAK;QACxB,OAAO,EAAE,IAAI,CAAC,OAAO,IAAI,KAAK;KAC/B,CAAC;AACJ,CAAC;AAED,SAAS,UAAU,CAAC,EAAW;IAC7B,IAAI,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,MAAM,IAAI,EAAE,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IAC9E,IAAI,EAAE,EAAE,CAAC;QACP,OAAO,CAAC,IAAI,CAAC,qCAAqC,EAAE,6BAA6B,CAAC,CAAC;IACrF,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,SAAS;IACvB,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC;QACH,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/D,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,iBAAiB,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;QAC1F,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;IACrC,CAAC;AACH,CAAC"}
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
package/dist/index.js ADDED
@@ -0,0 +1,83 @@
1
+ #!/usr/bin/env node
2
+ import path from 'node:path';
3
+ import { parseArgs, printHelp, printVersion } from './args.js';
4
+ import { collectUserInput } from './prompts.js';
5
+ import { copyTemplate, cleanup } from './scaffold.js';
6
+ import { installDependencies } from './install.js';
7
+ import { printBanner, printSuccess, printErrorDirectoryExists, printErrorCopyFailed, printErrorInstallFailed, printCancelled, } from './messages.js';
8
+ let targetDir = null;
9
+ let shouldCleanup = false;
10
+ // Register cleanup handler for SIGINT (Ctrl+C)
11
+ process.on('SIGINT', () => {
12
+ if (shouldCleanup && targetDir) {
13
+ cleanup(targetDir);
14
+ printCancelled();
15
+ }
16
+ process.exit(1);
17
+ });
18
+ async function main() {
19
+ // Parse command-line arguments
20
+ const args = parseArgs();
21
+ if (args.help) {
22
+ printHelp();
23
+ return;
24
+ }
25
+ if (args.version) {
26
+ printVersion();
27
+ return;
28
+ }
29
+ printBanner();
30
+ // Collect user input (interactive prompts for missing fields)
31
+ let userInput;
32
+ try {
33
+ userInput = await collectUserInput(args);
34
+ }
35
+ catch (err) {
36
+ if (err instanceof Error && err.message === 'USER_CANCELLED') {
37
+ console.log('\n Operation cancelled.');
38
+ return;
39
+ }
40
+ throw err;
41
+ }
42
+ // Set target directory
43
+ targetDir = path.resolve(process.cwd(), userInput.name);
44
+ shouldCleanup = true;
45
+ // Copy template files
46
+ try {
47
+ await copyTemplate(targetDir, userInput);
48
+ }
49
+ catch (err) {
50
+ if (err instanceof Error) {
51
+ if (err.message.startsWith('DIRECTORY_EXISTS:')) {
52
+ const dirName = err.message.split(':')[1];
53
+ printErrorDirectoryExists(dirName);
54
+ return;
55
+ }
56
+ if (err.message === 'COPY_FAILED') {
57
+ printErrorCopyFailed();
58
+ return;
59
+ }
60
+ }
61
+ throw err;
62
+ }
63
+ // Install dependencies
64
+ if (!userInput.skipInstall) {
65
+ try {
66
+ await installDependencies(targetDir, userInput.packageManager);
67
+ }
68
+ catch {
69
+ printErrorInstallFailed(userInput.name, userInput.packageManager);
70
+ // Don't exit — project files were created successfully
71
+ }
72
+ }
73
+ shouldCleanup = false;
74
+ printSuccess(userInput);
75
+ }
76
+ main().catch((err) => {
77
+ console.error(err);
78
+ if (shouldCleanup && targetDir) {
79
+ cleanup(targetDir);
80
+ }
81
+ process.exit(1);
82
+ });
83
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Install dependencies in the target directory using the specified package manager.
3
+ */
4
+ export declare function installDependencies(targetDir: string, pm: 'npm' | 'yarn' | 'pnpm' | 'bun'): Promise<void>;
@@ -0,0 +1,27 @@
1
+ import { spawn } from 'node:child_process';
2
+ /**
3
+ * Install dependencies in the target directory using the specified package manager.
4
+ */
5
+ export function installDependencies(targetDir, pm) {
6
+ return new Promise((resolve, reject) => {
7
+ const command = pm;
8
+ const args = ['install'];
9
+ const child = spawn(command, args, {
10
+ cwd: targetDir,
11
+ stdio: 'inherit',
12
+ shell: true,
13
+ });
14
+ child.on('close', (code) => {
15
+ if (code === 0) {
16
+ resolve();
17
+ }
18
+ else {
19
+ reject(new Error(`INSTALL_FAILED:${pm}`));
20
+ }
21
+ });
22
+ child.on('error', () => {
23
+ reject(new Error(`INSTALL_FAILED:${pm}`));
24
+ });
25
+ });
26
+ }
27
+ //# sourceMappingURL=install.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"install.js","sourceRoot":"","sources":["../src/install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAE3C;;GAEG;AACH,MAAM,UAAU,mBAAmB,CACjC,SAAiB,EACjB,EAAmC;IAEnC,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,EAAE,CAAC;QACnB,MAAM,IAAI,GAAG,CAAC,SAAS,CAAC,CAAC;QAEzB,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,EAAE,IAAI,EAAE;YACjC,GAAG,EAAE,SAAS;YACd,KAAK,EAAE,SAAS;YAChB,KAAK,EAAE,IAAI;SACZ,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;YACzB,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;gBACf,OAAO,EAAE,CAAC;YACZ,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;YAC5C,CAAC;QACH,CAAC,CAAC,CAAC;QAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACrB,MAAM,CAAC,IAAI,KAAK,CAAC,kBAAkB,EAAE,EAAE,CAAC,CAAC,CAAC;QAC5C,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { UserInput } from './prompts.js';
2
+ export declare function printSuccess(input: UserInput): void;
3
+ export declare function printErrorDirectoryExists(name: string): void;
4
+ export declare function printErrorCopyFailed(): void;
5
+ export declare function printErrorInstallFailed(name: string, pm: string): void;
6
+ export declare function printCancelled(): void;
7
+ export declare function printBanner(): void;
@@ -0,0 +1,51 @@
1
+ import { green, cyan, red, yellow, bold, dim } from 'kolorist';
2
+ export function printSuccess(input) {
3
+ console.log();
4
+ console.log(` ${bold(green('✔'))} ${bold('Project created successfully!')}`);
5
+ console.log();
6
+ console.log(` ${dim('Next steps:')}`);
7
+ console.log();
8
+ console.log(` ${cyan('cd')} ${input.name}`);
9
+ console.log(` ${cyan(`${input.packageManager} run dev`)}`);
10
+ console.log();
11
+ console.log(` ${dim('Build for production:')}`);
12
+ console.log(` ${cyan(`${input.packageManager} run build`)}`);
13
+ console.log();
14
+ console.log(` ${dim('Update framework:')}`);
15
+ console.log(` ${cyan(`${input.packageManager === 'yarn' ? 'yarn upgrade' : input.packageManager + ' update'} @s-blog/core @s-blog/engine`)}`);
16
+ console.log();
17
+ console.log(` ${dim('Happy blogging! 🎉')}`);
18
+ console.log();
19
+ }
20
+ export function printErrorDirectoryExists(name) {
21
+ console.error();
22
+ console.error(` ${red('✖')} ${bold('Error')}: Directory "${yellow(name)}" already exists.`);
23
+ console.error(` Please choose another name or delete the directory and try again.`);
24
+ console.error();
25
+ }
26
+ export function printErrorCopyFailed() {
27
+ console.error();
28
+ console.error(` ${red('✖')} ${bold('Error')}: Failed to copy template files.`);
29
+ console.error(` Cleaned up temporary files. Please check disk space and permissions, then try again.`);
30
+ console.error();
31
+ }
32
+ export function printErrorInstallFailed(name, pm) {
33
+ console.error();
34
+ console.error(` ${yellow('⚠')} ${bold('Warning')}: Dependency installation failed.`);
35
+ console.error(` Your project was created, but you need to install dependencies manually:`);
36
+ console.error();
37
+ console.error(` ${cyan('cd')} ${name}`);
38
+ console.error(` ${cyan(`${pm} install`)}`);
39
+ console.error();
40
+ }
41
+ export function printCancelled() {
42
+ console.log();
43
+ console.log(` ${yellow('✖')} Initialization cancelled. Cleaned up temporary files.`);
44
+ console.log();
45
+ }
46
+ export function printBanner() {
47
+ console.log();
48
+ console.log(` ${bold(cyan('create-s-blog'))} ${dim('- Scaffold a new spage project')}`);
49
+ console.log();
50
+ }
51
+ //# sourceMappingURL=messages.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"messages.js","sourceRoot":"","sources":["../src/messages.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { CliArgs } from './args.js';
2
+ export interface UserInput {
3
+ name: string;
4
+ description: string;
5
+ author: string;
6
+ siteUrl: string;
7
+ timezone?: string;
8
+ packageManager: 'npm' | 'yarn' | 'pnpm' | 'bun';
9
+ skipInstall: boolean;
10
+ }
11
+ export declare function collectUserInput(args: CliArgs): Promise<UserInput>;
@@ -0,0 +1,119 @@
1
+ import prompts from 'prompts';
2
+ export async function collectUserInput(args) {
3
+ const systemTimezone = Intl.DateTimeFormat().resolvedOptions().timeZone;
4
+ if (args.yes) {
5
+ return {
6
+ name: args.name || 'my-blog',
7
+ description: args.description || 'A blog powered by spage',
8
+ author: args.author !== undefined ? args.author : '',
9
+ siteUrl: args.siteUrl || '',
10
+ timezone: args.timezone || systemTimezone || undefined,
11
+ packageManager: args.pm || 'npm',
12
+ skipInstall: args['skip-install'] || false,
13
+ };
14
+ }
15
+ const questions = [];
16
+ if (!args.name) {
17
+ questions.push({
18
+ type: 'text',
19
+ name: 'name',
20
+ message: 'Project name:',
21
+ initial: 'my-blog',
22
+ });
23
+ }
24
+ if (!args.description) {
25
+ questions.push({
26
+ type: 'text',
27
+ name: 'description',
28
+ message: 'Project description:',
29
+ initial: 'A blog powered by spage',
30
+ });
31
+ }
32
+ if (args.author === undefined) {
33
+ questions.push({
34
+ type: 'text',
35
+ name: 'author',
36
+ message: 'Author name:',
37
+ initial: '',
38
+ });
39
+ }
40
+ if (args.siteUrl === undefined) {
41
+ // siteUrl for SEO (sitemap, rss, og tags)
42
+ questions.push({
43
+ type: 'text',
44
+ name: 'siteUrl',
45
+ message: 'Site URL (for SEO, leave empty to skip):',
46
+ initial: '',
47
+ });
48
+ }
49
+ if (args.timezone === undefined) {
50
+ if (systemTimezone) {
51
+ questions.push({
52
+ type: 'confirm',
53
+ name: 'useSystemTimezone',
54
+ message: `Detected system timezone: ${systemTimezone}. Use this for your blog?`,
55
+ initial: true,
56
+ });
57
+ questions.push({
58
+ type: prev => prev ? null : 'text',
59
+ name: 'customTimezone',
60
+ message: 'Enter IANA timezone identifier (leave empty to skip):',
61
+ initial: '',
62
+ });
63
+ }
64
+ else {
65
+ questions.push({
66
+ type: 'text',
67
+ name: 'customTimezone',
68
+ message: 'Enter IANA timezone identifier (leave empty to skip):',
69
+ initial: '',
70
+ });
71
+ }
72
+ }
73
+ if (!args.pm) {
74
+ questions.push({
75
+ type: 'select',
76
+ name: 'packageManager',
77
+ message: 'Package manager:',
78
+ choices: [
79
+ { title: 'npm', value: 'npm' },
80
+ { title: 'yarn', value: 'yarn' },
81
+ { title: 'pnpm', value: 'pnpm' },
82
+ { title: 'bun', value: 'bun' },
83
+ ],
84
+ initial: 0,
85
+ });
86
+ }
87
+ let cancelled = false;
88
+ // If there are no questions to ask, we can skip prompts
89
+ let response = {};
90
+ if (questions.length > 0) {
91
+ response = await prompts(questions, {
92
+ onCancel: () => {
93
+ cancelled = true;
94
+ },
95
+ });
96
+ if (cancelled) {
97
+ throw new Error('USER_CANCELLED');
98
+ }
99
+ }
100
+ let timezone = args.timezone;
101
+ if (args.timezone === undefined) {
102
+ if (response.useSystemTimezone) {
103
+ timezone = systemTimezone;
104
+ }
105
+ else if (response.customTimezone && response.customTimezone.trim() !== '') {
106
+ timezone = response.customTimezone.trim();
107
+ }
108
+ }
109
+ return {
110
+ name: args.name || response.name || 'my-blog',
111
+ description: args.description || response.description || 'A blog powered by spage',
112
+ author: args.author !== undefined ? args.author : (response.author || ''),
113
+ siteUrl: args.siteUrl !== undefined ? args.siteUrl : (response.siteUrl || ''),
114
+ timezone: timezone,
115
+ packageManager: args.pm || response.packageManager || 'npm',
116
+ skipInstall: args['skip-install'] || false,
117
+ };
118
+ }
119
+ //# sourceMappingURL=prompts.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompts.js","sourceRoot":"","sources":["../src/prompts.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import type { UserInput } from './prompts.js';
2
+ /**
3
+ * Copy template files to the target directory and generate customized files.
4
+ * Delegates to the Rust scaffold engine via NAPI.
5
+ */
6
+ export declare function copyTemplate(targetDir: string, input: UserInput): Promise<void>;
7
+ /**
8
+ * Remove the target directory and all its contents.
9
+ */
10
+ export declare function cleanup(targetDir: string): void;
@@ -0,0 +1,35 @@
1
+ import { createRequire } from 'node:module';
2
+ const require = createRequire(import.meta.url);
3
+ const { scaffoldBlog, cleanupBlog } = require('../index.cjs');
4
+ /**
5
+ * Copy template files to the target directory and generate customized files.
6
+ * Delegates to the Rust scaffold engine via NAPI.
7
+ */
8
+ export async function copyTemplate(targetDir, input) {
9
+ try {
10
+ scaffoldBlog({
11
+ targetDir,
12
+ name: input.name,
13
+ description: input.description,
14
+ author: input.author,
15
+ siteUrl: input.siteUrl || undefined,
16
+ timezone: input.timezone || undefined,
17
+ });
18
+ }
19
+ catch (err) {
20
+ const msg = err instanceof Error ? err.message : String(err);
21
+ if (msg.includes('Target directory already exists')) {
22
+ throw new Error(`DIRECTORY_EXISTS:${targetDir.split(/[/\\]/).pop()}`);
23
+ }
24
+ // Attempt cleanup on any other error
25
+ cleanup(targetDir);
26
+ throw new Error('COPY_FAILED');
27
+ }
28
+ }
29
+ /**
30
+ * Remove the target directory and all its contents.
31
+ */
32
+ export function cleanup(targetDir) {
33
+ cleanupBlog(targetDir);
34
+ }
35
+ //# sourceMappingURL=scaffold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scaffold.js","sourceRoot":"","sources":["../src/scaffold.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,MAAM,OAAO,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC/C,MAAM,EAAE,YAAY,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;AAE9D;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB,EAAE,KAAgB;IACpE,IAAI,CAAC;QACH,YAAY,CAAC;YACX,SAAS;YACT,IAAI,EAAE,KAAK,CAAC,IAAI;YAChB,WAAW,EAAE,KAAK,CAAC,WAAW;YAC9B,MAAM,EAAE,KAAK,CAAC,MAAM;YACpB,OAAO,EAAE,KAAK,CAAC,OAAO,IAAI,SAAS;YACnC,QAAQ,EAAE,KAAK,CAAC,QAAQ,IAAI,SAAS;SACtC,CAAC,CAAC;IACL,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,GAAG,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QAC7D,IAAI,GAAG,CAAC,QAAQ,CAAC,iCAAiC,CAAC,EAAE,CAAC;YACpD,MAAM,IAAI,KAAK,CAAC,oBAAoB,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,qCAAqC;QACrC,OAAO,CAAC,SAAS,CAAC,CAAC;QACnB,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,OAAO,CAAC,SAAiB;IACvC,WAAW,CAAC,SAAS,CAAC,CAAC;AACzB,CAAC"}
package/index.cjs ADDED
@@ -0,0 +1,316 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+ /* prettier-ignore */
4
+
5
+ /* auto-generated by NAPI-RS */
6
+
7
+ const { existsSync, readFileSync } = require('fs')
8
+ const { join } = require('path')
9
+
10
+ const { platform, arch } = process
11
+
12
+ let nativeBinding = null
13
+ let localFileExisted = false
14
+ let loadError = null
15
+
16
+ function isMusl() {
17
+ // For Node 10
18
+ if (!process.report || typeof process.report.getReport !== 'function') {
19
+ try {
20
+ const lddPath = require('child_process').execSync('which ldd').toString().trim()
21
+ return readFileSync(lddPath, 'utf8').includes('musl')
22
+ } catch (e) {
23
+ return true
24
+ }
25
+ } else {
26
+ const { glibcVersionRuntime } = process.report.getReport().header
27
+ return !glibcVersionRuntime
28
+ }
29
+ }
30
+
31
+ switch (platform) {
32
+ case 'android':
33
+ switch (arch) {
34
+ case 'arm64':
35
+ localFileExisted = existsSync(join(__dirname, 'create-s-blog.android-arm64.node'))
36
+ try {
37
+ if (localFileExisted) {
38
+ nativeBinding = require('./create-s-blog.android-arm64.node')
39
+ } else {
40
+ nativeBinding = require('create-s-blog-android-arm64')
41
+ }
42
+ } catch (e) {
43
+ loadError = e
44
+ }
45
+ break
46
+ case 'arm':
47
+ localFileExisted = existsSync(join(__dirname, 'create-s-blog.android-arm-eabi.node'))
48
+ try {
49
+ if (localFileExisted) {
50
+ nativeBinding = require('./create-s-blog.android-arm-eabi.node')
51
+ } else {
52
+ nativeBinding = require('create-s-blog-android-arm-eabi')
53
+ }
54
+ } catch (e) {
55
+ loadError = e
56
+ }
57
+ break
58
+ default:
59
+ throw new Error(`Unsupported architecture on Android ${arch}`)
60
+ }
61
+ break
62
+ case 'win32':
63
+ switch (arch) {
64
+ case 'x64':
65
+ localFileExisted = existsSync(
66
+ join(__dirname, 'create-s-blog.win32-x64-msvc.node')
67
+ )
68
+ try {
69
+ if (localFileExisted) {
70
+ nativeBinding = require('./create-s-blog.win32-x64-msvc.node')
71
+ } else {
72
+ nativeBinding = require('create-s-blog-win32-x64-msvc')
73
+ }
74
+ } catch (e) {
75
+ loadError = e
76
+ }
77
+ break
78
+ case 'ia32':
79
+ localFileExisted = existsSync(
80
+ join(__dirname, 'create-s-blog.win32-ia32-msvc.node')
81
+ )
82
+ try {
83
+ if (localFileExisted) {
84
+ nativeBinding = require('./create-s-blog.win32-ia32-msvc.node')
85
+ } else {
86
+ nativeBinding = require('create-s-blog-win32-ia32-msvc')
87
+ }
88
+ } catch (e) {
89
+ loadError = e
90
+ }
91
+ break
92
+ case 'arm64':
93
+ localFileExisted = existsSync(
94
+ join(__dirname, 'create-s-blog.win32-arm64-msvc.node')
95
+ )
96
+ try {
97
+ if (localFileExisted) {
98
+ nativeBinding = require('./create-s-blog.win32-arm64-msvc.node')
99
+ } else {
100
+ nativeBinding = require('create-s-blog-win32-arm64-msvc')
101
+ }
102
+ } catch (e) {
103
+ loadError = e
104
+ }
105
+ break
106
+ default:
107
+ throw new Error(`Unsupported architecture on Windows: ${arch}`)
108
+ }
109
+ break
110
+ case 'darwin':
111
+ localFileExisted = existsSync(join(__dirname, 'create-s-blog.darwin-universal.node'))
112
+ try {
113
+ if (localFileExisted) {
114
+ nativeBinding = require('./create-s-blog.darwin-universal.node')
115
+ } else {
116
+ nativeBinding = require('create-s-blog-darwin-universal')
117
+ }
118
+ break
119
+ } catch {}
120
+ switch (arch) {
121
+ case 'x64':
122
+ localFileExisted = existsSync(join(__dirname, 'create-s-blog.darwin-x64.node'))
123
+ try {
124
+ if (localFileExisted) {
125
+ nativeBinding = require('./create-s-blog.darwin-x64.node')
126
+ } else {
127
+ nativeBinding = require('create-s-blog-darwin-x64')
128
+ }
129
+ } catch (e) {
130
+ loadError = e
131
+ }
132
+ break
133
+ case 'arm64':
134
+ localFileExisted = existsSync(
135
+ join(__dirname, 'create-s-blog.darwin-arm64.node')
136
+ )
137
+ try {
138
+ if (localFileExisted) {
139
+ nativeBinding = require('./create-s-blog.darwin-arm64.node')
140
+ } else {
141
+ nativeBinding = require('create-s-blog-darwin-arm64')
142
+ }
143
+ } catch (e) {
144
+ loadError = e
145
+ }
146
+ break
147
+ default:
148
+ throw new Error(`Unsupported architecture on macOS: ${arch}`)
149
+ }
150
+ break
151
+ case 'freebsd':
152
+ if (arch !== 'x64') {
153
+ throw new Error(`Unsupported architecture on FreeBSD: ${arch}`)
154
+ }
155
+ localFileExisted = existsSync(join(__dirname, 'create-s-blog.freebsd-x64.node'))
156
+ try {
157
+ if (localFileExisted) {
158
+ nativeBinding = require('./create-s-blog.freebsd-x64.node')
159
+ } else {
160
+ nativeBinding = require('create-s-blog-freebsd-x64')
161
+ }
162
+ } catch (e) {
163
+ loadError = e
164
+ }
165
+ break
166
+ case 'linux':
167
+ switch (arch) {
168
+ case 'x64':
169
+ if (isMusl()) {
170
+ localFileExisted = existsSync(
171
+ join(__dirname, 'create-s-blog.linux-x64-musl.node')
172
+ )
173
+ try {
174
+ if (localFileExisted) {
175
+ nativeBinding = require('./create-s-blog.linux-x64-musl.node')
176
+ } else {
177
+ nativeBinding = require('create-s-blog-linux-x64-musl')
178
+ }
179
+ } catch (e) {
180
+ loadError = e
181
+ }
182
+ } else {
183
+ localFileExisted = existsSync(
184
+ join(__dirname, 'create-s-blog.linux-x64-gnu.node')
185
+ )
186
+ try {
187
+ if (localFileExisted) {
188
+ nativeBinding = require('./create-s-blog.linux-x64-gnu.node')
189
+ } else {
190
+ nativeBinding = require('create-s-blog-linux-x64-gnu')
191
+ }
192
+ } catch (e) {
193
+ loadError = e
194
+ }
195
+ }
196
+ break
197
+ case 'arm64':
198
+ if (isMusl()) {
199
+ localFileExisted = existsSync(
200
+ join(__dirname, 'create-s-blog.linux-arm64-musl.node')
201
+ )
202
+ try {
203
+ if (localFileExisted) {
204
+ nativeBinding = require('./create-s-blog.linux-arm64-musl.node')
205
+ } else {
206
+ nativeBinding = require('create-s-blog-linux-arm64-musl')
207
+ }
208
+ } catch (e) {
209
+ loadError = e
210
+ }
211
+ } else {
212
+ localFileExisted = existsSync(
213
+ join(__dirname, 'create-s-blog.linux-arm64-gnu.node')
214
+ )
215
+ try {
216
+ if (localFileExisted) {
217
+ nativeBinding = require('./create-s-blog.linux-arm64-gnu.node')
218
+ } else {
219
+ nativeBinding = require('create-s-blog-linux-arm64-gnu')
220
+ }
221
+ } catch (e) {
222
+ loadError = e
223
+ }
224
+ }
225
+ break
226
+ case 'arm':
227
+ if (isMusl()) {
228
+ localFileExisted = existsSync(
229
+ join(__dirname, 'create-s-blog.linux-arm-musleabihf.node')
230
+ )
231
+ try {
232
+ if (localFileExisted) {
233
+ nativeBinding = require('./create-s-blog.linux-arm-musleabihf.node')
234
+ } else {
235
+ nativeBinding = require('create-s-blog-linux-arm-musleabihf')
236
+ }
237
+ } catch (e) {
238
+ loadError = e
239
+ }
240
+ } else {
241
+ localFileExisted = existsSync(
242
+ join(__dirname, 'create-s-blog.linux-arm-gnueabihf.node')
243
+ )
244
+ try {
245
+ if (localFileExisted) {
246
+ nativeBinding = require('./create-s-blog.linux-arm-gnueabihf.node')
247
+ } else {
248
+ nativeBinding = require('create-s-blog-linux-arm-gnueabihf')
249
+ }
250
+ } catch (e) {
251
+ loadError = e
252
+ }
253
+ }
254
+ break
255
+ case 'riscv64':
256
+ if (isMusl()) {
257
+ localFileExisted = existsSync(
258
+ join(__dirname, 'create-s-blog.linux-riscv64-musl.node')
259
+ )
260
+ try {
261
+ if (localFileExisted) {
262
+ nativeBinding = require('./create-s-blog.linux-riscv64-musl.node')
263
+ } else {
264
+ nativeBinding = require('create-s-blog-linux-riscv64-musl')
265
+ }
266
+ } catch (e) {
267
+ loadError = e
268
+ }
269
+ } else {
270
+ localFileExisted = existsSync(
271
+ join(__dirname, 'create-s-blog.linux-riscv64-gnu.node')
272
+ )
273
+ try {
274
+ if (localFileExisted) {
275
+ nativeBinding = require('./create-s-blog.linux-riscv64-gnu.node')
276
+ } else {
277
+ nativeBinding = require('create-s-blog-linux-riscv64-gnu')
278
+ }
279
+ } catch (e) {
280
+ loadError = e
281
+ }
282
+ }
283
+ break
284
+ case 's390x':
285
+ localFileExisted = existsSync(
286
+ join(__dirname, 'create-s-blog.linux-s390x-gnu.node')
287
+ )
288
+ try {
289
+ if (localFileExisted) {
290
+ nativeBinding = require('./create-s-blog.linux-s390x-gnu.node')
291
+ } else {
292
+ nativeBinding = require('create-s-blog-linux-s390x-gnu')
293
+ }
294
+ } catch (e) {
295
+ loadError = e
296
+ }
297
+ break
298
+ default:
299
+ throw new Error(`Unsupported architecture on Linux: ${arch}`)
300
+ }
301
+ break
302
+ default:
303
+ throw new Error(`Unsupported OS: ${platform}, architecture: ${arch}`)
304
+ }
305
+
306
+ if (!nativeBinding) {
307
+ if (loadError) {
308
+ throw loadError
309
+ }
310
+ throw new Error(`Failed to load native binding`)
311
+ }
312
+
313
+ const { scaffoldBlog, cleanupBlog } = nativeBinding
314
+
315
+ module.exports.scaffoldBlog = scaffoldBlog
316
+ module.exports.cleanupBlog = cleanupBlog
package/index.d.ts ADDED
@@ -0,0 +1,16 @@
1
+ /* tslint:disable */
2
+ /* eslint-disable */
3
+
4
+ /* auto-generated by NAPI-RS */
5
+
6
+ export interface JsScaffoldInput {
7
+ targetDir: string
8
+ templateDir: string
9
+ name: string
10
+ description: string
11
+ author: string
12
+ siteUrl?: string
13
+ timezone?: string
14
+ }
15
+ export declare function scaffoldBlog(input: JsScaffoldInput): void
16
+ export declare function cleanupBlog(targetDir: string): void
package/package.json ADDED
@@ -0,0 +1,62 @@
1
+ {
2
+ "name": "create-spage",
3
+ "version": "0.6.0",
4
+ "type": "module",
5
+ "bin": {
6
+ "create-spage": "./dist/index.js"
7
+ },
8
+ "files": [
9
+ "dist/",
10
+ "index.cjs",
11
+ "index.d.ts"
12
+ ],
13
+ "napi": {
14
+ "name": "create-spage",
15
+ "triples": {
16
+ "defaults": false,
17
+ "additional": [
18
+ "x86_64-pc-windows-msvc",
19
+ "x86_64-unknown-linux-gnu",
20
+ "aarch64-apple-darwin"
21
+ ]
22
+ }
23
+ },
24
+ "scripts": {
25
+ "build": "tsc",
26
+ "build:rs": "npx @napi-rs/cli build --platform --release",
27
+ "dev": "tsc --watch",
28
+ "prepublishOnly": "bun run build"
29
+ },
30
+ "dependencies": {
31
+ "prompts": "^2.4.2",
32
+ "kolorist": "^1.8.0",
33
+ "minimist": "^1.2.8"
34
+ },
35
+ "devDependencies": {
36
+ "@napi-rs/cli": "^2.18.0",
37
+ "@types/prompts": "^2.4.9",
38
+ "@types/minimist": "^1.2.5",
39
+ "@types/node": "^24.10.1",
40
+ "typescript": "~5.9.3"
41
+ },
42
+ "optionalDependencies": {
43
+ "create-spage-win32-x64-msvc": "0.6.0",
44
+ "create-spage-linux-x64-gnu": "0.6.0",
45
+ "create-spage-darwin-arm64": "0.6.0"
46
+ },
47
+ "keywords": [
48
+ "blog",
49
+ "scaffold",
50
+ "create",
51
+ "spage"
52
+ ],
53
+ "license": "MIT",
54
+ "repository": {
55
+ "type": "git",
56
+ "url": "https://github.com/Suzichen/spage.git"
57
+ },
58
+ "bugs": {
59
+ "url": "https://github.com/Suzichen/spage/issues"
60
+ },
61
+ "homepage": "https://spage.me"
62
+ }