create-what 0.8.1 → 0.8.3

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.
Files changed (2) hide show
  1. package/index.js +55 -37
  2. package/package.json +3 -3
package/index.js CHANGED
@@ -6,8 +6,8 @@
6
6
  // npx create-what my-app
7
7
  // npx create-what my-app --yes (skip prompts, use defaults)
8
8
 
9
- import { mkdirSync, writeFileSync, existsSync } from 'node:fs';
10
- import { join } from 'node:path';
9
+ import { mkdirSync, writeFileSync, existsSync, readFileSync } from 'node:fs';
10
+ import { basename, resolve } from 'node:path';
11
11
  import { createInterface } from 'node:readline';
12
12
 
13
13
  // ---------------------------------------------------------------------------
@@ -17,6 +17,23 @@ const args = process.argv.slice(2);
17
17
  const positional = args.filter(a => !a.startsWith('-'));
18
18
  const flags = new Set(args.filter(a => a.startsWith('-')));
19
19
  const skipPrompts = flags.has('--yes') || flags.has('-y');
20
+ const showHelp = flags.has('--help') || flags.has('-h');
21
+ const packageVersion = JSON.parse(readFileSync(new URL('./package.json', import.meta.url), 'utf8')).version;
22
+ const whatVersionRange = `^${packageVersion}`;
23
+
24
+ if (showHelp) {
25
+ console.log(`
26
+ create-what - scaffold a What Framework project
27
+
28
+ Usage:
29
+ create-what [project-name] [options]
30
+
31
+ Options:
32
+ -y, --yes Skip prompts and use defaults
33
+ -h, --help Show this help message
34
+ `);
35
+ process.exit(0);
36
+ }
20
37
 
21
38
  // ---------------------------------------------------------------------------
22
39
  // Prompt helpers (zero-dependency, uses Node readline)
@@ -121,20 +138,20 @@ async function gatherOptions() {
121
138
  // File generators
122
139
  // ---------------------------------------------------------------------------
123
140
 
124
- function generatePackageJson(projectName, { reactCompat, cssApproach }) {
141
+ function generatePackageJson(packageName, { reactCompat, cssApproach }) {
125
142
  const deps = {
126
- 'what-framework': '^0.6.0',
143
+ 'what-framework': whatVersionRange,
127
144
  };
128
145
  const devDeps = {
129
146
  vite: '^6.0.0',
130
- 'what-compiler': '^0.6.0',
131
- 'what-devtools-mcp': '^0.6.0',
147
+ 'what-compiler': whatVersionRange,
148
+ 'what-devtools-mcp': whatVersionRange,
132
149
  '@babel/core': '^7.23.0',
133
150
  };
134
151
 
135
152
  if (reactCompat) {
136
- deps['what-react'] = '^0.1.0';
137
- deps['what-core'] = '^0.6.0';
153
+ deps['what-react'] = whatVersionRange;
154
+ deps['what-core'] = whatVersionRange;
138
155
  // Include zustand as a demo React library
139
156
  deps['zustand'] = '^5.0.0';
140
157
  }
@@ -150,7 +167,7 @@ function generatePackageJson(projectName, { reactCompat, cssApproach }) {
150
167
  }
151
168
 
152
169
  return JSON.stringify({
153
- name: projectName,
170
+ name: packageName,
154
171
  private: true,
155
172
  version: '0.1.0',
156
173
  type: 'module',
@@ -214,13 +231,13 @@ export default defineConfig({
214
231
  return config;
215
232
  }
216
233
 
217
- function generateIndexHtml(projectName) {
234
+ function generateIndexHtml(packageName) {
218
235
  return `<!doctype html>
219
236
  <html lang="en">
220
237
  <head>
221
238
  <meta charset="UTF-8" />
222
239
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
223
- <title>${projectName}</title>
240
+ <title>${packageName}</title>
224
241
  <link rel="icon" type="image/svg+xml" href="/favicon.svg" />
225
242
  <link rel="stylesheet" href="/src/styles.css" />
226
243
  </head>
@@ -790,7 +807,7 @@ output {
790
807
  `;
791
808
  }
792
809
 
793
- function generateReadme(projectName, { reactCompat, cssApproach }) {
810
+ function generateReadme(packageName, { reactCompat, cssApproach }) {
794
811
  let notes = `- Canonical package name is \`what-framework\`.
795
812
  - Uses the What compiler for JSX transforms and automatic reactivity.
796
813
  - Vite is preconfigured; use \`npm run dev/build/preview\`.
@@ -813,7 +830,7 @@ function generateReadme(projectName, { reactCompat, cssApproach }) {
813
830
  - StyleX is configured via \`vite-plugin-stylex\`. Define styles with \`stylex.create()\` and apply with \`{...stylex.props()}\`.`;
814
831
  }
815
832
 
816
- return `# ${projectName}
833
+ return `# ${packageName}
817
834
 
818
835
  ## Run
819
836
 
@@ -837,17 +854,18 @@ async function main() {
837
854
  const options = await gatherOptions();
838
855
  const { projectName, reactCompat, cssApproach } = options;
839
856
 
840
- const root = join(process.cwd(), projectName);
857
+ const root = resolve(process.cwd(), projectName);
858
+ const packageName = basename(root);
841
859
 
842
860
  if (existsSync(root)) {
843
- console.error(`\nError: "${projectName}" already exists.`);
861
+ console.error(`\nError: "${root}" already exists.`);
844
862
  process.exit(1);
845
863
  }
846
864
 
847
- mkdirSync(join(root, 'src'), { recursive: true });
848
- mkdirSync(join(root, 'public'), { recursive: true });
865
+ mkdirSync(resolve(root, 'src'), { recursive: true });
866
+ mkdirSync(resolve(root, 'public'), { recursive: true });
849
867
  // MCP DevTools config — lets AI agents (Claude Code, Cursor, etc.) connect to the running app
850
- writeFileSync(join(root, '.mcp.json'), JSON.stringify({
868
+ writeFileSync(resolve(root, '.mcp.json'), JSON.stringify({
851
869
  mcpServers: {
852
870
  'what-devtools-mcp': {
853
871
  command: 'npx',
@@ -857,7 +875,7 @@ async function main() {
857
875
  }, null, 2) + '\n');
858
876
 
859
877
  // CLAUDE.md — agent instructions for Claude Code (also useful for other AI tools)
860
- writeFileSync(join(root, 'CLAUDE.md'), `# ${projectName}
878
+ writeFileSync(resolve(root, 'CLAUDE.md'), `# ${packageName}
861
879
 
862
880
  Built with What Framework — signal-based reactivity, components run once.
863
881
 
@@ -987,7 +1005,7 @@ If dep graph shows an edge but diff shows 0 re-runs, the effect lost its subscri
987
1005
  `);
988
1006
 
989
1007
  // AGENTS.md — model-agnostic instructions for OpenCode, Codex, Gemini, Cursor, etc.
990
- writeFileSync(join(root, 'AGENTS.md'), `# ${projectName} — Agent Instructions
1008
+ writeFileSync(resolve(root, 'AGENTS.md'), `# ${packageName} — Agent Instructions
991
1009
 
992
1010
  > Model-agnostic guide for AI agents using MCP DevTools with What Framework.
993
1011
 
@@ -1051,8 +1069,8 @@ count(c => c + 1) // update
1051
1069
  `);
1052
1070
 
1053
1071
  // Also generate a .cursor/mcp.json for Cursor users
1054
- mkdirSync(join(root, '.cursor'), { recursive: true });
1055
- writeFileSync(join(root, '.cursor', 'mcp.json'), JSON.stringify({
1072
+ mkdirSync(resolve(root, '.cursor'), { recursive: true });
1073
+ writeFileSync(resolve(root, '.cursor', 'mcp.json'), JSON.stringify({
1056
1074
  mcpServers: {
1057
1075
  'what-devtools-mcp': {
1058
1076
  command: 'npx',
@@ -1062,16 +1080,16 @@ count(c => c + 1) // update
1062
1080
  }, null, 2) + '\n');
1063
1081
 
1064
1082
  // .gitignore
1065
- writeFileSync(join(root, '.gitignore'), `node_modules\ndist\n.DS_Store\n`);
1083
+ writeFileSync(resolve(root, '.gitignore'), `node_modules\ndist\n.DS_Store\n`);
1066
1084
 
1067
1085
  // package.json
1068
- writeFileSync(join(root, 'package.json'), generatePackageJson(projectName, options));
1086
+ writeFileSync(resolve(root, 'package.json'), generatePackageJson(packageName, options));
1069
1087
 
1070
1088
  // index.html
1071
- writeFileSync(join(root, 'index.html'), generateIndexHtml(projectName));
1089
+ writeFileSync(resolve(root, 'index.html'), generateIndexHtml(packageName));
1072
1090
 
1073
1091
  // favicon
1074
- writeFileSync(join(root, 'public', 'favicon.svg'), `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
1092
+ writeFileSync(resolve(root, 'public', 'favicon.svg'), `<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 64 64">
1075
1093
  <defs>
1076
1094
  <linearGradient id="g" x1="0" x2="1" y1="0" y2="1">
1077
1095
  <stop offset="0%" stop-color="#2563eb" />
@@ -1084,10 +1102,10 @@ count(c => c + 1) // update
1084
1102
  `);
1085
1103
 
1086
1104
  // vite.config.js
1087
- writeFileSync(join(root, 'vite.config.js'), generateViteConfig(options));
1105
+ writeFileSync(resolve(root, 'vite.config.js'), generateViteConfig(options));
1088
1106
 
1089
1107
  // tsconfig.json
1090
- writeFileSync(join(root, 'tsconfig.json'), JSON.stringify({
1108
+ writeFileSync(resolve(root, 'tsconfig.json'), JSON.stringify({
1091
1109
  compilerOptions: {
1092
1110
  target: 'ES2022',
1093
1111
  module: 'ESNext',
@@ -1107,32 +1125,32 @@ count(c => c + 1) // update
1107
1125
  }, null, 2) + '\n');
1108
1126
 
1109
1127
  // .vscode
1110
- mkdirSync(join(root, '.vscode'), { recursive: true });
1128
+ mkdirSync(resolve(root, '.vscode'), { recursive: true });
1111
1129
 
1112
- writeFileSync(join(root, '.vscode', 'settings.json'), JSON.stringify({
1130
+ writeFileSync(resolve(root, '.vscode', 'settings.json'), JSON.stringify({
1113
1131
  'typescript.tsdk': 'node_modules/typescript/lib',
1114
1132
  'editor.formatOnSave': true,
1115
1133
  }, null, 2) + '\n');
1116
1134
 
1117
- writeFileSync(join(root, '.vscode', 'extensions.json'), JSON.stringify({
1135
+ writeFileSync(resolve(root, '.vscode', 'extensions.json'), JSON.stringify({
1118
1136
  recommendations: [],
1119
1137
  }, null, 2) + '\n');
1120
1138
 
1121
1139
  // src/main.jsx
1122
- writeFileSync(join(root, 'src', 'main.jsx'), generateMainJsx(options));
1140
+ writeFileSync(resolve(root, 'src', 'main.jsx'), generateMainJsx(options));
1123
1141
 
1124
1142
  // src/styles.css
1125
1143
  if (reactCompat && cssApproach === 'none') {
1126
- writeFileSync(join(root, 'src', 'styles.css'), generateStylesWithReactCompat());
1144
+ writeFileSync(resolve(root, 'src', 'styles.css'), generateStylesWithReactCompat());
1127
1145
  } else {
1128
- writeFileSync(join(root, 'src', 'styles.css'), generateStyles(options));
1146
+ writeFileSync(resolve(root, 'src', 'styles.css'), generateStyles(options));
1129
1147
  }
1130
1148
 
1131
1149
  // README.md
1132
- writeFileSync(join(root, 'README.md'), generateReadme(projectName, options));
1150
+ writeFileSync(resolve(root, 'README.md'), generateReadme(packageName, options));
1133
1151
 
1134
1152
  // Summary
1135
- console.log(`\nCreated ${projectName}.`);
1153
+ console.log(`\nCreated ${root}.`);
1136
1154
 
1137
1155
  const features = [];
1138
1156
  if (reactCompat) features.push('React compat (what-react + zustand demo)');
@@ -1143,7 +1161,7 @@ count(c => c + 1) // update
1143
1161
  }
1144
1162
 
1145
1163
  console.log('\nNext steps:');
1146
- console.log(` cd ${projectName}`);
1164
+ console.log(` cd ${root}`);
1147
1165
  console.log(' npm install');
1148
1166
  console.log(' npm run dev\n');
1149
1167
  }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "create-what",
3
- "version": "0.8.1",
3
+ "version": "0.8.3",
4
4
  "description": "Scaffold a new What Framework project",
5
5
  "type": "module",
6
6
  "bin": {
7
- "create-what": "./index.js"
7
+ "create-what": "index.js"
8
8
  },
9
9
  "main": "index.js",
10
10
  "files": [
@@ -20,7 +20,7 @@
20
20
  "license": "MIT",
21
21
  "repository": {
22
22
  "type": "git",
23
- "url": "https://github.com/CelsianJs/what-framework"
23
+ "url": "git+https://github.com/CelsianJs/what-framework.git"
24
24
  },
25
25
  "bugs": {
26
26
  "url": "https://github.com/CelsianJs/what-framework/issues"