@stratawp/cli 0.2.2 → 0.3.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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ GNU GENERAL PUBLIC LICENSE
2
+ Version 3, 29 June 2007
3
+
4
+ Copyright (C) 2024 Jon Imms
5
+
6
+ This program is free software: you can redistribute it and/or modify
7
+ it under the terms of the GNU General Public License as published by
8
+ the Free Software Foundation, either version 3 of the License, or
9
+ (at your option) any later version.
10
+
11
+ This program is distributed in the hope that it will be useful,
12
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
13
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
+ GNU General Public License for more details.
15
+
16
+ You should have received a copy of the GNU General Public License
17
+ along with this program. If not, see <https://www.gnu.org/licenses/>.
18
+
19
+ ---
20
+
21
+ For the full GPL-3.0 license text, see: https://www.gnu.org/licenses/gpl-3.0.txt
package/dist/create.js CHANGED
@@ -7,6 +7,7 @@ import ora from "ora";
7
7
  import { execa } from "execa";
8
8
  import fs from "fs-extra";
9
9
  import path from "path";
10
+ import os from "os";
10
11
  import validatePackageName from "validate-npm-package-name";
11
12
  async function main() {
12
13
  console.log(chalk.bold.cyan("\n\u26A1 Create StrataWP Theme\n"));
@@ -93,6 +94,7 @@ async function createTheme(config) {
93
94
  spinner.text = "Installing dependencies...";
94
95
  await execa("pnpm", ["install"], { cwd: themePath });
95
96
  spinner.succeed(chalk.green("Theme created successfully!"));
97
+ await offerWordPressLinking(themePath, config.slug);
96
98
  console.log(chalk.cyan("\n\u{1F4E6} Next steps:\n"));
97
99
  console.log(` cd ${config.slug}`);
98
100
  console.log(" pnpm dev");
@@ -103,6 +105,99 @@ async function createTheme(config) {
103
105
  process.exit(1);
104
106
  }
105
107
  }
108
+ async function offerWordPressLinking(themePath, slug) {
109
+ console.log();
110
+ const { shouldLink } = await prompts({
111
+ type: "confirm",
112
+ name: "shouldLink",
113
+ message: "Would you like to link this theme to a WordPress installation?",
114
+ initial: true
115
+ });
116
+ if (!shouldLink) {
117
+ return;
118
+ }
119
+ const wordpressSites = await detectWordPressSites();
120
+ if (wordpressSites.length === 0) {
121
+ console.log(chalk.yellow("\n\u26A0\uFE0F No WordPress installations detected automatically."));
122
+ console.log(chalk.dim("You can manually create a symlink later:\n"));
123
+ console.log(chalk.dim(` ln -s "${themePath}" /path/to/wordpress/wp-content/themes/${slug}
124
+ `));
125
+ return;
126
+ }
127
+ const { selectedSite } = await prompts({
128
+ type: "select",
129
+ name: "selectedSite",
130
+ message: "Select WordPress installation:",
131
+ choices: wordpressSites.map((site) => ({
132
+ title: `${site.name} (${site.type})`,
133
+ description: site.path,
134
+ value: site
135
+ }))
136
+ });
137
+ if (!selectedSite) {
138
+ return;
139
+ }
140
+ try {
141
+ const targetPath = path.join(selectedSite.path, "wp-content", "themes", slug);
142
+ if (await fs.pathExists(targetPath)) {
143
+ console.log(chalk.yellow(`
144
+ \u26A0\uFE0F Theme already exists at ${targetPath}`));
145
+ return;
146
+ }
147
+ await fs.ensureSymlink(themePath, targetPath);
148
+ console.log(chalk.green(`
149
+ \u2713 Linked theme to ${selectedSite.name}`));
150
+ console.log(chalk.dim(` ${targetPath}`));
151
+ } catch (error) {
152
+ console.log(chalk.red("\n\u2716 Failed to create symlink"));
153
+ console.log(chalk.dim("You can manually create it:\n"));
154
+ console.log(chalk.dim(` ln -s "${themePath}" ${path.join(selectedSite.path, "wp-content", "themes", slug)}
155
+ `));
156
+ }
157
+ }
158
+ async function detectWordPressSites() {
159
+ const sites = [];
160
+ const homeDir = os.homedir();
161
+ const localSitesPath = path.join(homeDir, "Local Sites");
162
+ if (await fs.pathExists(localSitesPath)) {
163
+ try {
164
+ const localDirs = await fs.readdir(localSitesPath);
165
+ for (const dir of localDirs) {
166
+ const sitePath = path.join(localSitesPath, dir, "app", "public");
167
+ const wpConfigPath = path.join(sitePath, "wp-config.php");
168
+ if (await fs.pathExists(wpConfigPath)) {
169
+ sites.push({
170
+ name: dir,
171
+ path: sitePath,
172
+ type: "Local by Flywheel"
173
+ });
174
+ }
175
+ }
176
+ } catch (error) {
177
+ }
178
+ }
179
+ if (process.platform === "darwin") {
180
+ const mampPath = "/Applications/MAMP/htdocs";
181
+ if (await fs.pathExists(mampPath)) {
182
+ try {
183
+ const mampDirs = await fs.readdir(mampPath);
184
+ for (const dir of mampDirs) {
185
+ const sitePath = path.join(mampPath, dir);
186
+ const wpConfigPath = path.join(sitePath, "wp-config.php");
187
+ if (await fs.pathExists(wpConfigPath)) {
188
+ sites.push({
189
+ name: dir,
190
+ path: sitePath,
191
+ type: "MAMP"
192
+ });
193
+ }
194
+ }
195
+ } catch (error) {
196
+ }
197
+ }
198
+ }
199
+ return sites;
200
+ }
106
201
  async function createBasicStructure(themePath, config) {
107
202
  const packageJson = {
108
203
  name: config.slug,
package/dist/index.js CHANGED
@@ -2,7 +2,6 @@
2
2
 
3
3
  // src/index.ts
4
4
  import { Command } from "commander";
5
- import chalk10 from "chalk";
6
5
 
7
6
  // src/commands/dev.ts
8
7
  import chalk from "chalk";
@@ -957,6 +956,20 @@ async function createCSSEntry(framework, cwd) {
957
956
  }
958
957
 
959
958
  // src/index.ts
959
+ import {
960
+ setupCommand,
961
+ generateCommand,
962
+ reviewCommand,
963
+ documentCommand
964
+ } from "@stratawp/ai";
965
+ import {
966
+ searchCommand,
967
+ installCommand,
968
+ infoCommand,
969
+ publishCommand,
970
+ listCommand
971
+ } from "@stratawp/registry";
972
+ import { startCommand as explorerStartCommand } from "@stratawp/explorer";
960
973
  var program = new Command();
961
974
  program.name("stratawp").description("\u26A1 A modern WordPress theme framework").version("0.2.2");
962
975
  program.command("dev").description("Start development server with hot reload").option("-p, --port <port>", "Port number", "3000").option("-h, --host <host>", "Host address", "localhost").action(devCommand);
@@ -967,17 +980,40 @@ program.command("template:new <name>").description("Create a new WordPress templ
967
980
  program.command("part:new <name>").description("Create a new template part").option("-t, --type <type>", "Part type (header|footer|sidebar|content|custom)", "custom").option("--markup <markup>", "Markup style (html|php)", "php").action(partCommand);
968
981
  program.command("design-system:setup <framework>").description("Set up a design system (tailwind|unocss)").action(designSystemCommand);
969
982
  program.command("test").description("Run tests").option("--unit", "Run unit tests only").option("--e2e", "Run E2E tests only").option("--watch", "Watch mode").action(testCommand);
970
- program.command("storybook").description("Launch component explorer").action(() => {
971
- console.log(chalk10.cyan("\u{1F3AD} Launching component explorer..."));
972
- console.log(chalk10.dim("Coming soon!"));
983
+ program.command("explorer").description("Launch interactive component explorer").option("-p, --port <port>", "Port number", "3000").option("-h, --host <host>", "Host address", "localhost").option("--no-open", "Do not open browser automatically").action((options) => {
984
+ explorerStartCommand({
985
+ port: options.port ? parseInt(options.port, 10) : 3e3,
986
+ host: options.host,
987
+ open: options.open !== false
988
+ });
973
989
  });
974
- program.command("ai:block <description>").description("Generate block from description using AI").action((description) => {
975
- console.log(chalk10.magenta("\u{1F916} AI Block Generator"));
976
- console.log(chalk10.dim(`Description: ${description}`));
977
- console.log(chalk10.yellow("\u26A0\uFE0F Coming soon!"));
990
+ program.command("storybook").description("Alias for explorer command").option("-p, --port <port>", "Port number", "3000").option("-h, --host <host>", "Host address", "localhost").option("--no-open", "Do not open browser automatically").action((options) => {
991
+ explorerStartCommand({
992
+ port: options.port ? parseInt(options.port, 10) : 3e3,
993
+ host: options.host,
994
+ open: options.open !== false
995
+ });
978
996
  });
979
- program.command("ai:optimize").description("AI-powered performance optimization").action(() => {
980
- console.log(chalk10.magenta("\u{1F916} AI Optimizer"));
981
- console.log(chalk10.yellow("\u26A0\uFE0F Coming soon!"));
997
+ program.command("ai:setup").description("Configure AI providers and API keys").action(setupCommand);
998
+ program.command("ai:generate <type>").description("Generate code with AI (block|component|pattern)").option("-o, --output <path>", "Output file path").action((type, options) => {
999
+ generateCommand({ type, ...options });
982
1000
  });
1001
+ program.command("ai:review <file>").description("Review code for best practices and security").option("-f, --focus <focus>", "Focus area (security|performance|best-practices|all)", "all").action((file, options) => {
1002
+ reviewCommand({ file, ...options });
1003
+ });
1004
+ program.command("ai:document <file>").description("Generate documentation for code").option("-o, --output <path>", "Output file path").option("-f, --format <format>", "Documentation format (markdown|phpdoc|jsdoc)").action((file, options) => {
1005
+ documentCommand({ file, ...options });
1006
+ });
1007
+ program.command("registry:search <query>").description("Search for components in the registry").option("-t, --type <type>", "Filter by component type (block|component|pattern|template)").option("-l, --limit <number>", "Maximum number of results", "20").action((query, options) => {
1008
+ searchCommand(query, {
1009
+ type: options.type,
1010
+ limit: parseInt(options.limit, 10)
1011
+ });
1012
+ });
1013
+ program.command("registry:install <component>").description("Install a component from the registry").option("-v, --version <version>", "Specific version to install").option("-f, --force", "Overwrite if component already exists").option("-d, --dev", "Install as dev dependency").option("--target-dir <dir>", "Custom target directory").action((component, options) => {
1014
+ installCommand(component, options);
1015
+ });
1016
+ program.command("registry:info <component>").description("Get detailed information about a component").action(infoCommand);
1017
+ program.command("registry:publish").description("Publish current component to the registry").option("--tag <tag>", "Publish with a specific tag").option("--access <access>", "Public or restricted access", "public").option("--dry-run", "Test publication without actually publishing").action(publishCommand);
1018
+ program.command("registry:list").description("List installed StrataWP components").action(listCommand);
983
1019
  program.parse();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@stratawp/cli",
3
- "version": "0.2.2",
3
+ "version": "0.3.0",
4
4
  "description": "CLI tool for StrataWP - create and manage WordPress themes",
5
5
  "author": "Jon Imms",
6
6
  "license": "GPL-3.0-or-later",
@@ -39,13 +39,6 @@
39
39
  "dist",
40
40
  "templates"
41
41
  ],
42
- "scripts": {
43
- "dev": "tsup --watch",
44
- "build": "tsup",
45
- "test": "vitest",
46
- "lint": "eslint src",
47
- "clean": "rm -rf dist"
48
- },
49
42
  "dependencies": {
50
43
  "chalk": "^5.3.0",
51
44
  "commander": "^11.1.0",
@@ -54,7 +47,10 @@
54
47
  "fs-extra": "^11.2.0",
55
48
  "ora": "^8.0.1",
56
49
  "prompts": "^2.4.2",
57
- "validate-npm-package-name": "^5.0.0"
50
+ "validate-npm-package-name": "^5.0.0",
51
+ "@stratawp/ai": "0.1.0",
52
+ "@stratawp/explorer": "0.7.0",
53
+ "@stratawp/registry": "0.1.0"
58
54
  },
59
55
  "devDependencies": {
60
56
  "@types/fs-extra": "^11.0.4",
@@ -63,5 +59,12 @@
63
59
  "tsup": "^8.0.1",
64
60
  "typescript": "^5.3.3",
65
61
  "vitest": "^1.0.4"
62
+ },
63
+ "scripts": {
64
+ "dev": "tsup --watch",
65
+ "build": "tsup",
66
+ "test": "vitest",
67
+ "lint": "eslint src",
68
+ "clean": "rm -rf dist"
66
69
  }
67
- }
70
+ }